章节

15.2 子测试

本篇学习 t.Run 子测试与表格驱动测试,并能用一组用例测试同一个函数。

子测试

概念说明

子测试通过 t.Run 把一个测试函数拆成多个命名场景。
它常与表格驱动测试一起使用,让多组输入输出更清晰。

每个子测试都有独立名称。
测试失败时,可以快速定位是哪一个场景失败。

语法/规则

  1. 使用 t.Run(name, func(t *testing.T) { ... }) 创建子测试。
  2. 用结构体切片保存多组测试用例。
  3. 子测试名称要表达场景含义。
  4. 循环变量传入闭包时要注意捕获问题。
  5. 可以用 go test -run TestName/SubName 只运行某个子测试。

子测试示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package calc

import "testing"

func Add(a, b int) int {
	return a + b
}

func TestAdd(t *testing.T) {
	cases := []struct {
		name string
		a    int
		b    int
		want int
	}{
		{name: "positive", a: 1, b: 2, want: 3},
		{name: "zero", a: 0, b: 2, want: 2},
	}

	for _, item := range cases {
		item := item // 避免闭包直接复用循环变量
		t.Run(item.name, func(t *testing.T) {
			got := Add(item.a, item.b)
			if got != item.want {
				t.Fatalf("got %d, want %d", got, item.want)
			}
		})
	}
}

运行命令:

1
go test -v

输出结果:

1
PASS

常见错误

  1. 子测试名称都写成空字符串,失败时不好定位。
  2. 表格用例字段太模糊,看不出输入和期望输出。
  3. 并行子测试中没有处理循环变量捕获,导致测试数据错乱。
本文禁止转载
使用 Hugo 构建
主题 StackJimmy 设计 由 Hobin 魔改
最近构建时间:2026-04-17 19:07:48 CST
载入天数...载入时分秒...
发表了 1 篇文章 · 发表了 152 篇笔记 · 总计 18 万 0 千字