Testing
The Perses Operator uses unit, integration, end-to-end (e2e), and alerting rule tests.
Some test commands use tools installed locally under bin/. Run make build-tools to install all tools, or let the Makefile targets (e.g. make test-unit, make test-integration) install them automatically.
Unit Tests#
Unit tests validate individual functions and utilities using standard Go testing with testify or Ginkgo.
# Run all unit tests
make test-unit
# Run a single test by name (testify)
go test ./internal/metrics/... -run TestNewMetrics -v
# Run a single test by name (Ginkgo)
# --focus matches against Describe/It block descriptions
bin/ginkgo --focus "GetVolumes" -v ./internal/perses/common/...Integration Tests#
Integration tests use Ginkgo with envtest to spin up a lightweight API server with CRDs installed. These tests validate controller reconcile logic, CRD validation, and resource management.
# Run all integration tests
make test-integration
# Run a single integration test by name
# --focus matches against Ginkgo Describe/It block descriptions
KUBEBUILDER_ASSETS="$(bin/setup-envtest use -p path)" \
bin/ginkgo --focus "should successfully reconcile" -v ./controllers/...E2E Tests (kuttl)#
E2E tests use kuttl to validate the operator end-to-end in a real kind cluster, including deployment, resource synchronization, and cleanup.
Prerequisites#
Quick Start#
make e2e-setup # Create cluster + deploy operator
make test-e2e # Run tests
make e2e-cleanup # Tear downWhen iterating:
- Run
make e2e-setuponce to create the cluster and deploy the operator. - Run
make test-e2eto run the tests. - After code changes, run
make e2e-deployto rebuild and redeploy the operator, thenmake test-e2eagain.
Configuration#
The following Makefile variables can be overridden to customize the e2e environment:
| Variable | Default | Description |
|---|---|---|
KIND_CLUSTER_NAME | kuttl-e2e | Name of the kind cluster |
E2E_TAG | Git short SHA | Image tag for the operator |
E2E_IMG | docker.io/persesdev/perses-operator:<E2E_TAG> | Full operator image reference |
Test Structure#
Tests are under test/e2e/ following the kuttl convention. Kuttl creates a random namespace per test case for isolation. Steps run sequentially.
test/e2e/
├── kuttl-test.yaml
├── global-datasource/ # Global datasource sync
├── multi-instance-sync/ # Dashboard/datasource sync across instances
├── namespace-isolation/ # Namespace-scoped resource isolation
├── perses-deployment/ # database.sql → Deployment
├── perses-emptydir/ # emptyDir storage
├── perses-statefulset/ # database.file → StatefulSet with PVC
├── perses-volumes/ # Custom volumes and volume mounts
└── resource-update/ # Update existing resources and assert reconciliation- To add a new test case, create a directory under
test/e2e/. - To add steps to an existing test case, add numbered files (e.g.
05-install.yaml,05-assert.yaml).
Debugging#
# Operator logs
kubectl logs -n perses-operator-system deployment/perses-operator-controller-manager -f
# Run a single test case
bin/kubectl-kuttl test --config test/e2e/kuttl-test.yaml --test perses-statefulsetAlerting Rule Tests#
Alerting rules are validated using promtool. When adding or modifying rules, add corresponding test cases to test/promtool/alerts_test.yaml and run:
make test-alertsSee Developer Guide for the full workflow.
Integration vs E2E Tests#
| Aspect | Integration Tests | E2E Tests |
|---|---|---|
| Environment | Lightweight API server via envtest (no real cluster) | Real Kubernetes cluster via kind |
| Scope | Controller reconcile logic, CRD validation, status updates | Full operator lifecycle including pod scheduling and networking |
| Speed | Fast (seconds) | Slower (minutes, includes cluster setup) |
| Framework | Ginkgo + envtest | kuttl |

