Skip to content

Big Bang Template Self-testing Guide📜

The Big Bang chart includes a self-testing functionality that allows you to easily verify the functionality of individual templates.

How it works📜

The self-testing feature is implemented using a special section in the values.yaml file called _selfTest. This section allows you to define tests for specific templates by specifying the template name and the arguments to be passed to the template.

When the self-test is executed, the specified template is rendered with the provided arguments, and the result is placed at the result key in a special TestResult resource named after the template.

The self-test results can then be used in unit tests to verify the correctness of the template.

Example📜

Let’s say we have a simple template that multiplies two numbers together. The template is defined as follows:

{{- define "bigbang.example-template.multiply" }}
  {{- mul (index . 0) (index . 1) }}
{{- end }}

A test for this template can be defined in the _selfTest section of the values.yaml file:

_selfTest:
  bigbang.example-template.multiply:
    args:
      - 2
      - 3

The test specifies the arguments to be passed to the template. In this case, we are passing a list of two numbers: 2 and 3.

When the self-test is executed, the template is rendered with the provided arguments, and the result is placed at the result key:

helm template chart --show-only templates/_self-test/render.yaml
---
# Source: bigbang/templates/_self-test/render.yaml
apiVersion: testing.bigbang.dev/v1
args:
  - 2
  - 3
kind: TestResult
metadata:
  name: bigbang.example-template.multiply
result: "6"

Note: The result is a string because Helm templates always render strings.

Using self-test results in unit tests📜

The self-test results can be used in unit tests to verify the correctness of the template. For example, you can create a unit test that checks if the result of the multiplication is as expected:

suite: bigbang.example-template.multiply
tests:
  - it: multiplies two numbers correctly
    set:
      _selfTest:
        bigbang.example-template.multiply:
          args:
            - 2
            - 3
    asserts:
      - equal:
          path: result
          value: "6"

Asserting yaml structures📜

In cases where the output of a template is a complex YAML structure, you can set the resultIsYaml flag to true in the _selfTest section. This will instruct the testing framework to parse the result as YAML, allowing you to perform assertions on individual fields within the structure.

Example📜

For example, consider a template that receives a map of key-value pairs and generates a Kubernetes ConfigMap:

{{- define "bigbang.example-template.configmap" }}
apiVersion: v1
kind: ConfigMap
metadata:
  name: example-config
data:
  {{- range $key, $value := . }}
  {{ $key }}: {{ $value | quote }}
  {{- end }}
{{- end }}

A test for this template can be defined in the _selfTest section of the values.yaml file:

_selfTest:
  bigbang.example-template.configmap:
    args:
      key1: value1
      key2: value2

When the self-test is executed, the template is rendered with the provided arguments, and the result is placed at the result key:

helm template chart --show-only templates/_self-test/render.yaml
---
# Source: bigbang/templates/_self-test/render.yaml
apiVersion: testing.bigbang.dev/v1
args:
  key1: value1
  key2: value2
kind: TestResult
metadata:
  name: bigbang.example-template.configmap
result: |
  apiVersion: v1
  kind: ConfigMap
  metadata:
    name: example-config
  data:
    key1: "value1"
    key2: "value2"

In this case, the result is a multi-line string representing the YAML structure of the ConfigMap.

By setting the resultIsYaml flag to true, you can have the testing framework parse the result as YAML, allowing you to perform assertions on individual fields within the structure:

 _selfTest:
   bigbang.example-template.configmap:
     args:
       key1: value1
       key2: value2
+    resultIsYaml: true
 ---
 # Source: bigbang/templates/_self-test/render.yaml
 apiVersion: testing.bigbang.dev/v1
 args:
   key1: value1
   key2: value2
 kind: TestResult
 metadata:
   name: bigbang.example-template.configmap
-result: |
+result:
   apiVersion: v1
   kind: ConfigMap
   metadata:
     name: example-config
   data:
     key1: "value1"
     key2: "value2"
suite: bigbang.example-template.configmap
tests:
  - it: creates a ConfigMap with the correct data
    set:
      _selfTest:
        bigbang.example-template.configmap:
          args:
            key1: value1
            key2: value2
          resultIsYaml: true
    asserts:
      - equal:
          path: result.data.key1
          value: "value1"
      - equal:
          path: result.data.key2
          value: "value2"

Passing the helm root context to templates📜

In some cases, you may want to pass the entire Helm root context to a template for testing purposes. This can be achieved by using the special argument helm:context.

Example📜

For example, consider a template that generates a Service resource based on values from the Helm root context:

app:
  name: my-app
service:
  name: my-service
  type: ClusterIP
  port: 80
  targetPort: 8080
{{- define "bigbang.example-template.service" }}
apiVersion: v1
kind: Service
metadata:
  name: {{ .Values.service.name }}
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.port }}
      targetPort: {{ .Values.service.targetPort }}
  selector:
    app: {{ .Values.app.name }}
{{- end }}

A test for this template can be defined in the _selfTest section of the values.yaml file, using the helm:context argument to pass the entire Helm root context:

_selfTest:
  bigbang.example-template.service:
    args: helm:context

When the self-test is executed, the template is rendered with the Helm root context, and the result is placed at the result key:

helm template chart --show-only templates/_self-test/render.yaml
---
# Source: bigbang/templates/_self-test/render.yaml
apiVersion: testing.bigbang.dev/v1
args:
  # The helm:context expands to the full Helm root context, including
  # all values, capabilities, release info, and chart metadata.
  Values: { ... }
  Capabilities: { ... }
  Release: { ... }
  Chart: { ... }
kind: TestResult
metadata:
  name: bigbang.example-template.service
result: |
  apiVersion: v1
  kind: Service
  metadata:
    name: my-service
  spec:
    type: ClusterIP
    ports:
      - port: 80
        targetPort: 8080
    selector:
      app: my-app

For flexible argument support, the helm:context magic string is also supported as part of a list or as a value in a top-level map key:

_selfTest:
  bigbang.example-template.i-take-a-list:
    args:
      - helm:context
      - someOtherValue
_selfTest:
  bigbang.example-template.i-take-a-map:
    args:
      config: helm:context
      otherConfig: someOtherValue
_selfTest:
  bigbang.example-template.i-take-a-deeply-nested-map:
    args:
      config:
        nestedConfig: helm:context # This does NOT work; only top-level keys support helm:context
      otherConfig: someOtherValue

This allows you to test templates that require the full Helm context while still being able to pass additional arguments as needed.