Helm3 Unit Test Tutorial

Jack Zhai
2 min readApr 24, 2022

Helm is a declarative deployment tool for K8s. Chart is a package format for Helm’s deployment method. This article is based on helm v3 version.

This article will cover:

  1. why Helm unit tests are needed
  2. how to write Helm unit tests
  3. how to integrate into the build pipeline

Why Helm unit tests are needed

Helm uses the Go Template language, which is very difficult to maintain, so Helm’s Chart package is also difficult to maintain.

After we writed the YAML file in Chart, we can only verify its syntax correctness by executing Helm template command manually. The disadvantages of doing so are:

  1. no automated validation
  2. no repeatable validation

How to do Helm unit testing

Helm3 unit testing requires the following steps.

  1. install the helm3-unittest plugin.
  2. add $YOUR_CHART/tests to .helmignore. as you do not need to package the tests directory into the final chart package.
  3. write unit test code.
  4. integrate into the continuous integration pipeline.

Install the helm3-unittest plugin

helm plugin install https://github.com/vbehar/helm3-unittest

Of course, you can also add the — version parameter to specify the version. As follows.

helm plugin install --version 1.0.16 https://github.com/vbehar/helm3-unittest

Steps to write unit tests

  1. Create the $YOUR_CHART/tests directory. Note that it is not $YOUR_CHART/templates/test directory.
  2. Write the unit tests in the $YOUR_CHART/tests directory.
  3. Execute the command in the root directory of the repo: helm unittest .

Writing unit tests

We create a unit test case $YOURCHART/tests/deloyment_test.yaml:

suite: test deployment
templates:
- deployment.yaml
tests:
- it: should pass all kinds of assertion
values:
# 指定一个values文件 相对于 $YOUR_CHART/tests路径。
- ./values/image.yaml
set:
# 覆盖以上values的一项配置
service.internalPort: 8080
asserts:
- equal:
path: spec.template.spec.containers[0].image
value: apache:latest
- notEqual:
path: spec.template.spec.containers[0].image
value: nginx:stable
- matchRegex:
path: metadata.name
pattern: ^.*-basic$
- notMatchRegex:
path: metadata.name
pattern: ^.*-foobar$
- contains:
path: spec.template.spec.containers[0].ports
content:
containerPort: 8080
- notContains:
path: spec.template.spec.containers[0].ports
content:
containerPort: 80
- isNull:
path: spec.template.nodeSelector
- isNotNull:
path: spec.template
- isEmpty:
path: spec.template.spec.containers[0].resources
- isNotEmpty:
path: spec.template.spec.containers[0]
- isKind:
of: Deployment
- isAPIVersion:
of: extensions/v1beta1
- hasDocuments:
count: 2
- matchSnapshot:
path: spec

Integration into the continuous integration pipeline

We use GitHub actions as an example:

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Helm unittest
uses: WyriHaximus/github-action-helm3@v2.0.0
with:
exec: helm plugin install --version 1.0.16 https://github.com/vbehar/helm3-unittest && helm unittest .

A little bit of basics of Helm plugin

  • The environment variable HELM_PLUGINS can specify the path where the Helm plugin is installed.
  • If there are too many Helm plugins in your project, consider placing the plugins in the $HELM_PLUGINS directory in advance.

Follow up

The Helm unit test only tests for Helm syntax-level errors and does not test to see how well it actually runs in K8s. To test how well it really runs on K8s, we need integration tests. That’s a topic for another day.

--

--

Jack Zhai

DevOps,SRE,Bazel The Author of 《Jenkins2.x In Practice》, https://showme.codes