Go 入门(18):Go 单元测试——testing 包与表驱动测试
更新时间:2026-09-01。本文是
languages/go/beginner/入门层第 18 篇,接 panic 与 recover。Go 内置testing包,go test命令运行测试,不需要第三方测试框架。表驱动测试是 Go 社区常用的模式,本篇讲清楚。
本文要回答的问题
- 测试文件名怎么命名?后缀为什么是
_test.go? - 测试函数怎么写?参数
*testing.T做什么? - 什么是表驱动测试?为什么 Go 社区喜欢表驱动?
go test命令常用参数有哪些?
一、测试文件命名
Go 约定:
- 测试文件:
xxx_test.go,放在同一个包下 - 测试函数:
func TestXxx(t *testing.T) {},Xxx 大写开头
示例结构:
utils/
add.go
add_test.go_test.go 文件在 go build 时不会被编译进二进制,只有 go test 会编译它。
二、最简单的测试用例
go
// add.go
package utils
func Add(a, b int) int {
return a + b
}go
// add_test.go
package utils
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)
}
}运行:
bash
go test
# 输出:ok your/package 0.001s三、表驱动测试:Go 推荐模式
当你要测试多个输入输出案例时,用一张"表"放所有案例,循环测试:
go
func TestAdd(t *testing.T) {
// 案例表
cases := []struct {
name string
a, b int
want int
}{
{"positive", 2, 3, 5},
{"zero", 0, 0, 0},
{"negative", -1, 1, 0},
{"both negative", -1, -2, -3},
}
// 循环每个案例
for _, c := range cases {
// 用 t.Run 开一个子测试
t.Run(c.name, func(t *testing.T) {
got := Add(c.a, c.b)
if got != c.want {
t.Errorf("got %d, want %d", got, c.want)
}
})
}
}为什么 Go 社区喜欢表驱动测试:
- 所有案例放在一起,一目了然
- 添加新案例只需要加一行
- 避免重复写代码
- 每个案例可以单独运行(
go test -run TestAdd/positive)
四、测试错误
go
func TestDiv(t *testing.T) {
_, err := Div(10, 0)
if err == nil {
t.Error("expected error for division by zero, got nil")
}
}t.Errorf 打印错误,标记测试失败,继续跑其他案例;t.Fatalf 直接标记失败,不继续跑这个测试了。
五、常用 go test 参数
bash
go test ./... # 递归测试当前目录下所有包
go test -v # 详细输出,打印每个测试名
go test -run="Add.*" # 只运行名字匹配的测试
go test -cover # 输出覆盖率
go test -bench="." # 运行基准测试六、基准测试(性能测试)
go
func BenchmarkAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
Add(2, 3)
}
}运行基准测试:
bash
go test -bench="."
# 输出:
# BenchmarkAdd-8 1000000000 0.25 ns/opb.N 是 Go 自动确定的循环次数,运行足够长时间得到稳定结果。
七、常见坑对照
| 坑 | 现象 | 对策 |
|---|---|---|
| 测试函数名字写错 | 测试不被运行 | TestXxx,第一个字母大写 |
文件不是 _test.go | 测试被编进二进制 | 后缀必须是 _test.go |
表驱动不使用 t.Run | 一个案例失败整个测试结束 | 每个案例用 t.Run 开子测试 |
| 依赖外部网络/文件 | 单元测试依赖环境,不能离线 | 单元测试不要依赖外部,mock 掉 |
相关与延伸
下一篇:goroutine 基础——go 关键字创建轻量级线程;基准测试和性能剖析结合,见 pprof 性能剖析;Go 内置
testing够大部分场景用,复杂 mocking 才需要第三方库。
一句话总结
Go 单元测试:xxx_test.go 文件放测试,测试函数 func TestXxx(t *testing.T);t.Errorf 报告错误,t.Fatalf 终止;多个输入输出用表驱动测试,切片定义案例,循环遍历,每个案例 t.Run 开子测试;go test 运行测试,go test ./... 递归跑所有,-bench 跑基准测试。Go 内置就够用,不用第三方框架。