Coverage, Race Detector & Golden Files
Cover profiles, -race in CI, and snapshot testing.
Search across all documentation pages
Cover profiles, -race in CI, and snapshot testing.
Coverage tells you what code ran; the race detector tells you if concurrent access was unsafe; golden files snapshot expected output for regressions.
Together they strengthen CI when paired with meaningful assertions, not as vanity metrics alone.
Quick-reference recipe card - copy-paste ready.
go test -race -coverprofile=coverage.out ./...
go tool cover -func=coverage.out
go test -update ./... # pattern: custom flag updates golden filesfunc TestRenderGolden(t *testing.T) {
got := Render()
want, err := os.ReadFile("testdata/render.out")
if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(string(want), got); diff != "" {
t.Fatalf("diff:\n%s", diff)
}
}When to reach for this:
package report
import (
"flag"
"os"
"path/filepath"
"strconv"
"sync"
"testing"
)
var updateGolden = flag.Bool("update", false, "update golden files")
var cache = struct {
mu sync.Mutex
m map[string]int
}{m: make(map[string]int)}
func Inc(key string) {
cache.mu.Lock()
cache.m[key]++
cache.mu.Unlock()
}
func FormatReport(keys []string) string {
out := ""
for _, k := range keys {
cache.mu.Lock()
n := cache.m[k]
cache.mu.Unlock()
out += k + ":" + strconv.Itoa(n) + "\n"
}
return out
}
func TestIncRaceSafe(t *testing.T) {
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
Inc("x")
}()
}
wg.Wait()
}
func TestFormatReportGolden(t *testing.T) {
Inc("a")
Inc("a")
Inc("b")
got := FormatReport([]string{"a", "b"})
path := filepath.Join("testdata", "report.golden")
if *updateGolden {
if err := os.WriteFile(path, []byte(got), 0644); err != nil {
t.Fatal(err)
}
}
want, err := os.ReadFile(path)
if err != nil {
t.Fatal(err)
}
if string(want) != got {
t.Fatalf("golden mismatch\n--- want\n%s--- got\n%s", want, got)
}
}What this demonstrates:
go test -race exercises TestIncRaceSafe with instrumentationtestdata/ captures formatted output-update flag rewrites goldens intentionally after reviewcache-coverprofile.go tool cover -html colors lines green/red for manual gap analysis.| Flag | Effect |
|---|---|
-cover | Summary percent per package |
-coverprofile=file | Write profile for go tool cover |
-covermode=atomic | Accurate counts under parallelism |
-coverpkg=./... | Include non-test packages in profile |
go test -race -timeout=10m ./...Run on Linux CI agents; macOS/Windows support exists but Linux is the common default.
import "github.com/google/go-cmp/cmp"
if diff := cmp.Diff(want, got); diff != "" {
t.Fatalf("mismatch (-want +got):\n%s", diff)
}go-cmp produces readable golden diffs for structs and JSON.
-update hides bugs. Fix: Treat golden diffs like code review material.testdata/ by convention.t.Parallel().| Alternative | Use When | Don't Use When |
|---|---|---|
| Structured assertions only | Small stable JSON APIs | Large CLI transcripts |
httptest body string compare | HTTP snapshots | Binary output |
| Mutation testing (go-mutesting) | Test quality audit | Everyday CI cost |
| Production tracing | Real concurrency bugs | Pre-merge unit signal |
No universal percent - track trend on core packages.
Require tests for new exported APIs and error branches.
No - it catches data races, not deadlocks or logic bugs.
Combine with stress tests and timeouts.
Use build tags on generated files or filter profiles in CI scripts.
Do not skip testing wrappers that contain logic.
Yes - go tool covdata (Go 1.20+) merges profiles from parallel CI jobs.
testdata/ is conventional and excluded from normal binaries.
Subdirs per test are fine.
Do not auto-update in CI - fail and let developers run locally with -update.
Prevents silent acceptance of bad output.
Mostly yes with caveats.
Pure Go race coverage is more predictable; test cgo packages explicitly.
Both live under testdata/.
Fuzz files reproduce crashes; goldens reproduce expected output.
Increase from default when integration tests spawn many goroutines.
-timeout=10m is a common starting point.
Use go tool cover -html or gopls coverage integration when enabled.
HTML report is the portable baseline.
Small JSON responses - decode and assert fields.
Large HTML templates - golden files with reviewed diffs.
See ci-quality-gates-lint-test-race-vuln for ordering race, vuln, and lint with tests.
-race smoke introStack 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 16, 2026