Skip to content

Go testing tiers

The Go module has three test tiers. Pick the cheapest tier that can fail on the behavior you are testing.

Tier Build tag Runs against Cost CI job
Default none Fakes and in-process code Seconds moon battery
pgtest pgtest A real Postgres Minutes per package pgtest
podman e2e podman The real stack and the real agent image Tens of minutes e2e

The exact commands and flags are in the pgtest and e2e jobs of .github/workflows/ci.yml.

  1. Does the assertion need real SQL: a query, a constraint, RLS, a migration? Use pgtest.
  2. Does it need the process or container topology: stack children, the runner, an agent turn, teardown? Use podman e2e.
  3. Otherwise use the default tier.

A tagged test that cannot reach its dependency skips. CI checks that the pgtest and podman suites actually ran, so a skip there does not pass silently.

The entry point is pgtest.RequireDSN(t) (go/internal/pgtest). Open your own store on the DSN it returns. It finds Postgres in this order:

  • COMPASS_TEST_DATABASE_DSN points at a running Postgres. Each test gets a fresh schema, dropped when the test ends. CI uses this.
  • COMPASS_TEST_USE_CONTAINER=1 starts a throwaway container. Use this locally.
  • With neither set, it fails when a container runtime exists, and skips when none does. CI sets COMPASS_REQUIRE_LIVE=1, so there a missing database fails.

For tests that must go through a transaction-mode pooler, use pgtest.RequirePoolerDSN(t). It needs both COMPASS_TEST_DATABASE_DSN and COMPASS_TEST_POOLER_DSN in URL form, and gives each test a fresh database.

Fixture-based legs live in go/e2e. cmd/compass-stack also has podman-tagged supervisor tests that do not use the fixture.

In go/e2e, TestMain builds the stack binaries once and starts one suite Postgres. Each leg starts with a podmanUsable check and skips when rootless podman cannot run the agent image.

Most legs call sharedFixture(t). Every such leg in the run uses one stack, which attaches to the suite Postgres through ExternalDatabase.

  • Register options the shared stack needs from a register<Leg>FixtureOptions function listed in TestMain. Never register from a leg body: canned routes are fixed when the stub is built. A registered option applies to every shared leg.
  • You can register WithForgeStub() and the WithCanned* options. WithObjectStore needs a *testing.T to start, so it is own-stack only.
  • Route each model turn by a marker unique to your leg. The positional canned script is one counter shared by every leg.
  • Await every turn your leg starts before it returns, so no model request outlives the leg.
  • -count above 1 is not supported; CI runs with -count=1. In a full run, zz_legsix_test.go closes the shared stack at the end of each pass, so a later pass cannot reach it. Without leg six, handles are create-only and the stack persists, so the second pass fails with already_exists.

Call NewFixture(ctx, t, opts...) when the leg needs a stack nobody else touches, such as a restart, a teardown check, or object-store state. It costs a full cold start: its own stack-owned Postgres, server and runner.

  • WithSite(site) reuses one root, state dir and port across two NewFixture calls, so the second Up reattaches the same Postgres data.
  • WithEmbeddedPostgres() states that the leg needs the stack-owned Postgres. Plain NewFixture already uses it; the option fails the test if an external database is also set.
  • WithForgeStub(), WithObjectStore(g) and the WithCanned* options apply to this leg only.

zz_legsix_test.go closes the shared stack before its restart, so it must run last. Its file name sorts it last, and it skips under -shuffle.

Shared legs use the suite Postgres. Other own-stack legs use the stack-owned Postgres but do not check its lifecycle. TestEmbeddedPostgresSmoke is the only leg that asserts the supervisor-owns-Postgres lifecycle and its pgid-record teardown: the record names a live Postgres group after Up, and after Down the group is gone and the record is removed. Keep it when you change how the stack starts or stops Postgres.

  • Design record: docs/designs/infra/ci/compass-test-harness-tiers/design.md.
  • CI jobs: Build & CI.