跳转到主内容
极星编程网:以代码为星,赴技术山海!

Go测试函数怎么写_Go Test函数结构解析

Go测试函数必须以Test开头且接收*testing.T参数,文件名须为xxx_test.go且包名一致;子测试用t.Run();禁用log.Fatal/os.Exit;t.Parallel()需置于函数首行。 Go 的测试函数不是靠命名约定“自动运行”的,而是必须符合
Test*
命名 +
*testing.T
参数签名,否则
go test
根本不会识别它。 Test 函数必须以 Test 开头且接收 *testing.T 这是硬性规则,缺一不可。函数名不以
Test
开头(比如叫
CheckAdd
或
testAdd
),或参数不是
*testing.T
(比如漏掉指针符号、写成
testing.T
或加了第二个参数),
go test
都会直接跳过。
func TestAdd(t *testing.T)
✅ 正确
func testAdd(t *testing.T)
❌ 小写开头,被忽略
func TestAdd(t testing.T)
❌ 缺少
*
,编译失败
func TestAdd(t *testing.T, extra string)
❌ 多余参数,编译失败 子测试用 t.Run() 而不是嵌套函数 想对同一函数多个输入做数据驱动测试?别写多个顶层
Test*
函数,也别在测试里定义匿名函数然后手动调——用
t.Run()
。它能隔离执行、独立计时、单独失败,并在
go test -v
中清晰显示子测试名。
func TestParseURL(t *testing.T) { tests := []struct { name string input string wantHost string }{ {"empty", "", ""}, {"simple", "https://example.com", "example.com"}, {"with-port", "http://localhost:8080", "localhost:8080"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { u, err := url.Parse(tt.input) if err != nil { t.Fatal(err) } if u.Host != tt.wantHost { t.Errorf("Host = %q, want %q", u.Host, tt.wantHost) } }) } }
注意:
t.Run()
内部的闭包函数仍需接收
*testing.T
,且不能用外部循环变量直接拼接
name
(比如
t.Run(fmt.Sprintf("%v", i), ...)
),否则所有子测试可能共享最后一个值——要用显式传参或局部变量捕获。 测试文件必须是 _test.go 后缀且包名一致 测试代码不能写在普通
.go
文件里,也不能放在另一个包下。必须满足: 文件名形如
xxx_test.go
  • 文件顶部 package
  • 声明和被测代码完全一致(比如被测代码是
    package calc
    ,测试文件也得是
    package calc
    ) 如果想测未导出函数(首字母小写),只能放同一个包里;跨包测试只能调用已导出标识符 例如:你写了
    add.go
    在
    calc
    包中,对应测试就得是
    add_test.go
    ,且第一行是
    package calc
    。写成
    package calc_test
    会导致编译报错或无法访问内部函数。 不要在测试里用 log.Fatal 或 os.Exit 测试过程中遇到错误,该用
    t.Fatal
    /
    t.Fatalf
    ,而不是
    log.Fatal
    或
    os.Exit(1)
    。后者会直接终止整个测试进程,导致后续测试全部跳过,且不输出标准测试报告。
    t.Fatal("failed")
    ✅ 输出错误、标记失败、继续运行其他测试
    log.Fatal("failed")
    ❌ 进程退出,剩余测试不执行
    panic("failed")
    ❌ 虽然会中断当前测试,但不保证清理,也不如
    t.Error
    系列语义清晰 另外,
    t.Log
    和
    t.Logf
    只在
    -v
    模式下输出,适合调试信息;而
    t.Error
    类会在失败时自动打印堆栈前缀,比手写
    fmt.Println
    更可靠。 最常被忽略的一点:测试函数里调用
    t.Parallel()
    时,必须确保它出现在函数最开头,且所有并行子测试都通过
    t.Run()
    启动——否则并行行为不可控,甚至引发 panic。

    相关文章