Go testing needs no third-party framework: any function named TestXxx (taking a single *testing.T parameter) inside a file named *_test.go is automatically discovered and run by go test. The same mechanism extends to benchmarks (BenchmarkXxx, taking *testing.B) and example tests that double as documentation.
A basic test
A test file lives alongside the code it tests, named xxx_test.go. It calls t.Errorf (or t.Fatalf to stop immediately) to report a failure — there's no assertion library built in, though many projects add one.
package mathutil
import "testing"
func TestAdd(t *testing.T) {
got := Add(2, 3)
want := 5
if got != want {
t.Errorf("Add(2, 3) = %d, want %d", got, want)
}
}Run with go test in the package directory, or go test ./... to test every package in a module.
Table-driven tests
The idiomatic way to test many input/output cases without repeating code is a table-driven test: a slice of structs describing each case, looped over with t.Run to name and isolate each one.
func TestAdd(t *testing.T) {
cases := []struct {
name string
a, b int
expected int
}{
{"positive", 2, 3, 5},
{"negative", -1, -1, -2},
{"zero", 0, 0, 0},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
if got := Add(tc.a, tc.b); got != tc.expected {
t.Errorf("got %d, want %d", got, tc.expected)
}
})
}
}Benchmarks
A function named BenchmarkXxx taking *testing.B and looping b.N times measures performance; go test -bench=. runs it and reports time per operation, with the framework automatically adjusting b.N until the measurement is statistically stable.
func BenchmarkAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
Add(2, 3)
}
}