# Golang Testing

> Write, review, or debug Go tests using the standard testing package, table cases, subtests, parallel tests, fuzzing, race checks, integration isolation, HTTP utilities, examples, fixtures, and test doubles. Use when test design, reliability, or behavior is central.

- Skill: `reagin/golang-testing` (Agent Skill, multi-file: 6 files)
- Install (CLI): `npx skillmds@latest add reagin/golang-testing`
- Raw SKILL.md: https://api.skillmd.com/api/skills/reagin/golang-testing/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- License: MIT
- Author: reagin (https://skillmd.com/u/reagin)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/reagin/golang-testing

---


# Go Testing

Write tests that constrain observable behavior and produce useful failures. Match the repository's existing testing style and dependencies before introducing a new framework or generator.

## Start from the Contract

1. Read the implementation, callers, public documentation, existing tests, and nearby helpers.
2. Identify inputs, outputs, side effects, error identity, ordering, timing, concurrency, and ownership that callers can observe.
3. Choose the smallest test level that exercises the contract reliably.
4. Reproduce a bug with a failing test before changing production code when practical.
5. Avoid asserting incidental implementation details unless they are the contract under review.

## Choose a Test Shape

- Use a direct test for one behavior with a short setup.
- Use table-driven subtests when cases share the same arrange/act/assert structure and case names make failures clearer. Do not force unrelated scenarios into a large table.
- Use examples when executable documentation and rendered output are the primary value.
- Use fuzzing for parsers, codecs, state transitions, and input spaces with useful invariants. Seed important regressions.
- Use integration tests when the contract depends on a real database, filesystem, network protocol, process, or service behavior that a unit test cannot establish.
- Use benchmarks only for performance questions; functional tests should not encode fragile timing budgets.

Read [table, fuzz, and example recipes](references/table-fuzz-examples.md) when choosing concrete `t.Run`, `f.Add`/`f.Fuzz`, or `Example` shapes. Keep a table only while all cases share one readable assertion path.

## Assertions and Failures

- Prefer messages that include the operation, input or case, actual value, and expected value.
- Use `t.Fatalf` or a fatal helper only when later assertions cannot run meaningfully.
- Use `errors.Is` or `errors.As` when error identity or type is the contract. Avoid matching full error strings unless text itself is public behavior.
- Mark helpers with `t.Helper()` and register cleanup with `t.Cleanup()` when the test owns a resource.
- Bind assertion helpers to the current subtest's `*testing.T`; do not reuse a helper that captured the parent test.
- Compare structured values in a way that reports useful differences and respects semantic equality such as time instants, nil versus empty collections, or unordered results.

## Isolation and Parallelism

Each test should establish and clean up its own state. Use `t.TempDir()`, ephemeral listeners, unique database namespaces, and injected clocks or dependencies where appropriate.

Use `t.Parallel()` only after checking all shared state, environment variables, current working directory, ports, fixtures, global registries, and mutable package variables. Remember that a parallel subtest pauses until its parent returns; arrange parent-owned resources and cleanup accordingly. Run with shuffling or repetition when investigating order dependence.

For tests that interact with goroutines, synchronize on events rather than sleeps. Use the race detector and the toolchain's supported deterministic time/concurrency facilities when they fit the module target. A test timeout should bound the whole command or operation; avoid timeout helpers that leave runaway goroutines behind. See [references/helpers.md](references/helpers.md).

## Test Doubles

Prefer a small fake, stub, or function value that implements the consumer's actual dependency boundary. Mock call expectations only when the interaction sequence is itself important. Do not create production interfaces solely to satisfy a mocking framework when a simpler seam is available.

Read [references/mocking.md](references/mocking.md) when choosing among fakes, stubs, mocks, and injected functions.

## HTTP and Integration Tests

- Read [references/http-testing.md](references/http-testing.md) for handler, client, and server tests using `net/http/httptest`.
- Read [references/integration-testing.md](references/integration-testing.md) when tests require external infrastructure, schemas, migrations, build tags, or environment-dependent setup.

## Coverage, Race Detection, and Repetition

Coverage shows executed statements, not whether assertions are meaningful or every branch is tested. Use it to locate unexercised risk, not as the goal of the suite.

Typical commands, adjusted to the repository:

```bash
go test ./...
go test -race ./...
go test -shuffle=on -count=1 ./...
go test -run 'TestName/subtest' -count=1 ./path/to/pkg
go test -coverprofile=coverage.out ./...
go tool cover -func=coverage.out
```

Use repetition to reproduce flakes, but keep the exact failing seed, shuffle value, environment, and command. A passing repeated run reduces suspicion; it does not prove the absence of a race.

## Review Checklist

- Does each test fail for the intended regression?
- Are important success, boundary, and error paths covered without duplicating implementation logic?
- Are assertions attributed to the correct subtest?
- Can the test run alone, in any order, and under the race detector when relevant?
- Are cleanup and resource ownership explicit?
- Are time, randomness, network, filesystem, and external-service dependencies controlled?
- Does the test use APIs available to the module's Go target?
- Did the change add a dependency or fixture system without a demonstrated need?

