go test未运行test函数因文件名非_test.go、函数签名不符(须为func testxxx(t *testing.t))、或不在同包;t.log总输出,应改用t.Errorf内联上下文;b.n由框架自动调整以稳定基准耗时约1秒。

Go test 命令为什么没跑你的 Test 函数?
Go 测试文件必须以 _test.go 结尾,且 Test 函数签名必须严格匹配:func TestXxx(t *testing.T) —— 首字母大写的函数名、唯一参数类型为 *testing.T。小写开头(如 testFoo)或参数不对(比如多传了个 int),go test 直接无视。
- 测试文件放在和被测代码同一包下(不加
package xxx_test),才能直接访问未导出函数/变量 - 如果用了
package xxx_test(白盒测试变黑盒),只能测导出符号,但能避免循环导入 -
go test默认只运行当前目录的测试;子目录需显式指定:go test ./...或go test ./subdir - 常见错误现象:
no tests to run—— 先检查文件名、函数签名、是否在 GOPATH / Go module 根下
如何让 t.Log 和 t.Error 在失败时才输出?
t.Log 总是打印,但干扰调试;真正需要的是「仅失败时才暴露上下文」。用 t.Helper() + 条件日志不是解法,正确姿势是:把关键中间值塞进错误信息里,或用 t.Errorf 的格式化能力直接内联。
-
t.Log("request:", req, "response:", resp)→ 无论成败都刷屏,CI 日志爆炸 - 改用:
t.Errorf("failed on input %v: got %v, want %v", input, got, want),失败时自动带堆栈和上下文 - 想临时看某分支逻辑?加个
if testing.Verbose() { t.Log(...) },然后跑go test -v - 注意:
t.Fatal和t.Errorf后续语句不会执行,别放清理逻辑;清理统一走defer或t.Cleanup
基准测试中 b.N 是什么?为什么不能手动设?
b.N 是 Go 基准框架自动确定的循环次数,目标是让单次基准耗时稳定在 1 秒左右。它不是你控制的迭代数,而是结果——框架会先试跑、再放大 N 直到总耗时接近 1s,最后用 ns/op 衡量性能。
- 手动写
for i := 0; i 代替 <code>b.N→ 基准失去可比性,go test -bench不识别,且无法自动调优 - 必须用
for i := 0; i ,且循环体里不能有 I/O、sleep、随机等待等非受控操作 - 想排除初始化开销?用
b.ResetTimer()放在 setup 之后、循环之前 - 常见坑:
b.ReportAllocs()要提前加,否则内存分配统计不生效;-benchmem才显示 alloc 数值
测试并发时 t.Parallel() 的真实行为
t.Parallel() 不是“开 goroutine”,而是告诉测试主程序:“这个测试可以和其他标记了 Parallel 的测试一起跑”。实际调度由 go test 控制,且默认并发度受 GOMAXPROCS 和测试总数影响。
立即学习“go语言免费学习笔记(深入)”;
- 没调
t.Parallel()的测试串行执行;调了的,彼此之间并行,但每个仍独占一个*testing.T实例 - 共享资源(如全局 map、文件、端口)必须加锁或隔离,否则竞态检测器(
go test -race)会报Data Race - 父子测试关系:
t.Run("sub", ...)内部再调t.Parallel()是允许的,但父测试不能Parallel后再Run非 Parallel 子测试(会 panic) - 容易忽略:
go test -p=1强制串行,go test -p=4限制最多 4 个测试并行 —— 这会影响t.Parallel()的实际效果
并发测试的真实复杂点不在语法,而在状态隔离。哪怕只是复用一个 sync.Pool,也得确认它没被多个 Parallel 测试实例意外共享。