go单元测试依赖go test和testing包,命名需严格匹配(_test.go、testxxx、*testing.t),t.error继续执行而t.fatal终止,推荐t.run表驱动测试,-v查看日志,-cover统计覆盖率,依赖需接口抽象以保证快速隔离。

Go 语言单元测试不需要框架,go test 命令配合标准 testing 包就能覆盖 95% 的场景;加第三方测试库反而容易破坏隔离性、掩盖设计缺陷。
测试文件和函数命名必须严格匹配
不满足命名规则的测试代码会被 go test 完全忽略,且不报错——这是最常被误以为“测试没跑”的原因。
- 文件名必须以
_test.go结尾(如math_test.go),不能是test_math.go或math-tests.go - 测试函数名必须是
TestXxx形式:首字母大写的Test+ 大写开头的后缀(如TestAdd),testAdd、Test_add、TESTADD全部无效 - 函数签名必须是
func TestXxx(t *testing.T):少一个*、多一个参数、类型写成testing.T(没指针)都不行 - 测试文件必须和被测代码在同一个包下(比如
calc.go在main包,calc_test.go也得声明package main)
t.Error 和 t.Fatal 的行为差异直接影响调试效率
它们不是“轻重错误”之分,而是“是否继续执行当前测试函数”的开关。用错会导致漏掉大量失败用例。
-
t.Error记录错误并继续运行后续语句,适合单个测试函数里检查多个断言(比如验证返回值 + 验证 error 是否为 nil) -
t.Fatal立即终止当前测试函数,适合前置校验失败(如配置加载失败、临时文件无法创建),但后面必须跟return,否则可能 panic - 在循环中遍历测试用例时,绝不能直接用
t.Fatal—— 第一个失败就中断,其余 case 全被跳过;应改用t.Errorf+ 显式continue或重构为t.Run子测试
用 t.Run 写表驱动测试是 Go 最推荐的组织方式
硬写一堆 TestAdd1/TestAdd2 很难维护,而表驱动 + t.Run 能让每个用例独立失败、单独重跑、错误信息带上下文。
- 测试数据用结构体切片定义,必含
name字段,传给t.Run(tt.name, ...) - 循环内必须写
tt := tt,否则闭包会捕获最后一次迭代的值,所有子测试看到的都是同一个tt - 错误信息要打印具体输入和期望值:
t.Errorf("Add(%d,%d) = %d, want %d", tt.a, tt.b, got, tt.want),而不是模糊的"got wrong result" - 支持按名称筛选运行:
go test -run TestAdd/正数相加,快速复现特定 case
go test 默认静默通过,-v 是日常开发必备参数
全绿时 go test 只输出 ok 0.001s,没有任何中间日志——这不是卡住,是默认行为。调试时容易误判。
- 加
-v参数才能看到每个测试函数的执行过程:go test -v - 想看中间值?用
t.Log或t.Logf,fmt.Println的输出会被测试框架丢弃 - 覆盖率用
go test -cover,但注意它只统计实际执行到的代码行,if false { }这类死代码不计入 - 并发子测试要加
t.Parallel(),但加了之后就不能调用t.Skip或t.Fatal,否则 panic
真正难的从来不是怎么写 TestXxx,而是怎么把依赖(HTTP client、DB、time.Now)抽成接口、再注入进去——这决定了你的测试能不能真正 fast & isolated。别指望框架替你做这件事。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











