Go测试函数怎么写_Go Test函数标准写法

6次阅读

go测试函数必须命名为TestXxx且参数为*testing.T,定义在_test.go文件中、同包名下;需用t.Error/Fatal报告失败,推荐表驱动测试。

Go测试函数怎么写_Go Test函数标准写法

Go测试函数必须叫TestXxx,且参数固定为*testing.T

Go的测试函数不是随便命名的,必须以Test开头,后接**大写字母开头的驼峰名**(如TestAddTestParseURL),不能是test_addtestAdd。函数签名也严格限定为func(t *testing.T)——少一个星号、换类型、加参数都会导致go test直接忽略该函数。

常见错误现象:go test运行后显示no tests to run,但文件里明明写了函数——八成是命名不合规或参数不对。

  • 函数必须定义在_test.go结尾的文件中(如math_test.go
  • 函数必须是包级导出函数(首字母大写),但名字本身不需导出,TestXxx已满足导出要求
  • 不能用*testing.B代替*testing.T,那是基准测试用的

t.Errorft.Fatal报告失败,别用panic或log

测试中检查逻辑失败时,必须调用t.Error*系列方法,比如t.Errorf("expected %v, got %v", want, got)。这些方法会标记当前测试失败,但允许继续执行后续断言;而t.Fatal*会立即终止当前测试函数。

绝对不要在测试里写paniclog.Fatalos.Exit——它们会让go test无法正确统计失败数,甚至中断整个测试套件。

  • t.Error:记录错误,继续执行
  • t.Fatal:记录错误,立刻返回(适合前置条件不满足,如文件不存在)
  • t.Log:只输出日志,不影响测试结果
  • 所有t.*方法只能在测试函数内调用,不能传给子函数再调(除非显式传*testing.T

表驱动测试是Go推荐写法,用Struct切片组织用例

Go标准库和主流项目几乎都用表驱动(table-driven)方式写测试,把输入、期望输出、说明打包进一个结构体切片,然后range循环执行。这样比重复写一TestXxx1/TestXxx2更易维护、覆盖更全。

func TestSplit(t *testing.T) {     tests := []struct {         name  string         input string         sep   string         want  []string     }{         {"empty", "", ",", []string{}},         {"single", "a", ",", []string{"a"}},         {"multi", "a,b,c", ",", []string{"a", "b", "c"}},     }     for _, tt := range tests {         t.Run(tt.name, func(t *testing.T) {             got := Split(tt.input, tt.sep)             if !reflect.DeepEqual(got, tt.want) {                 t.Errorf("Split() = %v, want %v", got, tt.want)             }         })     } }

注意:t.Run创建子测试,让每个用例独立显示、可单独运行(如go test -run=TestSplit/empty),还能避免变量闭包陷阱(循环中tt被复用)。

测试文件路径和包名要和被测代码对齐

测试文件必须和被测代码在**同一目录**,且声明相同的包名(通常是package xxx,不是package xxx_test)。只有想测试包私有符号(如未导出函数、变量)时,才需要另建xxx_internal_test.go并用package xxx_test——但这属于高级用法,日常80%场景不需要。

  • 错误做法:把http_test.go放在test/子目录下 → go test找不到
  • 错误做法:测试文件写package main → 编译失败
  • 如果被测代码在cmd/mytool/下,测试文件也得放那儿,不能挪到根目录

路径和包名错一个字符,测试就静默失效——这是最常被忽略的硬性约束。

text=ZqhQzanResources