Change-Id: I2e2564a72b6be9af536235fc3795fd788fd9257b
9.1 KiB
Helm Chart Testing
Three test scripts are provided:
local-test.sh— Offline lint + template validation (no cluster needed)integration-test.sh— Deploy to a real Kind cluster and verify resourcesct-test.sh— Wrapper around chart-testing (ct), matching what CircleCI runs
1. Offline Tests (local-test.sh)
Runs helm lint and helm template — no cluster required.
Prerequisites
- Helm v3.x
Usage
# Test all charts
./test/local-test.sh
# Test a specific chart
./test/local-test.sh haproxy-unified-gateway
./test/local-test.sh kubernetes-ingress
What It Tests
| Test | Description |
|---|---|
| Chart.yaml metadata | Verifies required fields (name, version, appVersion, description) |
| helm lint (defaults) | Runs helm lint with default values |
| helm template (defaults) | Renders templates and checks for errors |
| Deployment vs DaemonSet | Confirms charts that support controller.kind render the correct resource type |
| HugConf cleanup hook | Verifies cleanup hook renders/skips based on hugconf.create and targets correct name |
| Metrics port | Verifies metrics container port (31060) renders, --metrics-auth flag is correct for both kube-rbac (default) and none, metrics Service has both stat and metrics ports |
| ServiceMonitor/PodMonitor | Renders with monitoring.coreos.com/v1 API, skipped without it, metrics Service only with ServiceMonitor |
| CI values (lint + template) | Lint and template for every ci/*.yaml file |
2. Integration Tests (integration-test.sh)
Installs charts into a real Kubernetes cluster, waits for pods to become Ready, verifies key resources exist, then cleans up.
By default the script creates a Kind cluster named
dev-helm-charts, runs all tests, and deletes the cluster when done.
Prerequisites
Usage
# Test all charts (creates + destroys Kind cluster automatically)
./test/integration-test.sh
# Test a specific chart
./test/integration-test.sh haproxy-unified-gateway
./test/integration-test.sh kubernetes-ingress
Environment Variables
| Variable | Default | Description |
|---|---|---|
TIMEOUT |
120 |
Max seconds to wait for pods per install |
KEEP_NS |
0 |
Set to 1 to keep test namespaces after run (for debugging) |
CI_FILTER |
(empty) | Glob pattern to filter ci/ values files (e.g. deployment-*) |
TEST_FILTER |
(empty) | Run only a specific test: defaults, daemonset, hpa, pdb, metrics-port, monitoring, hugconf-cleanup, ci |
KIND_KEEP_CLUSTER |
0 |
Set to 1 to keep the Kind cluster after tests finish |
KIND_CLUSTER_NAME |
dev-helm-charts |
Custom Kind cluster name |
SKIP_KIND |
0 |
Set to 1 to skip Kind management and use your existing kubeconfig |
Examples
# Run tests and keep the Kind cluster for manual inspection afterwards
KIND_KEEP_CLUSTER=1 ./test/integration-test.sh haproxy-unified-gateway
# Re-run tests against the cluster you kept (reuses existing cluster)
./test/integration-test.sh haproxy-unified-gateway
# Delete the cluster manually when done
kind delete cluster --name dev-helm-charts
# Use your own cluster instead of Kind
SKIP_KIND=1 ./test/integration-test.sh haproxy-unified-gateway
# Longer timeout for slow clusters
TIMEOUT=300 ./test/integration-test.sh haproxy-unified-gateway
# Only run deployment-related ci/ test cases
CI_FILTER="deployment-*" ./test/integration-test.sh haproxy-unified-gateway
# Run only the monitoring test (ServiceMonitor/PodMonitor)
TEST_FILTER=monitoring ./test/integration-test.sh haproxy-unified-gateway
# Run only the metrics port test
TEST_FILTER=metrics-port ./test/integration-test.sh haproxy-unified-gateway
# Run only the HugConf cleanup test
TEST_FILTER=hugconf-cleanup ./test/integration-test.sh haproxy-unified-gateway
# Run only the defaults test
TEST_FILTER=defaults ./test/integration-test.sh haproxy-unified-gateway
# Keep namespaces after the run for manual inspection
KEEP_NS=1 ./test/integration-test.sh haproxy-unified-gateway
# Then clean up manually when done
kubectl get ns | grep '^it-' | awk '{print $1}' | xargs kubectl delete ns
What It Tests
For each chart, the script runs these phases:
| Test | Description |
|---|---|
| Install (defaults) | helm install with default values, wait for pods, verify resources |
| Install (DaemonSet) | Same but with controller.kind=DaemonSet (if chart supports it) |
| Install (HPA) | Enables HPA, verifies HPA resource is created |
| Install (PDB) | Enables PDB, verifies PDB resource is created |
| Metrics port | Verifies controller pod has metrics container port 31060, --metrics-auth=kube-rbac arg, and main Service has stat port |
| Install (monitoring) | Installs Prometheus Operator CRDs, verifies ServiceMonitor/PodMonitor/metrics Service with both stat + metrics ports |
| HugConf cleanup | Verifies HugConf CR is deleted after helm uninstall |
| Install ci/ values | Installs with each ci/*.yaml file, waits for pods |
Each test:
- Creates an isolated namespace (
it-<chart>-<suffix>-<timestamp>) - Runs
helm install --wait - Verifies pods reach Running/Completed state
- On failure: dumps pod status, events, and container logs
- Runs
helm uninstalland deletes the namespace
On Failure
When a test fails, the script automatically prints:
- Pod status (
kubectl get pods -o wide) - Recent events (
kubectl get events) - Container logs from unhealthy pods (last 20 lines)
3. Chart Testing (ct-test.sh)
Wrapper around chart-testing (ct) — the same
tool CircleCI uses. Runs ct lint and ct install locally so you can validate before pushing.
Prerequisites
- ct v3.x
- yamale (
pipx install yamale) - yamllint (
pipx install yamllint) - Helm v3.x
- Kind — only for
installmode kubectl— only forinstallmode
ct Usage
# Lint all charts
./test/ct-test.sh lint
# Lint a specific chart
./test/ct-test.sh lint haproxy-unified-gateway
# Install all charts on a Kind cluster (creates + destroys automatically)
./test/ct-test.sh install
# Install a specific chart
./test/ct-test.sh install haproxy-unified-gateway
# Lint + install in one go
./test/ct-test.sh all haproxy-unified-gateway
ct Environment Variables
| Variable | Default | Description |
|---|---|---|
KIND_CLUSTER_NAME |
ct-dev |
Kind cluster name |
KIND_KEEP_CLUSTER |
0 |
Set to 1 to keep the Kind cluster after tests |
SKIP_KIND |
0 |
Set to 1 to skip Kind management and use existing kubeconfig |
CT_ARGS |
(empty) | Extra arguments passed to ct (e.g. --debug) |
ct Examples
# Lint with debug output
CT_ARGS="--debug" ./test/ct-test.sh lint haproxy-unified-gateway
# Install and keep cluster for inspection
KIND_KEEP_CLUSTER=1 ./test/ct-test.sh install haproxy-unified-gateway
# Use an existing cluster
SKIP_KIND=1 ./test/ct-test.sh install haproxy-unified-gateway
# Delete the cluster manually when done
kind delete cluster --name ct-dev
CircleCI Compatibility
The CircleCI pipeline (.circleci/config.yml) runs:
ct lint --all— validates Chart.yaml schema, runshelm lintwith eachci/*.yamlfilect install --all— installs each chart with eachci/*.yamlfile on a Kind cluster
ct-test.sh runs the exact same commands locally using the config in test/ct.yaml,
so if it passes locally it will pass in CI.
CI Values Files
Both scripts use the ci/ values files in each chart directory. These are the same
files used by chart-testing (ct) in CircleCI.
Naming convention:
<mode>-<feature>-values.yaml
Examples:
deployment-default-values.yaml— Deployment with defaultsdaemonset-hostport-values.yaml— DaemonSet with host port mappingdeployment-hpa-values.yaml— Deployment with HPA enabled
Adding New Test Cases
-
Create a new values file in
<chart>/ci/following the naming convention. -
Validate offline:
./test/local-test.sh <chart-name> -
Verify ct lint passes (matches CircleCI):
./test/ct-test.sh lint <chart-name> -
Deploy to a cluster:
CI_FILTER="<your-new-file>" ./test/integration-test.sh <chart-name> -
The file is automatically picked up by all three scripts and CircleCI's
ct lint.