go测试函数名和文件名必须严格匹配:文件以_test.go结尾,函数为test开头且首字母大写、参数为*testing.t;测试文件须与被测代码同目录同包;表驱动测试应使用显式命名的结构体切片,每个子测试需用t.run并注意闭包变量捕获;error、float64、time.time等类型须专用比对方式。

Test函数名和文件名必须严格匹配go test的识别规则
go test不会自动发现测试,它只扫描满足两个硬性条件的函数:文件名以_test.go结尾,且函数名是Test开头、首字母大写的func TestXxx(t *testing.T)。漏掉任意一个,命令行就显示no tests to run——不是失败,是压根没加载。
常见错误包括:testAdd()(小写开头)、Test_add()(下划线破坏导出规则)、func TestAdd()(缺*testing.T参数)。这些都不会报编译错误,但测试静默失效。
- 测试文件必须和被测代码在
同一目录、同一包下,才能直接调用未导出函数 - 不要把所有
_test.go塞进单独的test/子目录——go test会找不到它们 -
go build自动忽略_test.go,无需担心污染生产二进制
表驱动测试必须用[]struct{}定义数据,不能用map或匿名结构体
Go没有参数化测试语法,表驱动本质是靠结构体切片+循环模拟。但结构体定义方式直接影响可维护性:用map[string]interface{}或struct{}匿名声明,IDE无法跳转、go vet不检查字段拼写、失败时打印不出字段名。
正确写法是显式命名字段,例如函数ParseURL(s string) (*url.URL, error),对应结构体就该是:
tests := []struct {
name string
input string
wantHost string
wantErr bool
}{
{"empty", "", "", true},
{"valid", "https://example.com", "example.com", false},
}
- 字段名要跟被测函数语义对齐,别用泛称如
in/out - 所有字段尽量导出(首字母大写),否则调试时
fmt.Printf("%+v", tt)看不到值 - 禁用
nil指针字段直接塞进结构体——比如input *Config为nil,而被测函数没防御,就会panic
t.Run()不是可选项,而是隔离失败、支持并发、允许过滤的基础设施
漏掉t.Run(),所有用例共享同一个*testing.T实例:一个t.Fatal()就终止整个函数,后续用例全跳过;go test -run=TestParse/valid也完全失效。
每个子测试必须传非空name,且建议含关键输入摘要(如fmt.Sprintf("host=%s", tt.input)),而不是"case1"。
- 循环内必须写
tt := tt再传入闭包,否则所有子测试看到的都是最后一次迭代的tt值 -
t.Parallel()必须放在t.Run()的函数体内,放外面无效 - 临时资源(如
t.TempDir()、mock初始化)必须在t.Run()里创建,不能提前提取到循环外 - 子测试失败时,错误信息会精确到
TestParse/host=https://example.com,而不是笼统的TestParse
error、float64、time.Time等类型必须用专用方式比对
直接用==比error或reflect.DeepEqual比float64,是表驱动测试里最常触发误报的地方。
典型错误写法:if err != tt.wantErr(tt.wantErr是bool,但err是error类型);或者if got != tt.want用于浮点数比较。
- error判断分三层:有无 →
(err != nil) != tt.wantErr;类型匹配 →errors.Is(err, io.EOF);字段断言 →errors.As(err, &myErr) && myErr.Code == 400 - float64加
tolerance float64字段,比较用math.Abs(got - tt.want) - time.Time必须用
.Equal(),DeepEqual会因单调时钟或时区差异失败 - 结构体含
sync.Mutex、函数字段、unsafe.Pointer时,禁用reflect.DeepEqual,手动比关键字段
真实项目里最容易被忽略的,是结构体字段的“空值兜底”——比如input []string字段在某个case里设成nil,而被测函数没做nil检查,测试直接panic,连错误信息都来不及输出。这类问题不会出现在编译期,只能靠你在填充tests切片后加一行校验。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











