testing.short() 是信号灯而非开关,需在每个测试函数首行主动检查并调用 t.skip() 才能跳过;子测试须单独判断,t.skip() 比 return 更语义清晰且支持日志归类。

testing.Short() 不是开关,是信号灯
它只返回 true 或 false,不会自动跳过任何测试。加了 go test -short 后,所有测试照常执行——除非你在每个测试函数里主动检查并退出。
常见错误是只写 if testing.Short() { } 却没调用 t.Skip() 或 return,结果数据库连接、HTTP server 启动已经失败,测试直接 panic。
- 必须在
func TestXxx(t *testing.T)进入后第一行判断 - 不能放在
defer里——太晚,资源可能已分配失败 - 不能在
TestMain里调用——那里没有*testing.T - 不能在 goroutine 中调用
t.Skip()——会 panic
t.Skip() 要比 return 更合适
t.Skip() 和 return 都能终止当前测试,但语义和行为有关键差异:
-
t.Skip("reason")明确标记为 skipped,CI 日志里可过滤归类;return是静默退出,无记录 - 两者都会执行已注册的
defer,但t.Skip()更清晰表达“有意跳过”,尤其配合t.Cleanup()时逻辑更可靠 - 别写
if testing.Short() { t.Skip(); defer cleanup() }——defer应在t.Skip()前注册,或统一用t.Cleanup()
子测试(t.Run)必须单独判断 Short
testing.Short() 的返回值不传递给子测试,父测试里查一次,子测试里不查,照样跑满 5 秒。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
错误写法:t.Run("slow", func(t *testing.T) { /* 没检查 Short,直接跑耗时逻辑 */ })
- 每个
t.Run函数体开头都要独立调用if testing.Short() { t.Skip(...) } - 别在父测试里用
t.Skip()一刀切——会失去对快/慢用例的粒度控制 - 子测试中调用
t.Skip()只影响该子测试,不影响其他兄弟或父测试
哪些测试适合加 Short 判断?
不是所有慢测试都该跳,重点看是否满足:「本地开发/CI 快反馈阶段可安全省略,且不影响核心逻辑验证」。
- 依赖真实 DB、Redis、HTTP 外部服务的集成测试
- 启动
httptest.Server或监听端口的端到端测试 - 生成 GB 级测试文件、执行复杂计算的性能敏感用例
- 涉及定时器、超时等待、重试循环的逻辑验证
真正容易被忽略的是:跳过逻辑必须出现在 setup 之前。哪怕只差一行,也可能导致连接池已建、临时目录已创建、goroutine 已泄漏。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










