许多 Go 程序员更喜欢使用无 if
的测试断言,以使测试更短且更易读。例如,不用带有 t.Errorf
的 if
语句:
func Test(t *testing.T) {
db := getDB(t)
db.Str().Set("name", "alice")
age, err := db.Str().Get("age")
if!errors.Is(err, redka.ErrNotFound) {
t.Errorf("want ErrNotFound, got %v", err)
}
if age!= nil {
t.Errorf("want nil, got %v", age)
}
}
PASS
而是使用 testify/assert
(或其“邪恶双胞胎” testify/require
):
func Test(t *testing.T) {
db := getDB(t)
db.Str().Set("name", "alice")
age, err := db.Str().Get("age")
assert.ErrorIs(t, err, redka.ErrNotFound)
assert.Nil(t, age)
}
但作者认为不需要 testify/assert
及其 40 种不同的断言函数来保持测试干净,提出了一种替代方法:
断言相等:最常见的测试断言类型是检查相等性,如:
func Test(t *testing.T) { db := getDB(t) db.Str().Set("name", "alice") name, _ := db.Str().Get("name") if name.String()!= "alice" { t.Errorf("want 'alice', got '%v'", name) } }
PASS
并编写了基本的通用断言辅助函数
AssertEqual
:// AssertEqual asserts that got is equal to want. func AssertEqual[T any](tb testing.TB, got T, want T) { tb.Helper() // Check if both are nil. if isNil(got) && isNil(want) { return } // Fallback to reflective comparison. if reflect.DeepEqual(got, want) { return } // No match, report the failure. tb.Errorf("want %#v, got %#v", want, got) }
还对一些类型(如
time.Time
和net.IP
)进行了优化,使用其Equal
方法进行比较,并使用bytes.Equal
优化字节切片的比较。断言错误:在 Go 中错误无处不在,所以检查错误是测试的重要部分,如:
func Test(t *testing.T) { db := getDB(t) db.Str().Set("name", "alice") _, err := db.Str().Get("name") if err!= nil { t.Errorf("unexpected error: %v'", err) } }
PASS
并创建了单独的函数
AssertErr
来处理错误断言,包括检查无错误、特定错误值、错误类型、错误消息等情况,还使want
参数可选,以处理可能存在的任意错误。其他断言:
AssertEqual
和AssertErr
可能处理典型 Go 项目中 85 - 95%的测试断言,对于剩下的 5 - 15%,如检查长度和包含字符串等情况,引入了AssertTrue
函数:// AssertTrue asserts that got is true. func AssertTrue(tb testing.TB, got bool) { tb.Helper() if!got { tb.Error("not true") } }
最后作者认为不需要 40 种断言函数来测试 Go 应用,三个(甚至两个)就足够了,如
Equal
、Err
和True
,并将其提取到了 github.com/nalgeon/be 迷你包中。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。