Go单元测试需严格遵循命名规范:测试文件名必须为*_test.go,函数名必须为TestXxx形式(Xxx首字母大写);推荐使用t.Run组织表驱动测试,避免全局状态和外部依赖以确保稳定可靠。
Go 的单元测试不需要额外框架,go test 命令原生支持,但必须遵守命名和结构约定,否则测试文件不会被识别、函数不会被运行。
测试文件名和函数签名必须严格匹配 *_test.go 和 TestXxx
Go 只扫描以 _test.go 结尾的文件,并只执行函数名符合 Test 开头 + 首字母大写的函数(如 TestAdd)。小写开头(testAdd)、下划线后非大写(Test_add)、或没加 Test 前缀(AddTest)都会被忽略。
- 正确示例:
calculator_test.go中定义func TestAdd(t *testing.T) - 错误示例:
test_calculator.go、func testAdd(t *testing.T)、func Testadd(t *testing.T) - 注意:测试文件应与被测包同目录,除非是
example_test.go这类特殊用途
t.Run 是组织子测试的唯一可靠方式,不用它容易漏测或误判
单个测试函数里混写多个逻辑断言(比如连续调用 t.Errorf),一旦前面失败,后续逻辑仍会执行,但错误堆栈不清晰;而用 t.Run 可隔离场景、支持并行(t.Parallel())、且失败时能精准定位到子测试名。
- 推荐写法:
t.Run("positive numbers", func(t *testing.T) { ... }) - 避免写法:在同一个
TestAdd里硬编码三组输入然后逐个if !equal { t.Error(...) } - 子测试名不要含空格或特殊字符,否则
go test -run过滤可能出错,例如t.Run("1+2=3", ...)不如用"one_plus_two"
表驱动测试(table-driven tests)是 Go 单元测试的事实标准
把输入、期望输出、描述封装成结构体切片,配合 t.Run 循环执行,代码简洁、易扩展、diff 友好。相比每个 case 写一个函数,维护成本低得多。