Go 语言 子测试 与子基准测试 Subtest
子测试 又叫 命名测试 named tests 意味着 现在可以拥有 嵌套测试 这对于自定义(和过滤)给定测试的示例非常有用

T 和 B 的 Run 方法允许定义 子单元测试 和 子基准测试 而不必为每个子测试和子基准定义单独的函数
这使得可以使用 Table-Driven 的基准测试和创建层级测试 还提供了一种共享通用 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>
}
每个子测试和子基准测试都有一个唯一的名称
顶级测试的名称和传递给 Run 的名称的组合 以斜杠分隔 并具有用于消歧的可选尾随序列号

-run 和 -bench 命令行标志的参数是与测试名称相匹配的非固定的正则表达式
对于具有多个斜杠分隔元素(例如子测试)的测试 该参数本身是斜杠分隔的
其中表达式依次匹配每个名称元素 因为它是非固定的 一个空的表达式匹配任何字符串 例如 使用 "匹配" 表示 "其名称包含"
go test -run ''      # Run 所有测试
go test -run Foo     # Run 匹配 "Foo" 的顶层测试 例如 "TestFooBar"
go test -run Foo/A=  # 匹配顶层测试 "Foo" 运行其匹配 "A=" 的子测试
go test -run /A=1    # 运行所有匹配 "A=1" 的子测试
子测试 也可用于控制并行性 所有的子测试完成后 父测试才会完成
在这个例子中 所有的测试是相互并行运行的 当然也只是彼此之间 不包括定义在其他顶层测试的子测试
func TestGroupedParallel(t *testing.T) {
  for _, tc := range tests {
      tc := tc // capture range variable
      t.Run(tc.Name, func(t *testing.T) {
          t.Parallel()
          ...
      })
  }
}
在并行子测试完成之前 Run 方法不会返回 这提供了一种测试后清理的方法:
func TestTeardownParallel(t *testing.T) {
  // This Run will not return until the parallel tests finish.
  t.Run("group", func(t *testing.T) {
      t.Run("Test1", parallelTest1)
      t.Run("Test2", parallelTest2)
      t.Run("Test3", parallelTest3)
  })
  // <tear-down code>
}