Open-Source Wikis

/

Istio

/

How to contribute

/

Testing

istio/istio

Testing

Istio's test surface is large: ~275,000 lines of Go test code and over 700 test files. This page covers what's available, how to run it, and what each suite is for.

Test categories

Suite Where Runs against
Unit tests (*_test.go) Co-located with each package In-process; fakes for k8s
Benchmarks pilot/..., pkg/... In-process
Fuzz tests tests/fuzz/, pkg/fuzz/ In-process
Integration tests tests/integration/... Real or fake Kubernetes clusters
Conformance tests/integration/conformance/ Gateway API conformance
Binary tests tests/binary/ Built binaries (size, debug stripping)

The framework that orchestrates everything beyond plain go test lives in pkg/test/framework/.

Unit tests

Run everything with race detection and the assert build tag:

make test                    # equivalent to: go test -race -tags=assert ./...
make test PKG=./pilot/...    # scope to a subtree

-tags=assert enables paths that panic on internal invariant violations — most importantly the xDS cache assertion that fires when the same key gets two different encodings (UNSAFE_PILOT_ENABLE_RUNTIME_ASSERTIONS=true). Always run tests with this on.

Test patterns you will encounter

  • Table-driven tests for translation logic (pilot/pkg/networking/core/cluster_test.go and friends). The convention is a tests := []struct{...}{} slice plus t.Run(tc.name, func(t *testing.T) {...}). Most have golden-file output.
  • Golden files are stored under testdata/. To regenerate: make refresh-goldens (or make update-golden). The handler is REFRESH_GOLDEN=true go test .... Always inspect the diff before committing.
  • Fakes for Kubernetes come from pkg/test/util/yml/, pkg/kube/kclient/clienttest/, and pilot/pkg/config/memory/ — they let you stand up a fake Istiod with deterministic config.
  • Echo client/server (pkg/test/echo/) is the Istio-specific test workload. It speaks HTTP, HTTP/2, gRPC, TCP, TLS, and reports per-request metadata as headers, which lets test cases assert on exactly which backend served a request.

Running a single test

go test -race -tags=assert -run TestXdsCachePush ./pilot/pkg/xds/...
go test -race -tags=assert -run TestPushContext/auth -v ./pilot/pkg/model/...

For tests that depend on Linux features (CNI, iptables, network namespaces), run inside the build container or on a Linux host: BUILD_WITH_CONTAINER=1 make test PKG=./cni/....

Benchmarks

make benchtest

Driven by prow/benchtest.sh, which:

  1. Runs benchmarks under BENCH_TARGETS (default ./pilot/...).
  2. Uses benchstat to compare against the previous run.
  3. Reports regressions.

Most of Istio's benchmarks measure xDS push latency and config-translation throughput. They live under pilot/pkg/xds/bench_test.go, pilot/pkg/networking/core/..., and pkg/kube/krt/bench_test.go. If you change the translation pipeline or the cache, run benchtest and post the comparison in your PR.

Fuzz tests

Istio uses Go's native fuzzing (testing.F) for inputs that come from the network or untrusted YAML. Fuzz harnesses live in:

  • tests/fuzz/ — top-level harnesses run by OSS-Fuzz.
  • pkg/fuzz/ — utilities for writing fuzz tests across the codebase.
  • Inline Fuzz* functions next to the code they exercise (search func Fuzz to find them).

Run a fuzzer locally:

go test -fuzz=FuzzKubernetesYAML -fuzztime=30s ./pilot/pkg/config/kube/crdclient/...

OSS-Fuzz runs these continuously; failures are filed as issues automatically.

Integration tests

Integration tests exercise Istio against a real Kubernetes cluster (or fake one, depending on the test). They are big, slow, and the place where regressions in real cluster behavior get caught.

Layout

tests/integration/
├── README.md            # the canonical guide; read it before running
├── tests.mk             # included by Makefile.core.mk; defines integration targets
├── pilot/               # routing, gateway, sidecar, multicluster
├── ambient/             # ztunnel + waypoint scenarios
├── security/            # mTLS, authz, JWT, CA flows
├── telemetry/           # metrics, tracing, access logs
├── helm/                # Helm chart upgrade and install tests
├── iop-*.yaml           # IstioOperator profiles for the tests
└── base.yaml            # shared base config

Each subdirectory is a Go package with go test entry points. They register with the framework using framework.NewTest(t).Run(...).

Running them

Most integration tests assume a working Kubernetes cluster reachable via $KUBECONFIG. The standard target is:

make test.integration.pilot.kube           # KIND-based pilot tests
make test.integration.security.kube
make test.integration.ambient

The full list of make test.integration.* targets is in tests/integration/tests.mk. CI runs these on KIND clusters in Prow; locally you can use any cluster (Kind, Minikube, or a real one) but expect the suites to take 10-60 minutes each.

If you don't have a cluster:

make test.integration.pilot.fake           # uses in-process fake k8s

Fake mode is faster but skips data-plane tests.

Writing an integration test

The pattern, from tests/integration/pilot/:

func TestRouting(t *testing.T) {
    framework.NewTest(t).
        Features("traffic-management.routing").
        Run(func(t framework.TestContext) {
            // t.ConfigIstio().YAML(ns, vsYAML).ApplyOrFail(t)
            // echo.Instances{a, b, c}.CallOrFail(t, ...)
        })
}

The framework provides:

  • Cluster lifecycle (Clusters(), ClusterByName(...))
  • Namespace setup (namespace.NewOrFail(...))
  • Echo workloads (deployment.New(...))
  • Config application (t.ConfigIstio().YAML(...).Apply(...))
  • Built-in retries with echo.CheckXxx matchers

The README in tests/integration/README.md is the canonical reference and walks through every option.

Conformance

tests/integration/conformance/ is the Gateway API conformance suite, run against Istio's Kubernetes Gateway API implementation in pilot/pkg/config/kube/gateway/. Failures here typically mean Istio's translation diverges from the upstream gateway.networking.k8s.io spec.

Binary tests

tests/binary/ validates that built binaries are within size budgets and have the right symbols stripped. RELEASE_SIZE_TEST_BINARIES in Makefile.core.mk lists what's measured. Useful when you need to confirm a refactor hasn't bloated the istio-proxy binary.

Coverage

make test does not enable coverage by default; the Prow jobs do. To get a local coverage report:

go test -race -tags=assert -coverprofile=cover.out ./pilot/...
go tool cover -html=cover.out

There is no coverage gate at PR time — reviewers ask for coverage of new logic on a case-by-case basis.

Tips

  • For fast iteration on a single failing test, use T='-run ^TestName$ -v' with make test.
  • The -count=1 flag bypasses the test cache when you need a clean run.
  • pilot/pkg/xds/adstest.go has helpers (AdsTest, Connect) for spinning up a fake xDS client; reuse them rather than wiring gRPC streams from scratch.
  • The integration framework supports --istio.test.kube.deploy=false to reuse an already-installed Istio instead of redeploying for each suite — speeds up iteration considerably.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Testing – Istio wiki | Factory