helm-chart-tester
Configures helm-unittest for Helm chart unit testing - installs the `helm-unittest` plugin, authors `tests/*.yaml` per template, asserts on rendered manifests (`isKind`, `equal`, `matchRegex`, snapshots), plus `helm lint` and `helm template` render testing. Use to verify a chart's template logic and rendered shape; this is unit-level correctness testing, not security scanning - to enforce policy on rendered manifests use policy-as-code-runner, and to scan charts for misconfigurations use checkov-policy or kics-policy.
Install with skills.sh (any agent)
npx skills add testland/qa --skill helm-chart-testerhelm-chart-tester
Overview
helm-unittest (Helm plugin) unit-tests the rendered chart output - assert specific fields, conditional behaviors, value substitutions - to catch template bugs before deploying.
When to use
Step 1 - Install
helm plugin install https://github.com/helm-unittest/helm-unittest
helm plugin list # verifyStep 2 - Author a test
# charts/mychart/tests/deployment_test.yaml
suite: deployment template
templates:
- templates/deployment.yaml
tests:
- it: should set the right image
set:
image.repository: myapp
image.tag: v1.2.3
asserts:
- isKind:
of: Deployment
- equal:
path: spec.template.spec.containers[0].image
value: myapp:v1.2.3
- it: should add the configured env vars
set:
env:
- name: API_URL
value: https://api.example.com
- name: LOG_LEVEL
value: debug
asserts:
- contains:
path: spec.template.spec.containers[0].env
content:
name: API_URL
value: https://api.example.com
- it: should add resource limits when set
set:
resources:
limits:
memory: 512Mi
cpu: 500m
asserts:
- equal:
path: spec.template.spec.containers[0].resources.limits.memory
value: 512Mi
- it: should NOT add resource limits when unset
asserts:
- notExists:
path: spec.template.spec.containers[0].resources.limitsThe set: block overrides values; asserts: checks the rendered output.
Step 3 - Common assertions
| Assertion | Use |
|---|---|
equal | Exact value match |
notEqual | Inverse |
isKind | Document is the expected Kind |
isAPIVersion | Specific API version |
isNullOrEmpty | Field is null / empty |
notNullOrEmpty | Field has a value |
exists | Field exists |
notExists | Field absent |
contains | Array contains an item |
notContains | Inverse |
matchRegex | Field matches regex |
notMatchRegex | Inverse |
failedTemplate | Template should fail to render (negative test) |
Step 4 - Run
# All tests for a chart
helm unittest charts/mychart/
# Specific test file
helm unittest charts/mychart/ -f tests/deployment_test.yaml
# Update snapshots (if using snapshot assertions)
helm unittest charts/mychart/ -uStep 5 - Snapshot testing
For complex rendered manifests, snapshot the output:
tests:
- it: should render the full deployment correctly
asserts:
- matchSnapshot: {}First run captures the snapshot; subsequent runs compare. A diff fails the test. Useful for catching unintended template changes.
Per golden-file-conventions (in the qa-test-data plugin): sanitize the snapshots (strip volatile fields like timestamps).
Step 6 - Chart linting
helm lint charts/mychart/Catches:
Run alongside unit tests in CI.
Step 7 - Render testing
# See the rendered output without applying
helm template myrelease charts/mychart/ -f values.test.yaml
# Compare two renders (e.g., before / after a change)
helm template myrelease charts/mychart/ -f values.test.yaml > new.yaml
git stash
helm template myrelease charts/mychart/ -f values.test.yaml > old.yaml
git stash pop
diff old.yaml new.yamlUseful for review: "what does this change actually produce?"
Step 8 - CI integration
jobs:
helm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: azure/setup-helm@v4
with: { version: 'v3.16.4' }
- run: helm plugin install https://github.com/helm-unittest/helm-unittest
- run: helm lint charts/mychart/
- run: helm unittest charts/mychart/Step 9 - Kubernetes admission integration
For deeper verification, render charts and run them through OPA / Conftest:
helm template myrelease charts/mychart/ -f values.yaml | conftest test -The Conftest step catches policy violations the unit tests don't cover (e.g., "all containers must have resource limits"). See policy-as-code-runner.
Anti-patterns
| Anti-pattern | Why it fails | Fix |
|---|---|---|
Skipping helm lint | Schema violations slip; install fails at deploy. | Always lint (Step 6). |
Snapshot-only tests (no equal checks) | Snapshots accept any change; explicit assertions catch intent. | Mix snapshots + explicit (Step 2 + Step 5). |
| One mega-test file per chart | Test file becomes unreadable; merge conflicts. | One test file per template. |
| Hardcoded image tags in tests | Tests pass against the wrong tag if values default. | Set image tag explicitly via set:. |
Skipping the negative tests (notExists, failedTemplate) | Unintended additions slip through. | Test absences too (Step 2 example). |
Limitations
References
Related skills
checkov-policy
Configures Checkov for IaC security scanning across Terraform, CloudFormation, Kubernetes, Helm, ARM, Serverless, AWS CDK - `pip install checkov`, custom Python checks, SARIF / JUnit output, and `--baseline` gating so CI fails only on new findings in legacy code. Use for the broadest built-in rule set with Python custom checks; for Terraform-only scanning use tfsec-policy, for wider platform breadth (OpenAPI / Pulumi / Crossplane) use kics-policy, and for a consolidated new-project scanner use trivy-config.
kics-policy
Configures KICS (Keeping Infrastructure as Code Secure), Checkmarx's scanner covering Terraform, Kubernetes, Helm, Dockerfile, OpenAPI, Ansible, ARM, CloudFormation, Pulumi, Crossplane - CLI / Docker / GitHub Action / pre-commit, JSON / SARIF / HTML / JUnit output, custom Rego queries. Use for the widest platform breadth, especially OpenAPI / Pulumi / Crossplane; for the broadest built-in checks with Python custom rules use checkov-policy, for Terraform-only scanning use tfsec-policy, and for a consolidated scanner use trivy-config.
policy-as-code-runner
Configures policy-as-code testing using OPA / Conftest / Cedar - authors policies in Rego (OPA's language), runs Conftest against Kubernetes manifests / Terraform plans / Dockerfiles / arbitrary structured data, integrates with CI for PR-time policy gates. Per OPA's docs: "an open source, general-purpose policy engine that unifies policy enforcement across the stack." Use to express + enforce custom policies (cost limits, tagging requirements, security baselines) that Checkov / tfsec / KICS don't cover.
tfsec-policy
Configures tfsec for Terraform-specific security scanning - covers AWS / Azure / GCP / Kubernetes / OpenStack / Oracle / DigitalOcean / CloudStack, custom YAML rules, and SARIF / JUnit / Markdown output. Note: tfsec is transitioning to Trivy per Aqua Security, so new projects evaluate that first. Use for an existing Terraform-only tfsec stack; for the consolidated forward-path scanner use trivy-config, for the broadest multi-framework checks use checkov-policy, and for wider platform breadth use kics-policy.
trivy-config
Runs Trivy's misconfiguration scanner (`trivy config`) against IaC directories to detect security issues across Terraform, CloudFormation, Kubernetes manifests, Helm charts, Dockerfiles, and Azure ARM templates - installs Trivy, scans with severity gating via `--exit-code`, suppresses findings via `.trivyignore` / `.trivyignore.yaml` or inline annotations, extends built-in checks with custom Rego policies, and emits SARIF for GitHub Code Scanning. Trivy is the forward path from tfsec (per Aqua Security's own migration guidance). Use when adopting a consolidated IaC scanner for new projects, migrating away from tfsec, or scanning mixed IaC stacks with a single tool.