17370845950

Go测试中如何跳过用例 Golang Skip用法说明
t.Skip() 是测试中跳过当前用例的最常用方式,需在测试函数内直接调用,执行后立即终止并标记

为 skipped,不影响其他测试运行。

测试函数里直接调用 t.Skip() 跳过当前用例

最常用的方式是在测试函数内部根据条件主动跳过。比如某功能只在 Linux 下可用,Windows 下就跳过:

t.Skip() 执行时,测试会立即终止,标记为 “skipped”,不会报错也不会继续执行后续语句。

  • 必须在测试函数(func TestXxx(t *testing.T))中调用,不能在 goroutine 或子函数里直接传 t 后调用 —— 否则 panic:"testing: t.Skip now forbidden"
  • t.Skip()t.Skipf() 都会中断当前测试,但后者支持格式化消息,例如 t.Skipf("not supported on %s", runtime.GOOS)
  • 跳过不影响其他测试用例运行,整个 go test 流程照常继续

go test -skip 不存在,正确方式是用 -run 或构建标签

Go 原生不支持类似 go test -skip=TestFoo 这样的命令行跳过选项。想临时屏蔽某些用例,只有两个可靠路径:

  • -run 指定要运行的测试名(正则匹配),间接“跳过”未被匹配的,例如 go test -run=^TestBar$ 就只跑 TestBar
  • 用构建标签(//go:build !unit)配合文件级控制,把不想跑的测试放到 xxx_test.go 文件顶部加 //go:build skip,再用 go test -tags=skip 忽略整批
  • 别写 if false { t.Skip() } 来硬屏蔽 —— 这属于隐藏逻辑,CI 或他人调试时极难发现

t.SkipNow() 在辅助函数中安全跳过

如果判断逻辑封装在公共函数里(比如检查环境、依赖服务是否就绪),不能直接调用 t.Skip(),因为 t 是测试函数的局部变量。这时要用 t.SkipNow() 的配套机制:

  • 辅助函数接收 *testing.T 并调用 t.SkipNow() —— 它和 t.Skip() 行为一致,但明确表示“立刻退出当前测试函数”
  • 切记不要用 return 代替 t.SkipNow():那样测试会继续执行,可能引发空指针或误判
  • 示例:
    func requireLinux(t *testing.T) {
        if runtime.GOOS != "linux" {
            t.SkipNow() // 不加这行,下面代码仍会执行
        }
    }

跳过 vs 标记为失败:别混淆 t.Skip()t.Fatal()

跳过(Skipped)和失败(Failed)在 CI 报告、覆盖率统计、go test 返回码上完全不同:

  • t.Skip() 返回码仍是 0(成功),CI 不红;t.Fatal() 返回 1,CI 立刻中断
  • 覆盖率工具(如 go tool cover)对跳过用例中的代码行不计入统计 —— 即使那些行实际没被执行,也不会拉低覆盖率数字
  • 如果某个用例因外部依赖不稳定而频繁跳过,说明它不该是单元测试,该拆到集成测试阶段,或改用 testify/suite 等框架做环境隔离

真正容易被忽略的是:跳过状态不会传播到子测试(t.Run())。每个子测试需独立决定是否跳过,父测试里的 t.Skip() 对子测试无效。