Testing Charts
A comprehensive guide to testing Helm charts covering unit testing, linting, helm test, chart validation, and best practices for ensuring chart quality.
Unit Testing
Linting
helm test
Validation
Why Testing Charts Matters
Testing Helm charts is essential for ensuring quality, reliability, and security. A comprehensive testing strategy includes:
- Linting: Syntax and best practice validation
- Unit Testing: Template rendering validation
- helm test: Integration testing in the cluster
- Schema Validation: Values validation
- Security Scanning: Vulnerability detection
Key Concept: Testing charts early in the development cycle prevents issues in production. A good testing strategy catches errors before they reach users.
Linting Charts
# Lint a chart
helm lint ./my-chart
# Lint with strict mode
helm lint ./my-chart --strict
# Lint with values file
helm lint ./my-chart -f values-prod.yaml
# Lint with multiple values files
helm lint ./my-chart -f values-dev.yaml -f values-prod.yaml
# Lint all charts in a directory
for chart in ./charts/*; do
helm lint "$chart"
done
# Lint with JSON output
helm lint ./my-chart --output json
# Common lint errors to fix:
# - Missing required fields in Chart.yaml
# - Invalid values schema
# - Template syntax errors
# - Missing dependencies
# - Incorrect indentation
Chart.yaml Validation
Checks for required fields: name, version, apiVersion, and dependencies.
Template Syntax
Validates Go template syntax and Helm functions.
Values Validation
Validates values against schema and default values.
Dependency Checks
Verifies that dependencies are properly declared and accessible.
Linting Best Practices:
- Run
helm lintbefore every commit - Use
--strictmode to catch all issues - Fix all errors before packaging
- Use linting in CI/CD pipelines
- Document common linting issues
Unit Testing with helm-unittest
helm-unittest is a plugin that provides unit testing for Helm charts. It allows you to test template rendering with assertions.
# Install helm-unittest plugin
helm plugin install https://github.com/helm-unittest/helm-unittest
# Run unit tests
helm unittest ./my-chart
# Run unit tests with coverage
helm unittest ./my-chart --coverage
# Run specific test file
helm unittest ./my-chart --test-file tests/deployment_test.yaml
# Run tests with debug output
helm unittest ./my-chart --debug
# Test file structure
# tests/deployment_test.yaml
suite: test deployment
templates:
- deployment.yaml
tests:
- it: should render deployment with correct name
asserts:
- isKind:
of: Deployment
- equal:
path: metadata.name
value: my-app
- it: should set replicas from values
values:
- replicas: 5
asserts:
- equal:
path: spec.replicas
value: 5
- it: should use default replicas when not set
asserts:
- equal:
path: spec.replicas
value: 3
- it: should render image correctly
asserts:
- matchRegex:
path: spec.template.spec.containers[0].image
pattern: nginx:.*
- it: should handle ingress when enabled
values:
- ingress:
enabled: true
asserts:
- hasDocuments:
count: 1
Assertions
equal, isKind, matchRegex, hasDocuments, and more.Values Overrides
Test different values configurations.
Conditional Tests
Test templates with different conditions.
Coverage Reports
Track which templates are tested.
# Example test file with multiple assertions
# tests/configmap_test.yaml
suite: test configmap
templates:
- configmap.yaml
tests:
- it: should render configmap with all keys
asserts:
- equal:
path: data
value:
key1: value1
key2: value2
- it: should include environment label
asserts:
- equal:
path: metadata.labels.environment
value: production
- it: should handle custom annotations
values:
- configMap:
annotations:
custom: value
asserts:
- equal:
path: metadata.annotations.custom
value: value
- it: should not render when disabled
values:
- configMap:
enabled: false
asserts:
- hasDocuments:
count: 0
Unit Testing Considerations:
- Unit tests don't validate Kubernetes API compatibility
- They only test template rendering
- Combine with
helm testfor integration testing - Use coverage reports to identify gaps
- Keep tests focused and maintainable
helm test: Integration Testing
helm test runs integration tests against a deployed release. Tests are defined as pods with the test hook.
# Define a test in the chart
# templates/tests/health-check.yaml
apiVersion: v1
kind: Pod
metadata:
name: {{ include "my-app.fullname" . }}-test-connection
labels:
{{- include "my-app.labels" . | nindent 4 }}
annotations:
helm.sh/hook: test
helm.sh/hook-delete-policy: hook-succeeded,hook-failed
spec:
containers:
- name: wget
image: busybox
command: ['wget']
args: ['{{ include "my-app.fullname" . }}:{{ .Values.service.port }}']
restartPolicy: Never
# Database connectivity test
apiVersion: v1
kind: Pod
metadata:
name: {{ include "my-app.fullname" . }}-db-test
annotations:
helm.sh/hook: test
helm.sh/hook-delete-policy: hook-succeeded
spec:
containers:
- name: test
image: postgres:15
command: ['sh', '-c']
args:
- |
PGPASSWORD=$DB_PASSWORD psql -h $DB_HOST -U $DB_USER -d $DB_NAME -c "SELECT 1"
env:
- name: DB_HOST
value: {{ .Values.database.host }}
- name: DB_USER
value: {{ .Values.database.user }}
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
- name: DB_NAME
value: {{ .Values.database.name }}
restartPolicy: Never
# API health check
apiVersion: v1
kind: Pod
metadata:
name: {{ include "my-app.fullname" . }}-api-test
annotations:
helm.sh/hook: test
helm.sh/hook-delete-policy: hook-succeeded
spec:
containers:
- name: curl
image: curlimages/curl:latest
command: ['sh', '-c']
args:
- |
curl -f http://{{ include "my-app.fullname" . }}:{{ .Values.service.port }}/health
restartPolicy: Never
# Run tests
helm test my-release
# Run tests with timeout
helm test my-release --timeout 5m
# Run tests with debug
helm test my-release --debug
# Run tests and keep pods for inspection
helm test my-release --logs
Health Checks
Verify that services are healthy and responding.
Database Tests
Test database connectivity and basic queries.
Network Tests
Verify network connectivity between services.
Rollback Tests
Test rollback scenarios.
helm test Best Practices:
- Define tests for critical functionality
- Use
hook-delete-policyto clean up test pods - Run tests after installation and upgrades
- Keep tests idempotent
- Use test logs for debugging
Chart Validation
# Validate Chart.yaml structure
helm lint ./my-chart
# Validate values schema
# values.schema.json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"replicaCount": {
"type": "integer",
"minimum": 1,
"maximum": 10
},
"image": {
"type": "object",
"properties": {
"repository": {
"type": "string"
},
"tag": {
"type": "string",
"default": "latest"
}
},
"required": ["repository"]
}
},
"required": ["image"]
}
# Validate with dry-run
helm install my-release ./my-chart --dry-run --debug
# Validate with kubeconform
helm template my-release ./my-chart | kubeconform -strict
# Validate with kubectl apply dry-run
helm template my-release ./my-chart | kubectl apply --dry-run=client -f -
# Validate with OPA
conftest test --policy policy/ manifest.yaml
Schema Validation
Validate values against JSON schema.
Kubernetes Validation
Validate generated YAML against Kubernetes API.
Security Validation
Check for security vulnerabilities.
Policy Validation
Validate against organizational policies.
CI/CD Integration
# GitHub Actions workflow
name: Test Helm Chart
on:
pull_request:
paths:
- 'charts/**'
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Helm
uses: azure/setup-helm@v3
- name: Lint Chart
run: |
helm lint ./my-chart --strict
helm unittest ./my-chart
- name: Install Chart
run: |
helm install test-release ./my-chart --dry-run --debug
- name: Test with kind
uses: helm/kind-action@v1
with:
cluster_name: kind
- name: Install and Test
run: |
helm install test-release ./my-chart
helm test test-release
# GitLab CI
stages:
- test
- lint
- validate
test:
stage: test
image: alpine/helm:latest
script:
- helm unittest ./my-chart
- helm lint ./my-chart --strict
validate:
stage: validate
image: alpine/helm:latest
script:
- helm template test ./my-chart | kubeconform -strict
# Jenkins Pipeline
pipeline {
agent any
stages {
stage('Lint') {
steps {
sh 'helm lint ./my-chart --strict'
}
}
stage('Unit Test') {
steps {
sh 'helm plugin install https://github.com/helm-unittest/helm-unittest'
sh 'helm unittest ./my-chart'
}
}
stage('Validate') {
steps {
sh 'helm template test ./my-chart | kubeconform -strict'
}
}
stage('Integration Test') {
steps {
sh 'helm install test-release ./my-chart'
sh 'helm test test-release'
}
}
}
}
CI/CD Best Practices:
- Run linting on every commit
- Run unit tests in CI
- Use kind or minikube for integration tests
- Validate generated YAML
- Run security scans
- Keep test artifacts for debugging
Frequently Asked Questions
What is the difference between helm lint and helm unittest?
helm lint checks syntax and best practices. helm unittest tests template rendering with assertions. Use both for comprehensive testing. How do I run helm test on an installed release?
Use
helm test <release> to run tests on an installed release. Tests are defined as pods with the test hook. What is the helm-unittest plugin?
helm-unittest is a plugin that provides unit testing capabilities for Helm charts. It allows you to test template rendering with assertions. How do I validate generated Kubernetes YAML?
Use
helm template with kubectl apply --dry-run or kubeconform to validate generated YAML against Kubernetes API. What should I test in a Helm chart?
Test template rendering, values handling, conditional logic, dependencies, and integration with Kubernetes. Also test security and compliance.
How do I test chart dependencies?
Use
helm dependency update and helm dependency build to manage dependencies. Test that dependencies are properly included and configured. What is the best way to test Helm charts in CI/CD?
Use a multi-stage approach: lint, unit test, validate YAML, and then test in a kind or minikube cluster. This catches issues early.
How do I test values schema validation?
Create a
values.schema.json file in the chart root. Use helm lint or helm install --dry-run to validate.
Related Topics
Testing Helm charts is essential for maintaining quality and reliability. Use a combination of linting, unit testing, and integration testing to catch issues early.