go测试靠约定运行,testxxx函数需首字母大写以被反射识别为导出符号;_test.go文件必须与被测代码同包;表驱动测试中tc := tc防止闭包复用;-v控制输出详细度,-run控制执行范围;禁用panic/log.fatal以免破坏测试框架功能。

Go测试是 Go 语言原生内置的轻量级验证机制,不是第三方库,也不依赖配置文件或服务进程——它靠约定运行,写对位置、起对名、签对函数,go test 就能自动发现并执行。
TestXxx 函数为什么必须首字母大写?
因为 Go 的测试发现器只识别以 Test 开头、且紧随其后的字符是**大写字母**的函数。例如 TestAdd 合法,testAdd 或 Testadd 都不会被识别。
- 底层逻辑是:Go 测试框架通过反射扫描导出(exported)符号,而只有首字母大写的标识符才是导出的
- 包内未导出的
testHelper函数,即使签名正确,也会被跳过 - 常见错误:在重构时把
TestHTTPClient改成testHTTPClient,结果go test安静地什么也不跑
_test.go 文件必须和被测代码同包吗?
必须。测试文件可以放在任意目录,但 package 声明必须与被测代码完全一致,比如被测文件是 package utils,测试文件也得是 package utils,不能写成 package test 或 package utils_test(后者常用于内部测试隔离,但属于进阶用法,不是默认规则)。
- 误放目录 + 错包声明 = 测试函数“存在但不可见”,
go test返回no tests to run - 想测
main包?没问题,只要测试文件也在package main下,且不冲突func main() - 跨包调用私有函数?不行。测试代码无法访问非导出名,这是 Go 的封装边界,不是测试框架限制
表驱动测试里 tc := tc 这一行到底在防什么?
它防的是 Go 循环变量复用导致的闭包陷阱——所有子测试最终都引用同一个 tc 地址,结果全跑最后一条用例。
- 不加这行:10 个
t.Run全部执行的是切片末尾那个 case - 加了才真正实现“每个子测试独占一份数据”
- 这个坑在并发测试(
t.Parallel())下更隐蔽,失败现象是随机某几个 case 结果错乱
go test -v 和 go test -run=TestAdd 有什么实际区别?
-v 控制输出详细程度(verbose),-run 控制执行范围,两者经常一起用,但作用完全不同。
-
go test:静默运行,只在失败时打印摘要 -
go test -v:成功也打印每条t.Log、t.Logf和 PASS 行,适合调试中间状态 -
go test -run=TestAdd:只跑名字匹配正则TestAdd的函数(支持通配符,如-run=^TestAdd$精确匹配) - 组合使用最常见:
go test -v -run=TestAddTableDriven,既聚焦又可见细节
panic 或 log.Fatal——它们会让测试提前退出,导致 go test 无法统计失败数、无法触发 t.Cleanup、也无法生成覆盖率报告。该用 t.Fatalf 的地方,别手快敲成 panic。










