Skip to main content

Testing

Test types

TypeLocationBuild tagRuns by default
Unitinternal/<pkg>/*_test.gononeyes
Integrationinternal/<pkg>/*_integration_test.gointegrationonly with -tags=integration
Goldeninternal/<pkg>/testdata/<name>.goldennoneyes

Unit tests

  • One _test.go per source file.
  • Table-driven where there are 3+ similar cases.
  • Use t.Run(name, ...) subtests so failures are addressable.
  • No external dependencies (no network, no filesystem outside t.TempDir()).

Integration tests

  • For anything exercising SQLite, the state machine, and the store together.
  • Use an in-memory SQLite DB (file::memory:?cache=shared) per test — fast, isolated.
  • Migrations run once per test via storetest.New(t).
  • Build-tagged so casual go test ./... stays fast; CI runs both untagged and -tags=integration.

Golden tests

  • For report renderers and dashboard HTML.
  • Update with go test ./... -update.
  • Failures print a unified diff; do not auto-accept.

CLI tests

  • Invoke cmd/fairway as a subprocess in tests under cmd/fairway/.
  • Use t.TempDir() for repo + config + DB fixtures.
  • Assert on stdout, stderr, and exit code.

Coverage

No hard percentage gate. Instead:

  • Every public function in internal/store and internal/state has at least one test.
  • Every CLI verb has at least one end-to-end test.
  • Bug fixes include a regression test.

CI prints coverage; reviewers may push back on PRs that drop overall coverage by more than 2 percentage points.

Mocks

  • Do not mock the database. Use real SQLite in-memory.
  • Do not mock git. Use a real throwaway repo in t.TempDir().
  • The only thing we mock is the system clock, via a nowFunc func() time.Time field on the relevant struct.

Fixtures

  • testdata/ next to the package under test.
  • Small (< 10KB) fixtures committed in-tree.
  • Larger fixtures generated by go test -gen-fixtures (when needed).

Flakes

A flaky test is a broken test. If you see a flake:

  1. Open an issue with the test name and failure output.
  2. Either fix it or quarantine with t.Skip("flaky: see #N") and assign the issue.

Never t.Skip without an issue.