Golang 从入门到放弃 -0x10
Go 测试基础、表驱动测试和 benchmark,让代码不再全靠信仰。
很多人刚学编程时,对测试的态度都差不多:这玩意听起来挺重要,但今天先不写,明天再说。结果明天一忙,后天一改,测试就永远活在嘴上了。Go 在测试这块其实挺友好,标准库自带一套够你起步的工具。
最基本的单元测试
测试文件通常以 _test.go 结尾,函数名以 Test 开头。
package calc
import "testing"
func TestAdd(t *testing.T) {
got := Add(1, 2)
want := 3
if got != want {
t.Fatalf("want %d, got %d", want, got)
}
}然后跑:
go test ./...这个命令很值得背下来。它会从当前模块开始,把所有包的测试都跑一遍。
表驱动测试
Go 社区特别喜欢表驱动测试。说白了,就是把一组输入输出摆成表,再循环跑。好处是结构整齐,新增 case 也方便。
func TestAdd(t *testing.T) {
cases := []struct {
name string
a int
b int
want int
}{
{name: "positive", a: 1, b: 2, want: 3},
{name: "zero", a: 0, b: 0, want: 0},
{name: "negative", a: -1, b: -2, want: -3},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got := Add(tc.a, tc.b)
if got != tc.want {
t.Fatalf("want %d, got %d", tc.want, got)
}
})
}
}写多了你会发现,这种风格特别适合边界值、异常输入、各种小变体一起测。
测错误也很重要
别只测 happy path。出错分支往往更值得写测试,因为它平时不常走,一旦出事就特别容易让人掉坑里。
func TestDivideByZero(t *testing.T) {
_, err := Divide(10, 0)
if err == nil {
t.Fatal("expect error, got nil")
}
}Benchmark 也顺手看看
如果你关心某段代码的性能,可以写 benchmark。函数名以 Benchmark 开头。
func BenchmarkAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
Add(1, 2)
}
}执行:
go test -bench=.不过先提醒一句,benchmark 很容易被误读。看见数字漂亮不代表线上就一定快,看见数字一般也不代表就一定有问题。它更适合拿来比较“改前改后”有没有退化。
测试不是越多越神圣
很多初学者会走两个极端:
- 完全不写测试
- 什么 getter/setter 都测,写得比业务还累
我更推荐先测这些:
- 核心业务函数
- 边界条件
- 容易回归的 bug
- 涉及错误返回和分支判断的逻辑
把测试写在刀刃上,比追求覆盖率数字更实际。
小结
这一章先把最常用的基础打稳:
_test.go+TestXxx是标准入口。- 表驱动测试是 Go 里非常常见的写法。
- 错误分支别忽略。
- Benchmark 用来比较性能变化,不是用来许愿。
下一章我们聊配置、环境变量和日志。程序能跑起来只是开始,能不能把自己说清楚,也很重要。