Testing with go test

Table-driven tests

Go tests live in files ending with _test.go next to the code they check. A table test lists inputs and expected outputs in a slice, then loops over the rows, so adding a case means adding one line.

First, the code under test in main.go:

package main import "fmt" func Add(a, b int) int { return a + b } func main() { fmt.Println(Add(2, 3)) }

Next, the table test in main_test.go, in the same package:

package main import "testing" func TestAdd(t *testing.T) { tests := []struct { a int b int want int }{ {1, 2, 3}, {0, 0, 0}, {-1, 1, 0}, } for _, tc := range tests { if got := Add(tc.a, tc.b); got != tc.want { t.Errorf("Add(%d, %d) = %d, want %d", tc.a, tc.b, got, tc.want) } } }

Each row names its inputs and the expected answer, and Errorf reports the exact mismatch. Name every test with the Test prefix so the tool discovers it automatically.

go test -v

Run the suite with go test, and add -v to watch each test by name. A passing run prints PASS lines, while failures show the file and line of every broken expectation.

go test -v

=== RUN TestAdd
--- PASS: TestAdd (0.00s)
PASS
ok hello 0.004s

The tool runs every Test function in the package and summarizes the result on the last line. Keep the suite green at all times: a failing test you ignore teaches the team to ignore all of them.

Coverage

Coverage counts which lines your tests execute. Ask for a percentage while you work, and open the HTML report when you want the exact lines painted as covered or missed.

go test -cover

ok hello 0.004s coverage: 100.0% of statements

Every statement of Add runs under TestAdd, so the report shows full marks. Treat 100 percent as a hint, not a proof: it measures visited lines, not the quality of your expectations.

Benchmarks

Benchmarks measure speed the same way tests check truth: name the function with a Benchmark prefix and loop to b.N. The tool scales the loop and reports nanoseconds per operation, so compare numbers before and after each optimization.

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

go test -bench=. -benchtime=100x

BenchmarkAdd-8 1000000 1050 ns/op

The Add from main.go is reused here without changes. Benchmarks share the package with tests, so fast checks and slow measurements live side by side.

Next: Advanced errors

Article author: Arthur Isaev

Banner image