patterngoTip
Table-driven tests in Go
Viewed 0 times
table-driven testst.Runsubteststest casesparallel testsGo testing
Problem
Writing a separate test function for each input/output combination is repetitive and makes it hard to see the full coverage at a glance.
Solution
Use table-driven tests with t.Run for subtests:
func TestAdd(t *testing.T) {
tests := []struct {
name string
a, b int
want int
}{
{"positive", 1, 2, 3},
{"negative", -1, -2, -3},
{"zero", 0, 0, 0},
}
for _, tc := range tests {
tc := tc // capture range var (pre-Go 1.22)
t.Run(tc.name, func(t *testing.T) {
t.Parallel() // optional: run subtests in parallel
got := Add(tc.a, tc.b)
if got != tc.want {
t.Errorf("Add(%d, %d) = %d, want %d", tc.a, tc.b, got, tc.want)
}
})
}
}Why
Table-driven tests centralise test cases, make adding new cases trivial, and produce clear output (PASS/FAIL per subtest name). t.Run enables parallel execution and isolated failure reporting.
Gotchas
- t.Parallel() inside t.Run pauses the subtest until all non-parallel tests in the parent finish — combine with the range variable capture
- If a subtest calls t.Fatal, only that subtest stops — the table loop continues
- Use testify/assert for richer assertions, but the standard library is sufficient for most cases
Revisions (0)
No revisions yet.