testing.short() 是一个由 go test -short 触发的布尔函数,需配合 t.skip() 或 return 才能跳过测试;它不自动跳过,仅提供 flag 状态判断依据。

testing.Short() 是什么,它真能跳过测试吗
它不是“跳过测试”的开关,而是让你自己决定是否跳过——testing.Short() 返回一个布尔值,由 go test -short 命令触发。没加这个 flag 时它始终返回 false,加了才返回 true。你得主动用 if 判断并调用 t.Skip() 或提前 return,否则它什么都干不了。
常见错误现象:go test -short 运行后耗时测试依然执行、超时、甚至 panic;原因是只写了 if testing.Short() { ... } 却没调用 t.Skip() 或没提前退出。
- 必须搭配
t.Skip()或return才生效,光判断没用 - 推荐写法是开头就检查:
if testing.Short() { t.Skip("skipping in short mode") } - 不能在子测试(
t.Run())内部再用testing.Short()做条件分支来“跳过部分子测试”——它反映的是整个go test进程的 flag 状态,不是每个子测试独立可控
哪些测试适合用 testing.Short() 控制
典型场景是那些依赖外部服务、生成大量数据、或做密集计算的测试——比如调用真实 HTTP API、启动本地数据库、跑 Monte Carlo 模拟、解压大文件等。它们不该出现在 CI 快反馈循环里,但又不能删掉,因为需要定期验证。
不适用的情况:纯内存计算、小数据结构验证、接口契约检查——这些本就该快,加 testing.Short() 反而增加认知负担。
立即学习“go语言免费学习笔记(深入)”;
- 网络 I/O 类:HTTP client 测试指向真实 endpoint、gRPC 集成测试
- 存储类:SQLite 文件读写、临时目录下生成 GB 级测试数据
- 时间敏感类:sleep 100ms 等待重试、模拟长时间轮询
- 注意:不要用它掩盖性能差的单元测试——先优化逻辑,再考虑跳过
和 -timeout、-run 的关系别搞混
-short 和 -timeout 是正交机制:-timeout 是硬性熔断,超时直接 fail;-short 是软性协商,靠你代码配合跳过。两者可以共存,但行为不叠加。
容易踩的坑:go test -short -timeout=1s 并不会让短模式自动变更快——如果某个测试没检查 testing.Short(),它照样会跑满 1 秒然后被 kill。
-
-run匹配测试名,-short是全局开关,优先级无关——go test -run=TestFoo -short仍会进入TestFoo,只是你可以在里面决定跳不跳 - CI 中建议固定用
go test -short -timeout=30s ./...,既防挂起,又给短模式留出判断空间 - 本地开发时,别依赖
-short来“加速调试”,它只适合跳过,不适合替代精准-run或-v -count=1
实际写法示例与参数陷阱
最简安全模板就长这样,复制粘贴也不容易错:
func TestExpensiveAPICall(t *testing.T) {
if testing.Short() {
t.Skip("skipping API test in short mode")
}
resp, err := http.Get("https://api.example.com/health")
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
}
关键细节:
-
t.Skip()必须在t.Parallel()之前调用,否则 panic:“cannot skip during parallel test” - 别在
init()或包级变量初始化里调用testing.Short()——它只在测试函数运行时有效,此时*testing.T尚未构造 - 子测试中同样适用,但注意
t.Skip()只跳当前子测试,不影响父测试或其他子测试 - Go 1.21+ 支持
t.Setenv()等新方法,但testing.Short()行为没变,别误以为新版能自动跳过
真正难的不是写对这三行,而是每次新增耗时测试时,都记得补上这个判断——漏一次,CI 就多等两分钟。










