Testing
Unit Tests (envtest)
make testUses controller-runtime’s envtest — a real API server + etcd, no kubelet.
Coverage report lands in cover.out.
Test Locations
| Path | What it tests |
|---|---|
internal/controller/*_test.go | Controller reconciliation logic |
internal/pacing/*_test.go | Pacing engine constraints |
internal/podbuilder/*_test.go | Pod construction correctness |
internal/discovery/*_test.go | Source implementations |
E2E Tests (Chainsaw)
make test-e2eRequires a running kind cluster with the operator deployed (Tilt handles this).
Tests live in test/e2e/ and use Kyverno Chainsaw.
Each test scenario is a directory with chainsaw-test.yaml defining steps:
- Apply a resource
- Assert expected state (status, child resources, events)
- Cleanup
Writing Tests
Table-driven (preferred)
func TestSomething(t *testing.T) {
tests := []struct {
name string
// inputs
// expected outputs
}{
{name: "happy path", ...},
{name: "error case", ...},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// arrange, act, assert
})
}
}Controller tests (envtest)
var k8sClient client.Client
var testEnv *envtest.Environment
// Setup in TestMain or BeforeSuiteCreate resources with the real client, trigger reconciliation, assert status changes.
Discovery tests (mock HTTP)
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Return mock Prometheus/Registry response
}))
defer srv.Close()
source := &PrometheusSource{Endpoint: srv.URL, ...}
results, err := source.Fetch(ctx)Adding a New Test
- Create
*_test.gonext to the code being tested - Use table-driven format with descriptive case names
- For controllers: create the CRD resource, reconcile, assert status
- For discovery: mock the HTTP endpoint, call Fetch, assert results
- Run
make testto validate
Last updated on