Skip to content

Define your tests

Test definitions validate built images using container-structure-test. They are rendered during ch generate and executed by ch test.

File location

Place a test.yml or test.yml.gotpl file alongside the Dockerfile in the image directory. The .gotpl extension is optional — use it when you need Go template variables (versions, build args). Plain test.yml files are copied as-is.

images/my-image/
├── image.yml
├── Dockerfile
└── test.yml.gotpl

Variants can have their own test definitions:

images/my-image/
├── image.yml
├── Dockerfile
├── test.yml.gotpl
└── slim/
    ├── Dockerfile
    └── test.yml.gotpl

When both an image-level and variant-level test file exist, both are collected and executed.

Template context

The template receives a TemplateContext with the following fields:

Field Type Description
Versions map Version values resolved from image, tag, and variant definitions
BuildArgs map Build arguments resolved from image, tag, and variant definitions
ImageName string The name of the image

Values follow a merge hierarchy: image defaults -> tag overrides -> variant overrides.

Schema

Test files use the container-structure-test schema version 2.0.0. The following test types are supported:

Command tests

Run a command inside the container and check the output:

schemaVersion: 2.0.0
commandTests:
  - name: "Python version"
    command: "python"
    args: ["--version"]
    expectedOutput: ["Python {{ .Versions.python }}"]

File existence tests

Check that files exist (or don't) with expected permissions:

schemaVersion: 2.0.0
fileExistenceTests:
  - name: "Binary exists"
    path: "/usr/local/bin/my-app"
    shouldExist: true
    permissions: "-rwxr-xr-x"

File content tests

Check the contents of files in the image:

schemaVersion: 2.0.0
fileContentTests:
  - name: "Config contains production"
    path: "/etc/my-app/config.yml"
    expectedContents: ["production"]

Metadata tests

Validate image metadata like labels and environment variables:

schemaVersion: 2.0.0
metadataTest:
  labels:
    - key: "app"
      value: "{{ .ImageName }}"
  envVars:
    - key: "APP_VERSION"
      value: "{{ .Versions.app }}"

Template functions

Templates have access to all Sprig functions plus:

Function Description
resolve_base(name, tag) Produces an internal image reference for inter-image dependencies

Examples

Version check with Go template variable

schemaVersion: 2.0.0
commandTests:
  - name: "go-version"
    command: "go"
    args: ["version"]
    expectedOutput: ["go{{ .Versions.go }}"]
metadataTest:
  labels:
    - key: "app"
      value: "{{ .ImageName }}"

Rootfs file validation

schemaVersion: 2.0.0
commandTests:
  - name: "python-version"
    command: "python"
    args: ["--version"]
    expectedOutput: ["Python {{ .Versions.python }}"]

fileExistenceTests:
  - name: "rootfs-python-info-exists"
    path: "/etc/python-info"
    shouldExist: true

fileContentTests:
  - name: "rootfs-python-info-has-version-level-content"
    path: "/etc/python-info"
    expectedContents: ["level=version"]

Variant-specific test

schemaVersion: 2.0.0
commandTests:
  - name: "node-version"
    command: "node"
    args: ["--version"]
    expectedOutput: ["{{ .Versions.nodejs }}"]

Rendered output

During ch generate, test templates are rendered to dist/<image>/<tag>/tests/:

dist/my-image/latest/tests/
├── image.yml       # from image-level test.yml.gotpl
└── variant.yml     # from variant-level test.yml.gotpl (if present)

These rendered files are consumed by ch test using container-structure-test.

For more on running tests, see Container Structure Tests.