Go 1.7 引入的 t.Run() 是组织测试用例最自然、最推荐的方式,支持逻辑分组、嵌套层级、独立生命周期控制(如跳过、清理、并行)、精准命令行执行及清晰输出。
Go 1.7 引入的 t.Run() 是组织和分组测试用例最自然、最推荐的方式。它让测试结构更清晰、输出更易读,还能独立控制每个子测试的生命周期(如设置/清理、跳过、超时)。
在单个测试函数中,通过多次调用 t.Run(name, func(t *testing.T)) 定义多个子测试。每个子测试有独立名称,运行时会显示为 TestXxx/SubtestName 形式。
例如验证字符串处理函数的不同场景:
func TestParseDuration(t *testing.T) {
tests := []struct {
name string
input string
expected time.Duration
wantErr bool
}{
{"zero", "0s", 0, false},
{"seconds", "30s", 30 * time.Second, false},
{"invalid", "1y", 0, true},
}
for _, tt := range tests {
tt := tt // 避免循环变量捕获问题
t.Run(tt.name, func(t *testing.T) {
d, err := time.ParseDuration(tt.input)
if (err != nil) != tt.wantErr {
t.Fatalf("ParseDuration(%q) error = %v, wantErr %v", tt.input, err, tt.wantErr)
}
if !tt.wantErr && d != tt.expected {
t.Errorf("ParseDuration(%q) = %v, want %v", tt.input, d, tt.expected)
}
})
}
}子测试可以递归调用 t.Run(),形成多级分组。适合按功能模块 + 场景进一步拆解:
立即学习“go语言免费学习笔记(深入)”;
TestAuth)"Login", "Logout", "RefreshToken")"Login/ValidCredentials", "Login/EmptyPassword")运行时可通过 go test -run=TestAuth/Login/ValidCredentials 精准执行某条路径。
每个子测试拥有独立的 *testing.T 实例,因此可安全使用以下方法而不影响其他子测试:
t.Skip() 或 t.Skipf():跳过当前子测试(比如只在 CI 中运行的集成测试)t.Cleanup(func()):注册清理函数,子测试结束时自动执行(比 defer 更可靠)t.Setenv(key, value):临时修改环境变量,退出子测试后自动还原t.Parallel():标记子测试可并行执行(注意共享状态需加锁或避免)子测试名称支持通配符和路径匹配,大幅提升调试效率:
go test -run=TestParseDuration/seconds —— 运行指定子测试go test -run=TestParseDuration/invalid —— 快速复现错误分支go test -run=^TestAuth/Login$ —— 用正则匹配完整名称(需转义 ^$)go test -v —— 查看详细子测试执行顺序和耗时输出示例:--- PASS: TestParseDuration (0.00s)
--- PASS: TestParseDuration/zero (0.00s)
--- PASS: TestParseDuration/seconds (0.00s)
--- PASS: TestParseDuration/invalid (0.00s)