表驱动测试

参考 Go 维基官网——表驱动测试学习。

原网页由 Martin Tournoij 在 2018/4/11 编辑。第 3 次修订

介绍

编写好的测试不是烦琐的,在很多情况下大量领域可以使用表驱动测试覆盖:每个表条目是一个包含输入和预期结果的测试用例,而且有时候包含一些额外的信息,比如测试名称,使得测试输出易于阅读。如果你曾经发现自己在编写测试时使用拷贝和粘贴,考虑是否重构为表驱动测试,或者把拷贝的代码放在一个辅助函数可能是一个更好的选择。

给定一个测试用例表,真正的测试简单地迭代遍历所有表条目,且未每个条目执行必要的测试。测试代码只编写一次且被分摊到所有的表条目,因此精心编写一个带有好的错误消息的测试是有意义的。

表驱动测试的例子

这里是一个来自 fmt测试代码的好例子:

var flagtests = []struct {
  in  string
  out string
}{
  {"%a", "[%a]"},
  {"%-a", "[%-a]"},
  {"%+a", "[%+a]"},
  {"%#a", "[%#a]"},
  {"% a", "[% a]"},
  {"%0a", "[%0a]"},
  {"%1.2a", "[%1.2a]"},
  {"%-1.2a", "[%-1.2a]"},
  {"%+1.2a", "[%+1.2a]"},
  {"%-+1.2a", "[%+-1.2a]"},
  {"%-+1.2abc", "[%+-1.2a]bc"},
  {"%-1.2abc", "[%-1.2a]bc"},
}
func TestFlagParser(t *testing.T) {
  var flagprinter flagPrinter
  for _, tt := range flagtests {
    t.Run(tt.in, func(t *testing.T) {
      s := Sprintf(tt.in, &flagprinter)
      if s != tt.out {
        t.Errorf("got %q, want %q", s, tt.out)
      }
    })
  }
}

注意使用 t.Errorf 提供的详细的错误消息:提供了函数结果和预期结果;输入是子测试的名字。当测试失败时,哪个错误失败以及为什么失败是显然的,甚至不用阅读测试代码。

t.Errorf 调用不是一个断言。即使打印一个错误日志,测试仍会继续。比如,当使用整数输入测试一些代码时,知道函数对所有输入失败,还是只对奇数失败,或者是对 2 的幂失败是有意义的。

参考

相关