This document describes the decentralized testing architecture for the OADP CLI.
Tests are organized following Go best practices - they live next to the code they test:
├── cmd/
│ ├── root_test.go # Root command tests
│ ├── nabsl/
│ │ ├── nabsl.go
│ │ └── nabsl_test.go # NABSL command tests
│ └── non-admin/
│ ├── nonadmin_test.go # Non-admin command tests
│ └── bsl/
│ ├── bsl.go
│ └── bsl_test.go # BSL command tests
├── internal/
│ └── testutil/
│ └── testutil.go # Shared test utilities
└── integration_test.go # Integration tests
Located next to the source code they test:
cmd/root_test.go: Tests root command functionality, help text, basic structurecmd/nabsl/nabsl_test.go: Tests NABSL commands (approve, reject, get, describe)cmd/non-admin/nonadmin_test.go: Tests non-admin command structurecmd/non-admin/bsl/bsl_test.go: Tests BSL creation, credential handling
Located at the project root in integration_test.go:
- Binary Build: Tests that the CLI binary builds successfully
- Makefile Integration: Tests installation options and build system
- Client Config: Tests end-to-end client configuration workflow
- Command Architecture: Tests overall command structure and relationships
Located in internal/testutil/:
BuildCLIBinary(): Builds test binary with proper cleanupRunCommand(): Executes CLI commands with timeout and loggingTestHelpCommand(): Validates help text contains expected contentSetupTempHome(): Creates isolated test environment for client config
make testmake test-unitmake test-integration# Test specific command
go test ./cmd/nabsl-request -v
# Test with coverage
go test ./cmd/... -cover- ✅ Command help text and structure
- ✅ Flag definitions and validation
- ✅ Subcommand availability
- ✅ Help flag consistency (
--helpand-h) - ✅ Command architecture changes
- ✅ Binary builds successfully
- ✅ Makefile installation options work
- ✅ Client configuration end-to-end
- ✅ Cross-command functionality
- ✅ Overall system behavior
- Tests live next to the code they test
- Easy to find and maintain
- Clear ownership and responsibility
- Each test file has a narrow, clear scope
- Faster test execution for specific areas
- Better isolation of test failures
- Tests can run in parallel across packages
- Better CI/CD performance
- Independent test environments
- When code changes, related tests are immediately visible
- Easier to keep tests in sync with code
- Reduced cognitive overhead
- Create
*_test.gofile in the same package as your command - Import
"github.com/migtools/oadp-cli/internal/testutil" - Follow existing patterns for help text validation
- Add tests to
integration_test.go - Use
testutil.BuildCLIBinary()for binary-based tests - Focus on cross-package functionality
func TestNewCommand(t *testing.T) {
binaryPath := testutil.BuildCLIBinary(t)
tests := []struct {
name string
args []string
expectContains []string
}{
{
name: "command help",
args: []string{"newcommand", "--help"},
expectContains: []string{"expected text"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
testutil.TestHelpCommand(t, binaryPath, tt.args, tt.expectContains)
})
}
}- Use testutil helpers for common operations
- Test help text to verify command structure
- Use table-driven tests for multiple scenarios
- Keep tests focused on single responsibilities
- Mock external dependencies when possible
- Use descriptive test names that explain what's being tested
This testing architecture ensures comprehensive coverage while maintaining clarity and ease of maintenance.
The make install command includes intelligent namespace detection that automatically discovers where OADP is deployed in your cluster:
- OADP Controller Detection: Looks for
openshift-adp-controller-managerdeployment - DPA Resource Detection: Searches for
DataProtectionApplicationcustom resources - Velero Fallback: Falls back to looking for
velerodeployment - Interactive Prompt: If no resources found, prompts for manual input
# Smart detection + interactive prompt (default)
make install
# Skip detection, use default namespace
make install ASSUME_DEFAULT=true
# Skip detection, use custom namespace
make install VELERO_NAMESPACE=my-oadp-namespaceThis intelligent detection eliminates the guesswork of finding the correct OADP namespace in your cluster.