skip to content

What does `helm test` do when you run it against an installed release?

level: juniorimportance: must knowfreq 70%

answer

  1. It needs something already running
  2. Works on a release, not a chart
  3. Marked resources, created on demand
  4. Pod exit status decides the verdict
  5. Non-zero exit is the CI gate

basics

~20 s

helm test looks up an installed release, creates the manifests in it that carry the helm.sh/hook: test annotation - usually Pods - waits for them to finish in the release namespace, and reports pass or fail through its exit code.

solid answer

~50 s

`helm test RELEASE` operates on a release that is already installed: Helm loads the release, picks out the hook manifests annotated `helm.sh/hook: test`, creates them in the release's namespace, and waits for each Pod to terminate. A Pod whose containers all exit 0 reaches `Succeeded` and counts as a pass; anything else is a failure, and the command exits non-zero so a pipeline can gate on it. Because the Pod runs *inside* the cluster it can do things no offline check can - resolve the release's Service name, connect to it, use a Secret the chart rendered. `--logs` dumps the test Pods' output so you can see why one failed. It is a live smoke test, not a chart check: it never runs during `helm install` unless you invoke it, and it does not create a new release revision.

code

yaml · 12 lines
yaml
apiVersion: v1
kind: Pod
metadata:
  name: ledger-api-smoke
  annotations:
    "helm.sh/hook": test
spec:
  restartPolicy: Never
  containers:
    - name: smoke
      image: curlimages/curl:8.6.0
      args: ["--fail", "--silent", "http://ledger-api:8080/healthz"]

go deeper

for a junior

Be ready to say the command needs a release that is already installed, that it runs the resources marked as test hooks in the release's namespace, and that the Pod's exit code decides pass or fail.

for a middle

Explain the mechanics: Helm creates the test resources, waits for each Pod to terminate, and treats Succeeded as a pass. Be clear that no revision is created and that the run is separate from install and upgrade.

for a senior

Show that you know what the command is worth operationally - a non-zero exit is the gate, --logs is the triage, and a chart with no tests passes silently. Say how you keep that silent pass from becoming a green pipeline that proves nothing.

for a principal

Own the policy question: which releases must ship a test, what a test is allowed to assert against production data, and whether the smoke check belongs in Helm at all versus a probe or a synthetic check owned by the platform.

## What the command actually is `helm test RELEASE_NAME` is Helm's only command that runs *your* code against a release that is already live. Everything else Helm offers in the checking family works on chart source: it renders templates, validates values, or diffs YAML. `helm test` does none of that. It takes the name of an installed release, finds the resources in it that are marked as test hooks, creates them in the cluster, and tells you whether they succeeded. ## What has to exist first Two things. A release of that name must exist in the namespace you point at (`-n`, or whatever `HELM_NAMESPACE` resolves to) - if there is no release, the command errors out before it touches the cluster. And the chart that release was installed from must contain at least one manifest annotated `helm.sh/hook: test`. If the chart has none, `helm test` succeeds trivially and has proved nothing at all, which is a real trap: a green test on a chart with no tests looks identical in CI to a green test that actually connected to something. The scaffolding `helm create` emits includes a connection test under `templates/tests/` - a small Pod that fetches the release's own Service. That file is a starting point, not a smoke test worth trusting; most teams replace its body with a request that exercises a real endpoint. ## The lifecycle of a run Helm creates the test resources, then waits. The unit of judgement is the Pod: every container in it must terminate, and terminate with exit status 0, for the Pod to reach the `Succeeded` phase. That is why a test Pod must be written as a **command that ends** - a request, an assertion, an exit - rather than as a server. A Pod that keeps running is not passing slowly; it is not passing at all, and it will burn the whole wait budget before Helm gives up. When every test Pod has finished, Helm reports each one as passed or failed and sets its own exit status accordingly. Non-zero on failure is what makes the command usable as a pipeline step. `--logs` prints the test Pods' container output after the run completes, which is normally the fastest way to see what a failing assertion actually said. `--filter name=<pod-name>` narrows a multi-test chart to a single test while you iterate. ## What it does *not* touch `helm test` does not create a new revision. The release's revision number, its stored manifest and its stored values are all unchanged by a test run, which is why running it repeatedly is cheap and why a passing test is not itself recorded as part of the deployment history. It is also not part of `helm install` or `helm upgrade`: the install finishes, the release is already serving, and the test runs afterwards as a separate command. If you want the test to gate a rollout, your pipeline has to run it and act on the exit code itself. It is also not a substitute for the pre-merge checks a chart needs. Rendering the templates, validating a values file against a schema and asserting on the produced YAML all happen before anything reaches a cluster and catch a different class of defect - a typo in a template, an unset required value. `helm test` catches the class those cannot see: the chart rendered fine, the objects were accepted by the API server, and the thing still does not work because a Service selector matches nothing, a Secret key is spelled differently from the one the app reads, or a dependency is unreachable from that namespace. ## Why the distinction matters in an interview Candidates routinely describe `helm test` as "validating the chart". It validates nothing about the chart. It runs a Pod in a cluster against a running release and reports whether that Pod exited cleanly. Everything the test proves comes from what you wrote inside it, and everything it cannot prove comes from the fact that it is one process, run once, from inside one namespace.

  • Does `helm test` create a new release revision?
    No. It creates the test resources in the cluster and reports a verdict, but the release's revision number, stored manifest and stored values are untouched. That is why re-running it is cheap, and why a passing test leaves no trace in `helm history` - if you want a record that the smoke test passed, your pipeline has to keep it.
  • What exactly makes a chart test count as passed?
    The test Pod must reach the `Succeeded` phase: every container in it terminates, and terminates with exit code 0. A non-zero exit makes the Pod `Failed` and `helm test` exits non-zero. A container that never terminates never passes - it simply consumes the wait budget until Helm gives up.
  • A chart has no test-annotated manifests. What does `helm test` report?
    It has nothing to run and reports success. That is indistinguishable in CI from a test that genuinely connected to the app, so a pipeline that gates on `helm test` should also assert that the chart actually ships at least one test - otherwise deleting the test file silently turns the gate green forever.

It is the smoke test an electrician runs after wiring a building: flip the switch and see whether the light comes on. It says nothing about whether the wiring diagram was drawn correctly - only that this one circuit works right now.

saying these in an interview costs you the question

  • Says helm test validates the chart's templates or YAML
  • Thinks helm test runs automatically as part of helm install
  • Believes it needs the chart directory checked out locally
  • Confuses helm test with a lint or schema check
  • Assumes a long-running test container eventually counts as passing
  • Thinks a test run bumps the release revision

context