测试与工具
用标准 testing 与工具链保证可回归。
测试文件与 TestXxx
测试文件名以 _test.go 结尾,与被测包同目录(或 package xxx_test 做黑盒测试):
// mathutil/mathutil.go
package mathutil
func Add(a, b int) int { return a + b }
// mathutil/mathutil_test.go
package mathutil
import "testing"
func TestAdd(t *testing.T) {
got := Add(1, 2)
if got != 3 {
t.Fatalf("Add(1,2)=%d, want 3", got)
}
}
go test ./...
go test -v ./mathutil
失败用 t.Error / t.Fatal(Fatal 立刻结束当前测试)。子测试:t.Run("name", func(t *testing.T) { ... })。
表驱动测试
把输入输出列成表,一次覆盖多例:
func TestAddTable(t *testing.T) {
cases := []struct {
name string
a, b int
want int
}{
{"positive", 1, 2, 3},
{"zero", 0, 0, 0},
{"neg", -1, 1, 0},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
if got := Add(tc.a, tc.b); got != tc.want {
t.Fatalf("got %d want %d", got, tc.want)
}
})
}
}
这是 Go 社区最常见的测试风格。
覆盖率、基准与竞态
go test -cover ./...
go test -coverprofile=cover.out ./...
go tool cover -html=cover.out
基准测试函数名以 Benchmark 开头:
func BenchmarkAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
Add(1, 2)
}
}
go test -bench=. -benchmem ./mathutil
数据竞争检测:
go test -race ./...
开发机上对并发相关包定期跑 -race;CI 也可打开(更慢)。并发心智见「并发」。
其他:go vet ./... 做静态检查;go test -count=1 禁用缓存强制 重跑。
小结
_test.go+TestXxx+go test ./...- 优先表驱动 +
t.Run -cover看覆盖;Benchmark看性能- 并发代码加上
-race