简介
testify
可以说是最流行的(从 GitHub star 数来看)Go 语言测试库了。testify
提供了很多方便的函数帮助我们做assert
和错误信息输出。使用标准库testing
,我们需要自己编写各种条件判断,根据判断结果决定输出对应的信息。
testify
核心有三部分内容:
assert
:断言;mock
:测试替身;suite
:测试套件。
准备工作
本文代码使用 Go Modules。
创建目录并初始化:
$ mkdir -p testify && cd testify
$ go mod init github.com/darjun/go-daily-lib/testify
安装testify
库:
$ go get -u github.com/stretchr/testify
assert
assert
子库提供了便捷的断言函数,可以大大简化测试代码的编写。总的来说,它将之前需要判断 + 信息输出的模式
:
if got != expected {
t.Errorf("Xxx failed expect:%d got:%d", got, expected)
}
简化为一行断言代码:
assert.Equal(t, got, expected, "they should be equal")
结构更清晰,更可读。熟悉其他语言测试框架的开发者对assert
的相关用法应该不会陌生。此外,assert
中的函数会自动生成比较清晰的错误描述信息:
func TestEqual(t *testing.T) {
var a = 100
var b = 200
assert.Equal(t, a, b, "")
}
使用testify
编写测试代码与testing
一样,测试文件为_test.go
,测试函数为TestXxx
。使用go test
命令运行测试:
$ go test
--- FAIL: TestEqual (0.00s)
assert_test.go:12:
Error Trace:
Error: Not equal:
expected: 100
actual : 200
Test: TestEqual
FAIL
exit status 1
FAIL github.com/darjun/go-daily-lib/testify/assert 0.107s
我们看到信息更易读。
testify
提供的assert
类函数众多,每种函数都有两个版本,一个版本是函数名不带f
的,一个版本是带f
的,区别就在于带f
的函数,我们需要指定至少两个参数,一个格式化字符串format
,若干个参数args
:
func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{})
func Equalf(t TestingT, expected, actual interface{}, msg string, args ...interface{})
实际上,在Equalf()
函数内部调用了Equal()
:
func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return Equal(t, expected, actual, append([]interface{}{msg}, args...)...)
}
所以,我们只需要关注不带f
的版本即可。
Contains
函数类型:
func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool
Contains
断言s
包含contains
。其中s
可以是字符串,数组/切片,map。相应地,contains
为子串,数组/切片元素,map 的键。
DirExists
函数类型:
func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool
DirExists
断言路径path
是一个目录,如果path
不存在或者是一个文件,断言失败。
ElementsMatch
函数类型:
func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) bool
ElementsMatch
断言listA
和listB
包含相同的元素,忽略元素出现的顺序。listA/listB
必须是数组或切片。如果有重复元素,重复元素出现的次数也必须相等。
Empty
函数类型