Why Helm UnitTest?
Untested charts risk syntax errors, wrong resources, or missing configs that surface only during installs. Unit tests render templates locally, catch issues early, and ensure values like replicas or images work as expected.
CI/CD pipelines run these tests automatically, blocking merges with failures. Using helm unittest will lower prod incidents from template bugs.
Install Helm-Unittest
Prerequisites: Helm 3.8+, Git, basic YAML skills.
Install the plugin:
helm plugin install
https://github.com/helm-unittest/helm-unittest.git
helm unittest --help # Verify installation
Chart Structure
Organize your chart like this:
my-app/ ├── Chart.yaml ├── values.yaml ├── templates/ │ ├── deployment.yaml │ └── service.yaml └── tests/ └── basic_test.yaml
Write Your First Test
Create tests/basic_test.yaml:
suite: basic deployment tests
templates:
- deployment.yaml
tests:
- it: should have correct kind
asserts:
- isKind:
of: Deployment
- it: sets replicas correctly
set:
replicaCount: 3
asserts:
- equal:
path: spec.replicas
value: 3
- it: uses correct image
set:
image.repository: nginx
image.tag: "1.21"
asserts:
- equal:
path: spec.template.spec.containers[0].image
value: nginx:1.21
This suite renders deployment.yaml, applies value overrides, and verifies structure.
| Assertion | Purpose | Example |
|---|---|---|
isKind |
Check resource type | of: Deployment |
equal |
Exact path match | path: spec.replicas value: 2 |
matchSnapshot |
Full template validation | {} |
hasKey |
Field existence | path: metadata.labels.app |
matchRegex |
Pattern matching | path: metadata.name value: "^my-app-.*" |
contains |
Document count | count: 1 |
isEmpty |
No documents | {} |
fileExists |
Template presence | path: templates/deployment.yaml |
Test labels, resources, env vars, and volumes similarly.
Run Tests
From chart root:
helm unittest . # Default run helm unittest . -v # Verbose output helm unittest . --output-type junit > test-results.xml # CI reports Green output shows passes; failures list exact path mismatches.
Green output shows passes; failures list exact path mismatches.
Example verbose run:
✓ basic_test.yaml: "should have correct kind" ✓ basic_test.yaml: "sets replicas correctly"
Advanced Testing
Multiple Values Files:
- it: works with prod values values: - ../../values-prod.yaml asserts: - greater: path: spec.template.spec.containers[0].resources.limits.memory value: 1Gi
Subcharts: Prefix with subchartName//.
Conditionals: Test if blocks with varied set values.
Snapshots for golden files:
- it: matches production snapshot
set:
env: production
asserts:
- matchSnapshot: {}
Update with helm unittest . -u.
CI/CD Integration
GitHub Actions workflow (.github/workflows/test.yaml):
name: Helm Test
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: azure/setup-helm@v4
with:
version: v3.15.0
- run: helm plugin install https://github.com/helm-unittest/helm-unittest
- run: helm unittest . --output-type junit > junit.xml
- uses: actions/upload-artifact@v4
with:
name: test-results
path: junit.xml
Best Practices
-
Follow AAA: Arrange (set values), Act (render), Assert (check).
-
One assertion per test for clear failures.
-
Test defaults, overrides, and edge cases (replicaCount: 0).
-
Combine with
helm lintandhelm template --validate. -
Version control
tests/with your chart. -
Use descriptive
it:names.
Common Pitfalls
-
PathCheck typos: Use JSONPath like
spec.template.spec.containers.[0].name. -
Snapshot drift: Review changes before
-u. -
Global values: Scope with
global.*paths.
Start testing your charts today—your future self will thank you
