用Go泛型轻松测试断言的指南

610 阅读1分钟

现在Go 1.18已经发布了对泛型的支持,为你的测试断言创建辅助函数比以前更容易了。

为你的测试断言使用辅助函数可以帮助:

  • 使你的测试函数干净、清晰。
  • 保持测试失败信息的一致性。
  • 减少代码中因错别字而产生的错误的可能性。

为了说明这一点,我们假设你有一个简单的greet() ,你想测试的函数:

package main

import "fmt"

func greet(name string) (string, int) {
    greeting := fmt.Sprintf("Hello %s", name)

    // Return the greeting and its length (in bytes).
    return greeting, len(greeting)
}

在过去,你对greet() 函数的测试可能会是这样的:

package main

import "testing"

func TestGreet(t *testing.T) {
    greeting, greetingLength := greet("Alice")

    // Test assertion to check the returned greeting string.
    if greeting != "Hello Alice" {
        t.Errorf("want: %s; got: %s", "Hello Alice", greeting)
    }

    // Test assertion to check the returned greeting length.
    if greetingLength != 11 {
        t.Errorf("want: %d; got: %d", 11, greetingLength)
    }
}

在Go 1.18中,我们可以使用泛型和 comparable约束来创建一个Equal() 辅助函数,执行我们的测试断言。就个人而言,我喜欢把它放在一个可重复使用的assert 包中。

像这样:

package assert

import "testing"

func Equal[T comparable](t *testing.T, expected, actual T) {
    t.Helper()

    if expected != actual {
        t.Errorf("want: %v; got: %v", expected, actual)
    }
}

注意:这个 t.Helper()函数向 Go 测试运行器表明我们的Equal() 函数是一个测试助手。这意味着当t.Errorf() 被我们的Equal() 函数调用时,Go测试运行器将在输出中报告调用我们Equal() 函数的代码的文件名和行号。

有了这些,TestGreet() 的测试就可以简化成这样:

package main

import (
    "testing"
    "your.module.path/assert" // Import your assert package.
)

func TestGreet(t *testing.T) {
    greeting, greetingLength := greet("Alice")

    assert.Equal(t, "Hello Alice", greeting)
    assert.Equal(t, 11, greetingLength)
}