Learn Go← Dashboard

Built-in testing: go test, table tests, benchmarks, fuzzing.

Benchmarks and Fuzz Tests

Beyond regular tests, Go's testing package ships two more tools:

  • Benchmarks — measure performance.
  • Fuzz tests — generate random inputs and look for crashes / failures.

Both live in _test.go files. Names matter: Benchmark… and Fuzz….

Benchmarks

A benchmark function receives *testing.B. The runner calls it with increasing values of b.N until it gets a stable timing.

func BenchmarkAdd(b *testing.B) {
    for i := 0; i < b.N; i++ {
        Add(2, 3)
    }
}

Run benchmarks with:

go test -bench=.           # run benchmarks in current package
go test -bench=. -benchmem # also report allocations

Sample output:

BenchmarkAdd-8     1000000000     0.305 ns/op    0 B/op    0 allocs/op
  • 0.305 ns/op — average wall-clock per iteration.
  • B/op and allocs/op — bytes and allocations per iteration (needs -benchmem).

Fuzz tests (Go 1.18+)

A fuzz test takes a "seed corpus" and generates random inputs around it, looking for inputs that crash or break invariants.

func FuzzReverse(f *testing.F) {
    f.Add("hello")
    f.Fuzz(func(t *testing.T, s string) {
        r := Reverse(s)
        if Reverse(r) != s {
            t.Errorf("not stable: %q", s)
        }
    })
}
go test -fuzz=FuzzReverse   # run forever until it finds a failure or you Ctrl+C

When fuzzing finds a failing input, it writes a regression case into testdata/fuzz/... so the failure is reproducible in regular runs.

Comparing benchmarks: benchstat

To know whether a change actually improved things, save the output and use benchstat:

go test -bench=. -count=10 > old.txt
# ... make your change ...
go test -bench=. -count=10 > new.txt
benchstat old.txt new.txt

This runs each benchmark 10 times and reports the change with statistical significance — so you don't chase noise.

go playground
Loading...