TestXxx和BenchmarkXxx函数名不可混用:前者仅被go test执行,后者仅被go test -bench=.执行;命名错误将导致静默跳过,且参数类型、执行逻辑、结果统计方式均严格区分。

TestXxx 和 BenchmarkXxx 函数名不能混用
Go 的 testing 包靠函数名前缀自动识别测试类型:以 Test 开头的函数被 go test 执行,以 Benchmark 开头的才被 go test -bench=. 执行。如果写成 TestAddBenchmark 或 BenchmarkAddTest,对应命令会直接忽略——既不报错,也不运行,容易误以为“测试通过”或“没性能问题”。
-
go test只找Test*,哪怕函数里写了b.N也会 panic(因为参数类型是*testing.T,不是*testing.B) -
go test -bench=.只找Benchmark*,Test*函数完全不参与,哪怕内容是纯性能逻辑 - 同一文件中可共存两者,但必须严格遵守命名和参数签名,否则编译期不报错、运行期静默跳过
go test 和 go test -bench=. 的执行逻辑完全不同
go test 是验证性执行:每个 TestXxx 函数只运行一次,靠 t.Errorf 等触发失败;而 go test -bench=. 是测量性执行:每个 BenchmarkXxx 函数会自动调整 b.N 值反复运行,直到总耗时稳定在 1 秒左右,再计算平均值。
- 基准测试默认不报告内存分配,需显式加
-benchmem参数才能看到B/op和allocs/op - 单元测试加
-v可看每条t.Log输出;基准测试加-v反而会抑制结果输出(只显示 PASS/FAIL),要查细节得靠-benchmem -benchtime=100ms等调优参数 - 两者都支持
-run和-bench过滤,但语法不互通:go test -run=TestAdd有效,go test -bench=TestAdd无效(必须是BenchmarkAdd)
初始化逻辑不重置,基准测试容易测偏
很多开发者在 BenchmarkXxx 函数开头做初始化(比如构造大数组、打开文件、预热缓存),却忘了调用 b.ResetTimer(),导致初始化耗时被计入最终统计,结果严重虚高。
func BenchmarkProcessData(b *testing.B) {
data := make([]int, 1e6) // 初始化开销大
b.ResetTimer() // ✅ 必须加这一行,否则 make 耗时也被计时
for i := 0; i < b.N; i++ {
_ = processData(data)
}
}
- 不加
b.ResetTimer():结果可能是1200 ns/op(含初始化) - 加了之后:真实处理耗时可能只有
85 ns/op - 同理,
b.StopTimer()和b.StartTimer()用于分段计时,比如只测某段循环内核
测试文件名和包隔离规则必须守死
所有测试代码必须放在 _test.go 文件里,且与被测代码同包(如 mymath.go 对应 mymath_test.go)。否则会出现两种典型问题:
- 单元测试报
undefined: Add:因为测试文件用了新包名(如package mymath_test),无法访问未导出函数 - 基准测试跑出 0 次迭代(
BenchmarkAdd-8 0 0 ns/op):常见于把BenchmarkXxx放在非同包的helper_test.go中,导致函数不可见 - 想测私有函数?只能放同包;想复用测试工具函数?用
internal/或xxx_test子包,但主测试仍需同包










