3.5 KiB
3.5 KiB
Testing Strategy
How to test the Guildhouse SPIRE plugins.
Running Tests
make test # Run all tests
make lint # Run go vet
# Verbose output
go test -v ./...
# Single package
go test -v ./pkg/shellstream/...
# With coverage
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out
Test Structure
Unit Tests (pkg/)
Each package has *_test.go files with unit tests:
| Package | Tests | Coverage Focus |
|---|---|---|
pkg/shellstream |
~28 tests | Encode/decode round-trips, validation rules, format constraints, co-occurrence rules |
pkg/oidc |
2 tests | Config validation (scaffolded) |
pkg/governance |
2 tests | Client construction (scaffolded) |
pkg/sshcert |
3 tests | Builder config validation (scaffolded) |
pkg/config |
2 tests | Plugin config validation (scaffolded) |
pkg/shellstream Tests (Fully Implemented)
The shellstream package has comprehensive tests covering:
- Round-trip: Encode → Decode produces identical values (full and minimal)
- Required fields: Missing tenant-id, missing roles produce validation errors
- Format validation: Invalid UUID, wrong hex length, uppercase hex, invalid base64
- Co-occurrence: sat-scope without sat-hash, ceremony-id without ceremony-type, merkle-proof without merkle-root
- Parsing: JSON sat-scope, comma-separated roles, base64 merkle proof, uint64 governance epoch
- Edge cases: Epoch value 0, nil extensions, unknown extensions ignored
- Enum validation: Unknown ceremony-type rejected
Integration Test Approach (Future)
When plugin implementations are complete, integration tests will use mock gRPC servers:
// Example mock GovernanceService
type mockGovernanceServer struct {
quartermasterv1.UnimplementedGovernanceServiceServer
intents map[string]*Intent
}
func (s *mockGovernanceServer) CreateIntent(ctx context.Context, req *quartermasterv1.CreateIntentRequest) (*quartermasterv1.CreateIntentResponse, error) {
// Return predictable responses for testing
}
Integration tests will:
- Start mock gRPC servers for GovernanceService, CeremonyService, NotaryService
- Create plugin instances pointed at the mock servers
- Invoke plugin methods (Attest, Compose, Notify)
- Verify the plugin made expected gRPC calls with correct parameters
- Verify the plugin handled error conditions (unreachable service, denied intent, ceremony timeout)
Test Fixtures
Test fixture files in test/fixtures/:
| File | Purpose |
|---|---|
sample-oidc-token.json |
Example OIDC token payload for oidc-attestor testing |
sample-sat-scope.json |
Example SatScope for governance client testing |
sample-ssh-cert-extensions.json |
Example Shellstream extensions map for shellstream package testing |
spire-test-config.hcl |
Example SPIRE plugin configuration for config package testing |
Load fixtures in tests:
func loadFixture(t *testing.T, name string) []byte {
t.Helper()
data, err := os.ReadFile(filepath.Join("../../test/fixtures", name))
if err != nil {
t.Fatalf("load fixture %s: %v", name, err)
}
return data
}
CI Pipeline
# .github/workflows/test.yaml
name: Test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.23'
- run: make test
- run: make lint
- run: make build