Testing with go test
| Table-driven tests | |
| go test -v | |
| Coverage | |
| Benchmarks |
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