在 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)
}

这样比之前的方法优雅很多。但是,当查看错误信息的时候发现。

assert_right_place1

提示的错误行不在 TestWithAssert里面。为了解决这个问题, 使用 testingHelper()函数。

实现如

func assertEqual(t *testing.T, a, b interface{}) {
	t.Helper()
	if a != b {
		t.Errorf("Not Equal. %d %d", a, b)
	}
}

这时的错误信息为

assert_wrong_place1

正好是出错的行数。

当使用测试 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

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值