Skip to main content

test

📅 2026-02-05 ✏️ 2026-03-07 CS GO
No related notes

0.1 · go test 命令(go help test)#

用法go test [build/test flags] [packages] [flags & test binary flags]

  • 对指定包做自动化测试,输出每包摘要(ok/FAIL + 耗时),失败时再打详细输出。
  • 会编译 *_test.go;以 _. 开头的文件被忽略。testdata 目录被忽略,可放测试数据。
  • 构建前会跑 go vet 子集(atomic、bool、printf、tests 等),有问题则不运行测试。-vet=off 关闭,-vet=all 全开。
  • 测试的 stdout/stderr 会汇总到 go test 的 stdout。

两种模式

模式触发缓存
本地目录无包参数(go test / go test -v
包列表显式包(go test . / ./... / math

缓存:仅当仅用可缓存标志时生效(如 -run-bench-v-count-timeout 等)。禁用缓存常用 -count=1

go test 自有标志-c 只编译不运行;-o file 指定二进制路径;-args 后参数原样传测试二进制(包列表须在 -args 前);-json 输出 JSON;-exec xprog 用 xprog 跑二进制。

go test -v -args -x            # -args 后原样传测试二进制
pkg.test -test.v -test.cpuprofile=prof.out   # 直接跑二进制时用 test. 前缀

0.2 · testing 包(go doc testing)#

0.2.1 · 四种函数形式

形式用途
func TestXxx(*testing.T)单元测试,用 t.Error/t.Fail 报告失败
func BenchmarkXxx(*testing.B)基准,提供 -bench 时顺序执行
func FuzzXxx(*testing.F)模糊测试,随机/变异输入
func ExampleXxx()示例,用 stdout + // Output: 校验
  • 测试文件:*_test.go,普通 build 不包含。同包可访问未导出符号;package pkg_test 为黑盒,只能访问导出符号。
  • 更多:go help testgo help testflag

0.2.2 · TestXxx#

  • 跳过t.Skip();例 if testing.Short() { t.Skip("...") },配合 go test -short
func TestTimeConsuming(t *testing.T) {
    if testing.Short() {
        t.Skip("short 模式下跳过")
    }
    // ...
}
  • 子测试Subtestst.Run(name, func(t *testing.T) { ... }),可表驱动、共用 setup/tear-down。名字为「顶层/子名」层级。
func TestFoo(t *testing.T) {
    // <setup code>
    t.Run("A=1", func(t *testing.T) { ... })
    t.Run("A=2", func(t *testing.T) { ... })
    t.Run("B=1", func(t *testing.T) { ... })
    // <tear-down code>
}
go test -run Foo/A=    # 顶层匹配 Foo,子测试匹配 A=
go test -run /A=1      # 所有顶层的子测试匹配 A=1
  • -run:未锚定正则,按 / 分层;go test -run=FuzzFoo/种子id 可调试种子。
  • 并行:子测试里 t.Parallel();父测试等所有子测试完成。可用 t.Run("group", ...) 再在外部做 tear-down。

0.2.3 · BenchmarkXxx#

  • 新写法用 b.Loop() 包住被测代码;旧写法 for i := 0; i < b.N; i++,昂贵初始化前调 b.ResetTimer()
  • 并行:b.RunParallel(func(pb *testing.PB) { for pb.Next() { ... } }),常配 -cpu
  • 子基准:b.Run(name, func(b *testing.B) { ... })
func BenchmarkRandInt(b *testing.B) {
    for i := 0; i < b.N; i++ { rand.Int() }
}
// 输出 BenchmarkRandInt-8  68453040  17.8 ns/op 表示循环 68453040 次,约 17.8 ns/op

func BenchmarkBigLen(b *testing.B) {
    big := NewBig()
    b.ResetTimer()
    for i := 0; i < b.N; i++ { big.Len() }
}

并行基准(常配 -cpu):

func BenchmarkTemplateParallel(b *testing.B) {
    templ := template.Must(template.New("test").Parse("Hello, {{.}}!"))
    b.RunParallel(func(pb *testing.PB) {
        var buf bytes.Buffer
        for pb.Next() {
            buf.Reset()
            templ.Execute(&buf, "World")
        }
    })
}

子基准Sub-benchmarks):b.Run(name, func(b *testing.B) { for i := 0; i < b.N; i++ { ... } }),多组参数可写表驱动。

0.2.4 · FuzzXxx#

模糊测试:随机/变异输入找 bug。种子:(*F).Addtestdata/fuzz/<Name>;target 参数类型与 Add 一致。无效输入可 t.Skip()。失败输入会写回 testdata/fuzz/<Name>

func FuzzHex(f *testing.F) {
    for _, seed := range [][]byte{{}, {0}, {9}, {0xa}, {0xf}, {1, 2, 3, 4}} { f.Add(seed) }
    f.Fuzz(func(t *testing.T, in []byte) {
        enc := hex.EncodeToString(in)
        out, err := hex.DecodeString(enc)
        if err != nil { t.Fatalf("%v: decode: %v", in, err) }
        if !bytes.Equal(in, out) { t.Fatalf("%v: round trip", in, out) }
    })
}

0.2.5 · ExampleXxx#

  • // Output:// Unordered output: 与 stdout 比较(忽略首尾空白)。无注释则只编译不执行。
  • 命名:ExampleExampleFExampleTExampleT_M;多示例加后缀如 Example_suffix
func ExamplePrintln() {
    Println("The output of\nthis example.")
    // Output: The output of
    // this example.
}
func ExamplePerm() {
    for _, v := range Perm(4) { fmt.Println(v) }
    // Unordered output: 4
    // 2
    // 1
    // 3
    // 0
}

0.2.6 · TestMain#

若定义 func TestMain(m *testing.M),生成的 main 调用它而非直接跑测试;在 main goroutine 里 setup/tear-down 并 m.Run()。用标志时需在 TestMain 里 flag.Parse()

func TestMain(m *testing.M) {
    // flag.Parse() 若依赖命令行标志
    os.Exit(m.Run())
}

0.3 · Testing flags(go help testflag)#

参考:Testing flags

标志说明
-run regexp只运行匹配的测试
-bench regexp运行匹配的基准;默认不跑,-bench . 跑全部
-benchtime t基准时长,默认 1s;Nx 为 N 次
-fuzz regexp / -fuzztime t模糊测试及时长
-cpu 1,2,4GOMAXPROCS 组合
-count n执行次数
-parallel nt.Parallel() 的最大并发数
-timeout d超时 panic,0 禁用
-v详细输出
-short可配合 testing.Short() 跳过耗时测试
-cover / -covermode / -coverpkg覆盖率
-benchmem基准内存分配
-cpuprofile / -memprofile写出 profile 给 go tool pprof

对 test 二进制可用 test. 前缀,如 pkg.test -test.v -test.cpuprofile=out


0.4 · 表驱动与并行示例

// 表驱动:每行输入+预期,可带 name
tests := []struct {
    input, sep string
    want       []string
}{
    {"a/b/c", "/", []string{"a", "b", "c"}},
    {"abc", "/", []string{"abc"}},
}
for _, tc := range tests {
    t.Run(tc.input, func(t *testing.T) {
        got := Split(tc.input, tc.sep)
        if !reflect.DeepEqual(tc.want, got) {
            t.Fatalf("expected: %v, got: %v", tc.want, got)
        }
    })
}

// 并行子测试(注意 tc := tc 避免闭包捕获)
for _, tc := range tests {
    tc := tc
    t.Run(tc.Name, func(t *testing.T) {
        t.Parallel()
        // ...
    })
}

0.5 · pkg for test#

HTTP 测试示例(httptest + 表驱动):

func Test_helloHandler(t *testing.T) {
    tests := []struct{ name, param, expect string }{
        {"base", `{"name":"liwenzhou"}`, "hello liwenzhou"},
        {"bad", "", "we need a name"},
    }
    r := SetupRouter()
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            req := httptest.NewRequest("POST", "/hello", strings.NewReader(tt.param))
            w := httptest.NewRecorder()
            r.ServeHTTP(w, req)
            assert.Equal(t, http.StatusOK, w.Code)
            var resp map[string]string
            json.Unmarshal(w.Body.Bytes(), &resp)
            assert.Equal(t, tt.expect, resp["msg"])
        })
    }
}

0.6 · coverage / tricks / 可测代码#


0.7 · 参考链接

类别链接
官方Testing flagsgo.dev/doc/fuzzgo help testtest2json(-json 编码)
子测试/子基准SubtestsSub-benchmarks
Benchmarkdesign/14313-benchmark-formatgolang.org/x/perf/cmd
FuzzFuzzing (wiki)draft-fuzzingFuzzing in Go最佳实践
Mock/Stubmock vs stub (SO)Mocks Aren’t Stubs
testifyhttptestgockhttpmockgo-sqlmockminiredisgomockgostubmonkeygomonkeygoconveyAssertions
技巧与可测性benbjohnson/testingGo 测试技巧povilasvwireAbsolute unit testLearn Go with TestsTestCommentsIntegration testing with Docker