go test, list & generate
go test runs package tests, go list introspects what the build system sees, and go generate triggers code generation hooks you define beside source files.
Search across all documentation pages
go test runs package tests, go list introspects what the build system sees, and go generate triggers code generation hooks you define beside source files.
Testing is first-class in the toolchain: no external runner is required for unit tests, benchmarks, examples, or fuzz targets.
go list exposes packages, dependencies, tags, and module versions as machine-readable JSON for scripts and CI.
go generate runs //go:generate directives, usually shelling out to tools installed with go install.
Together they form the daily loop: list what exists, generate what is stale, test what changed.
Quick-reference recipe card - copy-paste ready.
# Run all tests with race detector and coverage
go test -race -cover ./...
# Run one test by name with verbose output
go test -run TestParseConfig -v ./internal/config
# List packages as JSON for scripting
go list -json ./...
# Run all generators in the module
go generate ./...When to reach for this:
go test ./... as the default CI gate before merge.go list -f templates to build SBOM or ownership reports.go generate after changing protobuf, stringer, or mock definitions.go test -bench when optimizing hot paths with reproducible numbers.// mathutil/sum.go
package mathutil
func Sum(nums []int) int {
total := 0
for _, n := range nums {
total += n
}
return total
}// mathutil/sum_test.go
package mathutil
import "testing"
func TestSum(t *testing.T) {
got := Sum([]int{1, 2, 3})
if got != 6 {
t.Fatalf("got %d want 6", got)
}
}
func BenchmarkSum(b *testing.B) {
data := make([]int, 1000)
for i := range data {
data[i] = i
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
Sum(data)
}
}// api/doc.go
package api
//go:generate go run golang.org/x/tools/cmd/stringer@latest -type=Kind
type Kind int
const (
KindHTTP Kind = iota
KindGRPC
)go test -cover ./mathutil
go test -bench=. -benchmem ./mathutil
go list -f '{{.ImportPath}} tags={{.BuildTags}}' ./...
go generate ./apiWhat this demonstrates:
t.Fatalf for fast failure.b.ResetTimer() excluding setup work.go list -f custom template for inventory scripts.//go:generate colocated with the type it maintains.go test compiles a test main that links _test.go files, then executes the binary and streams results.-count=1.go list loads packages without necessarily linking; -json emits structs for automation.go generate scans for //go:generate lines and runs commands in file order; it does not track staleness itself.| Flag | Purpose |
|---|---|
-run regexp | Filter tests, benchmarks, fuzz by name |
-race | Enable race detector |
-cover | Print coverage percentage |
-coverprofile=file | Write coverage profile for go tool cover |
-bench regexp | Run benchmarks matching pattern |
-benchmem | Report allocations in benchmarks |
-timeout d | Kill tests after duration (default 10m) |
-count n | Run each test n times; 1 disables pass cache |
-shuffle on | Randomize test order to expose coupling |
| Template field | Meaning |
|---|---|
.ImportPath | Canonical import path |
.Dir | Directory on disk |
.GoFiles | Production .go files selected by tags |
.TestGoFiles | _test.go files in package |
.Deps | Transitive import paths |
.Module | Module metadata when in module mode |
//go:generate (no space before go).git diff checks in CI.go run tool@version over undocumented local binaries for reproducibility.go test without ./... runs everything - bare . is only the current package. Fix: go test ./... from module root.go test -count=1 while debugging; fix root cause before merging.-benchmem - allocation regressions stay invisible. Fix: add -benchmem and compare with benchstat.go generate in CI without checking diffs - drift merges silently. Fix: run generate in a job that fails on non-empty git diff.package foo_test cannot access unexported symbols. Fix: test exported API or use internal test package package foo.jq on go list -json output in scripts.| Alternative | Use When | Don't Use When |
|---|---|---|
gotestsum | JUnit XML and prettier CI logs | Standard go test -v is enough locally |
make generate | Team wants one entry for many generators | go generate ./... already covers the module |
buf generate / protoc direct | Protobuf pipelines with their own plugins | Simple stringer/mockgen hooks in Go files |
golangci-lint run | Lint beyond compiler and vet | You only need the stdlib test runner |
func TestXxx(t *testing.T) asserts correctness.
func BenchmarkXxx(b *testing.B) measures performance and runs b.N iterations.
func FuzzXxx(f *testing.F) seeds inputs then mutates them to find crashes.
Run with go test -fuzz=FuzzName (Go 1.18+).
Yes.
func ExampleXxx() in _test.go files are compiled and optionally checked for stdout with // Output: comments.
Build tags filter sources.
Files with //go:build ignore never appear in .GoFiles.
No.
You invoke it explicitly or from CI/Makefile hooks.
Mark long tests with if testing.Short() { t.Skip() } and run CI with -short.
Passed test results stored under GOCACHE.
Changing sources or flags invalidates entries; failures are not cached.
Yes, but package main tests often live in main_test.go beside main.go.
Consider extracting logic into importable packages for easier testing.
go list -m all from module root.
In workspace mode, run from the workspace root to include every module in go.work.
Yes.
Use go run pkg@version in directives so teammates and CI resolve the same tool.
go test and go list examplesStack versions: This page was written for Go 1.26.x (Green Tea GC default, go fix modernizers - verify patch at build), chi (latest - verify at build), gin (latest - verify at build), echo (latest - verify at build), google.golang.org/grpc (latest - verify at build), sigs.k8s.io/controller-runtime (latest - verify at build), kubebuilder (latest - verify at build), tinygo (latest - verify board targets at build), wazero (latest - verify at build), and golangci-lint (latest - verify linter set at build).
Reviewed by Chris St. John·Last updated Jul 18, 2026