go代码测试综合指南(二)

编写表驱动测试

编写测试时,您可能会为了覆盖所有用例而重复大量代码。 想一想您将如何覆盖 Fooer 示例中涉及的许多用例。 您可以为每种用例都编写一个测试函数,但这会导致大量重复。 您也可以在同一个测试函数中多次调用被测函数并逐次验证输出,但如果测试失败,则很难确定失败点。 最后,您还可以使用表驱动方式帮助减少重复。 顾名思义,这涉及将测试用例组织为包含输入和所需输出的表。

这有两个好处:

表测试重用相同的断言逻辑,使测试保持整洁。

表测试可以清晰显示选择的输入和测试涵盖的内容。 此外,每一行都可以获得一个唯一名称,帮助识别正在测试的内容和表达测试的意图。

以下是 Fooer 函数的表驱动测试函数示例:

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
30
31
32
33
34
35
36
37
38
39
```
func TestFooerTableDriven(t *testing.T) {
      // Defining the columns of the table
        var tests = []struct {
        name string
            input int
            want  string
        }{
            // the table itself
            {"9 should be Foo", 9, "Foo"},
            {"3 should be Foo", 3, "Foo"},
            {"1 is not Foo", 1, "1"},
            {"0 should be Foo", 0, "Foo"},
        }
      // The execution loop
        for _, tt := range tests {
            t.Run(tt.name, func(t *testing.T) {
                ans := Fooer(tt.input)
                if ans != tt.want {
                    t.Errorf("got %s, want %s", ans, tt.want)
                }
            })
        }
    }
```

```    

表驱动测试从定义输入结构开始。 这相当于定义表的列。 表的每一行都列出了待执行的测试用例。 定义表后,您可以编写执行循环。

执行循环会调用定义子测试的 t.Run()。 因此,表的每一行都定义了一个名为 
`[NameOfTheFuction]/[NameOfTheSubTest]`
 的子测试。

这种测试编写方式非常流行,也被视作在 Go 中编写单元测试的规范方式。 GoLand 可以为您生成这些测试模板。 您可以右键点击函数,转到 Generate | Test for function(生成 | 函数测试)。 查看 GoLand 文档了解更多详细信息。 

您只需要添加测试用例:

```go

{“9 should be Foo”, args{9}, “Foo”},
        {“3 should be Foo”, args{3}, “Foo”},
        {“1 is not Foo”, args{1}, “1”},
        {“0 should be Foo”, args{0}, “Foo”},

  

执行测试时,您会看到 TestFooerTableDriven 函数运行四个子测试,每个对应表中的一行。

生成功能让表驱动测试的编写变得简单直观。

江达小记