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 lint before every commit
  • Use --strict mode 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 test for 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-policy to 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.
Previous: Uninstalling Charts Next: Helm Security

Testing Helm charts is essential for maintaining quality and reliability. Use a combination of linting, unit testing, and integration testing to catch issues early.