Go语言精进之路:从新手到高手的编程思想、方法和技巧(2)
上QQ阅读APP看书,第一时间看更新

42.3 表驱动测试的优点

表驱动测试本身是编程语言无关的。Go核心团队和Go早期开发者在实践过程中发现表驱动测试十分适合Go代码测试并在标准库和第三方项目中大量使用此种测试设计,这样表驱动测试也就逐渐成为Go的一个惯用法。就像我们从上面的示例中看到的那样,表驱动测试有着诸多优点。

(1)简单和紧凑

从上面的示例中我们看到,表驱动测试将不同测试项经由被测目标执行后的实际输出结果与预期结果的差异判断逻辑合并为一个,这使得测试函数逻辑结构更简单和紧凑。这种简单和紧凑意味着测试代码更容易被开发者理解,因此在测试代码的生命周期内,基于表驱动的测试代码的可维护性更好。

(2)数据即测试

表驱动测试的实质是数据驱动的测试,扩展输入数据集即扩展测试。通过扩展数据集,我们可以很容易地实现提高被测目标测试覆盖率的目的。

(3)结合子测试后,可单独运行某个数据项的测试

我们将表驱动测试与子测试(subtest)结合来改造一下上面的strings_test示例:

// chapter8/sources/table_driven_strings_with_subtest_test.go
func TestCompare(t *testing.T) {
    compareTests := []struct {
        name, a, b string
        i          int
    }{
        {`compareTwoEmptyString`, "", "", 0},
        {`compareSecondParamIsEmpty`, "a", "", 1},
        {`compareFirstParamIsEmpty`, "", "a", -1},
    }

    for _, tt := range compareTests {
        t.Run(tt.name, func(t *testing.T) {
            cmp := strings.Compare(tt.a, tt.b)
            if cmp != tt.i {
                t.Errorf(`want %v, but Compare(%q, %q) = %v`, tt.i, tt.a, tt.b, cmp)
            }
        })
    }
}

在示例中,我们将测试结果的判定逻辑放入一个单独的子测试中,这样可以单独执行表中某项数据的测试。比如:我们单独执行表中第一个数据项对应的测试:

$go test -v  -run /TwoEmptyString table_driven_strings_with_subtest_test.go
=== RUN   TestCompare
=== RUN   TestCompare/compareTwoEmptyString
--- PASS: TestCompare (0.00s)
    --- PASS: TestCompare/compareTwoEmptyString (0.00s)
PASS
ok     command-line-arguments   0.005s

综上,建议在编写Go测试代码时优先编写基于表驱动的测试。