Go Benchmarks and Fuzzing
A benchmark is a test function that measures how fast code runs. A fuzz test is a close relative that tries many inputs to hunt for failures.
A benchmark sits beside a test
This file is a test file, so it runs with go test and has no main function. A plain run runs the test and leaves the benchmark silent.
package main
import "testing"
func TestRepeat(t *testing.T) {
got := Repeat("go", 3)
if got != "gogogo" {
t.Errorf("Repeat = %q, want %q", got, "gogogo")
}
}
func BenchmarkRepeat(b *testing.B) {
for i := 0; i < b.N; i++ {
Repeat("go", 3)
}
}A fuzz test runs its seed
This file is also a test file, so it runs with go test. The one seed added with f.Add runs as a unit test under a plain run.
package main
import "testing"
func FuzzRepeat(f *testing.F) {
f.Add("go", 2)
f.Fuzz(func(t *testing.T, word string, times int) {
if times < 0 {
return
}
got := Repeat(word, times)
if len(got) != len(word)*times {
t.Errorf("Repeat(%q, %d) has length %d", word, times, len(got))
}
})
}Example
package main
import "testing"
func TestRepeat(t *testing.T) {
got := Repeat("go", 3)
if got != "gogogo" {
t.Errorf("Repeat = %q, want %q", got, "gogogo")
}
}
func BenchmarkRepeat(b *testing.B) {
for i := 0; i < b.N; i++ {
Repeat("go", 3)
}
}
func FuzzRepeat(f *testing.F) {
f.Add("go", 2)
f.Fuzz(func(t *testing.T, word string, times int) {
if times < 0 {
return
}
got := Repeat(word, times)
if len(got) != len(word)*times {
t.Errorf("Repeat(%q, %d) has length %d", word, times, len(got))
}
})
}Key points
- A benchmark runs one function many times and reports the time for each round.
- A benchmark function starts with Benchmark and receives a *testing.B value.
- The b.N field holds the round count the tool chooses.
- Use go test with the -bench flag to run benchmarks.
- A benchmark result line shows the name, the rounds run, and ns/op, the nanoseconds for one round.
- A fuzz function starts with Fuzz and receives a *testing.F value, and its seeds are added with f.Add.
- The seeds run as unit tests under plain go test, and the -fuzz flag grows new inputs from them.
In this example, one test file holds a test, a benchmark, and a fuzz function for the same Repeat helper. A plain go test run runs TestRepeat and then runs the single fuzz seed as a unit test. The benchmark stays silent because no -bench flag was given.
Note
Benchmark numbers change from machine to machine, so they guide comparisons and never promise an exact speed.
Try it Yourself
Edit the code, then press Run.
Running is simulated ยท Go Playground
Exercise
What does the -bench flag do?