Testing
Testing is built into the toolchain: no framework to install, just the testing package and the go test command.
A basic test
Section titled “A basic test”Given math.go:
package math
func Add(a, b int) int { return a + b}Create math_test.go in the same package:
package math
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 it with:
go test ./...The _test.go suffix and Test-prefixed function name are the only conventions go test needs.
Table-driven tests
Section titled “Table-driven tests”This is the idiomatic way to cover many cases without duplicating test logic:
func TestAdd(t *testing.T) { tests := []struct { name string a, b int want int }{ {"positives", 2, 3, 5}, {"negative", -1, 1, 0}, {"zero", 0, 0, 0}, }
for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := Add(tt.a, tt.b) if got != tt.want { t.Errorf("Add(%d, %d) = %d, want %d", tt.a, tt.b, got, tt.want) } }) }}Each t.Run becomes its own named subtest, so go test -run TestAdd/negative can target a single case.
Benchmarks
Section titled “Benchmarks”func BenchmarkAdd(b *testing.B) { for i := 0; i < b.N; i++ { Add(2, 3) }}go test -bench=. -benchmemb.N is chosen automatically by the test runner to produce a stable measurement.
Coverage
Section titled “Coverage”go test -cover ./...go test -coverprofile=cover.out ./... && go tool cover -html=cover.outThe second command opens an HTML report highlighting exactly which lines your tests do and don’t exercise.