在-Go-中使用-assert-风格的单元测试
目录
在 Go 中使用 assert 风格的单元测试
在 Go 中使用 assert 风格的单元测试
Go 语言提供很好的单元测试功能。单元测试只需新建一个以 “_test.go” 结尾的文件。假设有两个函数需要测试, 如:
func add(a, b int) int {
return a + b
}
func magicFunction(a int) int {
return a << 3
}
测试文件可以如下:
func TestWithoutAssert(t *testing.T) {
if add(1, 3) != 4 {
t.Error("add(1+3) ne 4")
}
// this will raise an error
if add(1, 3) != 5 {
t.Error("add(1+3) ne 5")
}
if magicFunction(5) != 40 {
t.Error("magicFunction(5) ne 40")
}
}
这样是可以完成测试的。不过,当测试量大的时候就显得代码很啰嗦。借鉴 JUnit 里面的 assert 函数, 在 Go 中使用类似的函数。
实现
assertEqual
如下:
func assertEqual(t *testing.T, a, b interface{}) {
if a != b {
t.Errorf("Not Equal. %d %d", a, b)
}
}
这样就可以在测试函数里面使用, 如:
func TestWithAssert(t *testing.T) {
assertEqual(t, add(1, 2), 3)
// this will raise an error
assertEqual(t, add(3, 4), 8)
assertEqual(t, magicFunction(5), 40)
}
这样比之前的方法优雅很多。但是,当查看错误信息的时候发现。
提示的错误行不在
TestWithAssert
里面。为了解决这个问题, 使用
testing
的
Helper()
函数。
实现如
func assertEqual(t *testing.T, a, b interface{}) {
t.Helper()
if a != b {
t.Errorf("Not Equal. %d %d", a, b)
}
}
这时的错误信息为
正好是出错的行数。
当使用测试 Benchmark 的时候, 函数的参数是
*testing.B
, 这样先前的
assertEqual
就无法直接使用。
怎么办?
Go 里面的
interface
是很神奇的东西。如果定义一个
interface
如:
type testcommon interface {
Error(args ...interface{})
Errorf(format string, args ...interface{})
Fail()
FailNow()
Failed() bool
Fatal(args ...interface{})
Fatalf(format string, args ...interface{})
Helper()
Log(args ...interface{})
Logf(format string, args ...interface{})
Name() string
Skip(args ...interface{})
SkipNow()
Skipf(format string, args ...interface{})
Skipped() bool
}
然后
assert
函数写成:
func assertEqual(t testcommon, a, b interface{}) {
t.Helper()
if a != b {
t.Errorf("Not Equal. %d %d", a, b)
}
}
这样可以兼容 Benchmark。
最终测试代码如:
func TestWithAssert(t *testing.T) {
assertEqual(t, add(1, 2), 3)
// this will raise an error
assertEqual(t, add(3, 4), 8)
assertEqual(t, magicFunction(5), 40)
}
func BenchmarkMagic(b *testing.B) {
for i := 0; i < 1000; i++ {
assertEqual(b, magicFunction(i), i*8)
}
}
下面是一些写好的
assert
函数,方便大家使用。
func assertEqual(t testcommon, a, b interface{}) {
t.Helper()
if a != b {
t.Errorf("Not Equal. %d %d", a, b)
}
}
func assertTrue(t testcommon, a bool) {
t.Helper()
if !a {
t.Errorf("Not True %t", a)
}
}
func assertFalse(t testcommon, a bool) {
t.Helper()
if a {
t.Errorf("Not True %t", a)
}
}
func assertNil(t testcommon, a interface{}) {
t.Helper()
if a != nil {
t.Error("Not Nil")
}
}
func assertNotNil(t testcommon, a interface{}) {
t.Helper()
if a == nil {
t.Error("Is Nil")
}
}
EOF