Open-Source Wikis

/

Temporal

/

How to contribute

/

Testing

temporalio/temporal

Testing

The repository ships three test layers, each with its own Make target. Most contributions need at least the first two.

The three layers

Layer Make target Tag What it covers
Unit make unit-test (none) Pure Go tests under service/, common/, chasm/. No real DB; uses mocks generated by go.uber.org/mock.
Integration make integration-test integration Persistence-backed tests requiring a real DB or fault-injection wrapper.
Functional make functional-test test_dep E2E tests under tests/. Spin up an in-process cluster.

Required build tag for any test: -tags test_dep (called out as mandatory in AGENTS.md). Add -tags integration,test_dep for integration tests.

go test -tags test_dep -v ./service/history/workflow -run TestMutableStateImpl
go test -tags integration,test_dep -v ./common/persistence/cassandra

Patterns and conventions

The project's test conventions are summarised in AGENTS.md and enforced by testifylint in make lint-code:

  • Prefer require over assert in unit tests. assert continues on failure and pollutes the failure log.
  • Avoid testify suites in unit tests (functional tests use them for cluster setup; that's fine).
  • require.Eventually instead of time.Sleep. The latter is forbidden by lint.
  • Float comparisons use require.InDelta / require.InEpsilon, never Equal.
  • In testify suites, use s.Require().NoError(err) rather than s.NoError(err) (the latter doesn't fail-fast).
  • Test both happy and failure paths, especially around persistence retries, shard transitions, and replication conflicts.

Mocks

Generated mocks live next to the interface (e.g. data_interfaces_mock.go next to data_interfaces.go). Regenerate with:

go generate ./common/persistence/...

Mocks are produced by go.uber.org/mock/mockgen; each mock file is annotated with //go:generate mockgen ... near the top of the source it mocks.

Integration test infrastructure

Persistence integration tests live in common/persistence/persistence-tests/. They use a small testify suite per backend; the same test bodies run against Cassandra, MySQL, Postgres, and SQLite. Bringing the backends up:

make start-dependencies   # Docker compose: Cassandra, MySQL, PG, ES
make stop-dependencies

The fault-injection wrapper at common/persistence/faultinjection/ wraps a real DB and randomly returns errors, used to exercise retry paths.

Functional tests

Under tests/. They:

  1. Bring up an in-process Temporal cluster via tests/testcore/.
  2. Drive it with a real Temporal SDK client (go.temporal.io/sdk).
  3. Assert on events, history, and outcomes.

They use testify suites because suite setup is non-trivial. Many functional tests are sharded across CI runners by the tools/optimize-test-sharding/ tool.

To run one functional test:

go test -tags test_dep,functional_test -v ./tests -run TestActivityApi -timeout 5m

The tests/xdc/ subdirectory holds cross-cluster (multi-DC) functional tests; they require two embedded clusters and exercise the replication path.

Coverage

make unit-test-coverage produces coverage reports uploaded to Codecov (config in .github/.codecov.yml). There is no hard percentage gate, but reviewers will ask about untested branches in critical paths (workflow state transitions, persistence retries, replication conflict resolution).

Flakiness and retries

The project has a custom flake-reporting tool at tools/flakereport/ that scrapes go-junit-report output and posts to Slack. If a test is flaky:

  • Reproduce locally with -count=10 or higher.
  • Use require.Eventually for any timing-sensitive assertion.
  • If the flake comes from upstream infrastructure (Cassandra spin-up, Docker DNS), file a CI issue rather than disabling the test.

Adding a test

For a new persistence behaviour: add a method to data_interfaces.go, regenerate mocks, write a unit test against the mock, then add a row to the matrix in persistence-tests/.

For a new gRPC API: add the proto, run make proto, write a unit test against the handler, then add a functional test under tests/.

For a new CHASM library: follow the layout in chasm/lib/ — most existing libraries (workflow, scheduler, nexusoperation) are good templates.

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

Testing – Temporal wiki | Factory