Golang Testing标准测试库指南_单元测试与基准测试基础

1次阅读

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

Golang Testing标准测试库指南_单元测试与基准测试基础

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.Fatalt.Errorf 后续语句不会执行,别放清理逻辑;清理统一走 defert.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 测试实例意外共享。

text=ZqhQzanResources