testing.short 是 go 的布尔函数,用于检测是否启用 -short 标志;应在集成、i/o 密集或依赖外部服务的测试中主动配合 t.skip 使用,以支持 ci 快速验证和本地开发提速。

testing.Short 是什么,什么时候该用它
testing.Short 是 Go 标准测试框架提供的一个布尔函数,返回 true 当前测试以短模式运行(即加了 -short 标志),否则为 false。它不是用来“跳过测试”的开关,而是让你主动判断是否该跳过——Go 不会自动跳过任何测试,你得自己写逻辑。
常见场景是:集成测试、IO 密集型测试(如启动 HTTP 服务、读写大文件)、依赖外部服务(数据库、Redis)的测试。这些在 CI 或日常开发快速验证时没必要跑。
别把它当成“魔法开关”,它只是个信号灯,要不要停车,得你自己踩刹车。
怎么在测试里正确使用 testing.Short
在测试函数开头调用 testing.Short,配合 t.Skip 主动退出:
func TestExpensiveDatabaseQuery(t *testing.T) {
if testing.Short() {
t.Skip("skipping expensive test in short mode")
}
// 实际耗时测试逻辑
db := setupTestDB()
rows, _ := db.Query("SELECT * FROM huge_table LIMIT 10000")
defer rows.Close()
}
关键点:
- 必须在测试函数体最开始检查,避免前置 setup 已经执行(比如已建好数据库连接)
-
t.Skip是安全退出,不会报错,也不会影响其他测试 - 不要用
return替代t.Skip,否则测试计数器可能出错,go test会误判失败
为什么 t.Run 子测试里也要单独检查 Short
子测试(t.Run)是独立的测试单元,父测试的 testing.Short() 结果不传递给子测试。如果你在父测试里只检查一次,然后在子测试里直接跑耗时逻辑,就失效了。
func TestWithSubtests(t *testing.T) {
if testing.Short() {
t.Skip("skipping whole test") // ❌ 错误:粗暴跳过全部,失去粒度控制
}
t.Run("fast_case", func(t *testing.T) {
// 这个可以保留
})
t.Run("slow_integration", func(t *testing.T) {
if testing.Short() { // ✅ 正确:每个子测试独立判断
t.Skip("skipping slow subtest")
}
// 耗时操作
})
}
容易踩的坑:
- 在子测试外统一跳过,导致本可快速执行的子测试也被砍掉
- 忘记在子测试里重查
testing.Short(),结果go test -short下仍执行了慢测试
CI 和本地开发中怎么配合使用
go test -short 是约定俗成的“轻量测试”命令,在 CI 流水线里普遍用于 PR 阶段快速反馈。但要注意:
-
-short不影响 benchmark(go test -bench默认不跑 benchmark,需显式加-bench=.) - 它和
-race、-cover可共存,例如:go test -short -race ./... - 有些团队会把耗时测试放在单独目录(如
integration/),用go test ./integration显式控制,这时testing.Short就不是必须的——但混合在同一个包里时,它仍是简单可靠的分流手段
真正容易被忽略的是:短模式下跳过的测试,不会出现在 go test -json 输出里,日志或监控工具如果只看输出流,可能误以为“所有测试都跑了”。需要确保你的可观测性链路知道哪些测试被主动跳过了。











