Modern QA2026Unit Testing with helm-unittest — tiles
Log inJoin
39 / 75 · 08 Infrastructure as Code Testing · Helm Chart Testing← prev⊞ allnext →☰ Read as one page

7.5Unit Testing with helm-unittest

helm-unittest is a dedicated unit testing framework for Helm charts. It lets you write assertions against rendered template output without deploying anything.

Installation

# Install as a Helm plugin
helm plugin install https://github.com/helm-unittest/helm-unittest

Test Structure

charts/myapp/
  Chart.yaml
  values.yaml
  templates/
    deployment.yaml
    service.yaml
    ingress.yaml
  tests/
    deployment_test.yaml
    service_test.yaml
    ingress_test.yaml

Writing Unit Tests

# tests/deployment_test.yaml
suite: Deployment Tests
templates:
  - deployment.yaml
tests:
  - it: should set resource limits
    asserts:
      - isNotNull:
          path: spec.template.spec.containers[0].resources.limits.cpu
      - isNotNull:
          path: spec.template.spec.containers[0].resources.limits.memory

  - it: should not run as root
    asserts:
      - equal:
          path: spec.template.spec.securityContext.runAsNonRoot
          value: true

  - it: should use the correct image tag
    set:
      image.tag: "2.3.1"
    asserts:
      - matchRegex:
          path: spec.template.spec.containers[0].image
          pattern: ":2\\.3\\.1$"

  - it: should set correct replica count for production
    values:
      - ../values-production.yaml
    asserts:
      - equal:
          path: spec.replicas
          value: 3

  - it: should set readiness probe
    asserts:
      - isNotNull:
          path: spec.template.spec.containers[0].readinessProbe
      - equal:
          path: spec.template.spec.containers[0].readinessProbe.httpGet.path
          value: /healthz

  - it: should set liveness probe
    asserts:
      - isNotNull:
          path: spec.template.spec.containers[0].livenessProbe

  - it: should drop all capabilities
    asserts:
      - contains:
          path: spec.template.spec.containers[0].securityContext.capabilities.drop
          content: "ALL"

  - it: should not use latest tag
    set:
      image.tag: "latest"
    asserts:
      - failedTemplate:
          errorMessage: "image.tag must not be 'latest'"

Testing Conditional Resources

# tests/ingress_test.yaml
suite: Ingress Tests
templates:
  - ingress.yaml
tests:
  - it: should not create ingress by default
    asserts:
      - hasDocuments:
          count: 0

  - it: should create ingress when enabled
    set:
      ingress.enabled: true
      ingress.host: "myapp.example.com"
    asserts:
      - hasDocuments:
          count: 1
      - equal:
          path: spec.rules[0].host
          value: "myapp.example.com"

  - it: should configure TLS when specified
    set:
      ingress.enabled: true
      ingress.host: "myapp.example.com"
      ingress.tls.enabled: true
      ingress.tls.secretName: "myapp-tls"
    asserts:
      - equal:
          path: spec.tls[0].secretName
          value: "myapp-tls"
      - contains:
          path: spec.tls[0].hosts
          content: "myapp.example.com"

Running Unit Tests

# Run all tests
helm unittest ./charts/myapp/

# Run with verbose output
helm unittest -v ./charts/myapp/

# Output as JUnit XML for CI
helm unittest -o junit -f test-results.xml ./charts/myapp/

# Run specific test file
helm unittest -f 'tests/deployment_test.yaml' ./charts/myapp/