GoConvey类似于C/C++语言的测试框架GTest,是一款针对Golang的测试框架,可以管理和运行测试用例,同时提供了丰富的断言函数,并支持很多 Web 界面特性。
Golang虽然自带了单元测试功能,并且在GoConvey框架诞生之前也出现了许多第三方测试框架,但没有一个测试框架像GoConvey一样能够让程序员如此简洁优雅的编写测试代码。
在命令行输入命令:
sudo go get github.com/smartystreets/goconvey
我们通过一个案例来介绍GoConvey框架的基本使用方法,并对要点进行归纳。
下面是一个能够实现整数基本四则运算(加、减、乘、除)的代码:
package goconvey
import (
"errors"
)
func Add(a int, b int) int {
c := a + b
return c
}
func Subtract(a, b int) int {
return a - b
}
func Multiply(a, b int) int {
return a * b
}
func Division(a, b int) (int, error) {
if b == 0 {
return 0, errors.New("被除数不能为 0")
}
return a / b, nil
}
package goconvey
import (
. "github.com/smartystreets/goconvey/convey"
"testing"
)
func TestAdd(t *testing.T) {
Convey("将两数相加", t, func() {
So(Add(1, 2), ShouldEqual, 3)
})
}
func TestSubtract(t *testing.T) {
Convey("将两数相减", t, func() {
So(Subtract(1, 2), ShouldEqual, -1)
})
}
func TestMultiply(t *testing.T) {
Convey("将两数相乘", t, func() {
So(Multiply(3, 2), ShouldEqual, 6)
})
}
func TestDivision(t *testing.T) {
Convey("将两数相除", t, func() {
Convey("除以非 0 数", func() {
num, err := Division(10, 2)
So(err, ShouldBeNil)
So(num, ShouldEqual, 5)
})
Convey("除以 0", func() {
_, err := Division(10, 0)
So(err, ShouldNotBeNil)
})
})
}
上面的测试用例代码有如下几个要点:
现在,您可以打开命令行,然后输入 go test -v 来进行测试。由于 GoConvey 兼容 Go 原生的单元测试,因此我们可以直接使用 Go 的命令来执行测试。
以下便是命令行的输出(Mac):
=== RUN TestAdd
将两数相加 ✔
1 total assertion
--- PASS: TestAdd (0.00s)
=== RUN TestSubtract
将两数相减 ✔
2 total assertions
--- PASS: TestSubtract (0.00s)
=== RUN TestMultiply
将两数相乘 ✔
3 total assertions
--- PASS: TestMultiply (0.00s)
=== RUN TestDivision
将两数相除
除以非 0 数 ✔✔
除以 0 ✔
6 total assertions
--- PASS: TestDivision (0.00s)
PASS
ok helloworld/goconvey 0.006s
我们可以看到,输出结果调理非常清晰,单元测试的代码写起来也非常优雅。那么,这就是全部吗?当然不是。GoConvey 不仅支持在命令行进行人工调用调试命令,还有非常舒适的 Web 界面提供给开发者来进行自动化的编译测试工作。
GoConvey不仅支持在命令行进行自动化编译测试,而且还支持在 Web 界面进行自动化编译测试。想要使用GoConvey的 Web 界面特性,需要在测试文件所在目录下执行goconvey:
$GOPATH/bin/goconvey
在 Web 界面中:
可以设置界面主题
查看完整的测试结果
使用浏览器提醒等实用功能
自动检测代码变动并编译测试
半自动化书写测试用例
查看测试覆盖率
临时屏蔽某个包的编译测试
针对想忽略但又不想删掉或注释掉某些断言操作,GoConvey提供了Convey/So的Skip方法:
SkipSo函数表明相应的断言将不被执行
当存在SkipConvey或SkipSo时,测试日志中会显式打上”skipped”形式的标记:
当测试代码中存在SkipConvey时,相应闭包函数中不管是否为SkipSo,都将被忽略,测试日志中对应的符号仅为一个”⚠”
我们先看一下So的函数原型:
func So(actual interface{}, assert assertion, expected ...interface{})
第二个参数为assertion,它的原型为:
type assertion func(actual interface{}, expected ...interface{}) string
当assertion的返回值为”“时表示断言成功,否则表示失败,GoConvey框架中的相关代码为:
const (
success = ""
needExactValues = "This assertion requires exactly %d comparison values (you provided %d)."
needNonEmptyCollection = "This assertion requires at least 1 comparison value (you provided 0)."
)
我们简单实现一个assertion函数:
func ShouldSummerBeComming(actual interface{}, expected ...interface{}) string {
if actual == "summer" && expected[0] == "comming" {
return ""
} else {
return "summer is not comming!"
}
}
我们仍然在slice_test文件中写一个简单测试:
func TestSummer(t *testing.T) {
Convey("TestSummer", t, func() {
So("summer", ShouldSummerBeComming, "comming")
So("winter", ShouldSummerBeComming, "comming")
})
}
根据ShouldSummerBeComming的实现,Convey语句中第一个So将断言成功,第二个So将断言失败。
我们运行测试,查看执行结果,符合期望:
=== RUN TestSummer
TestSummer ✔✘
Failures:
* /Users/zhangxiaolong/Desktop/D/go-workspace/src/infra/alg/slice_test.go
Line 52:
summer is not comming!
2 total assertions
--- FAIL: TestSummer (0.00s)
FAIL
exit status 1
FAIL infra/alg 0.006s
Golang虽然自带了单元测试功能,但笔者建议大家使用已经成熟的第三方测试框架。本文主要介绍了GoConvey框架,通过文字结合代码示例讲解基本的使用方法,要点归纳如下:
参考文档如下:
https://studygolang.com/articles/9801
https://studygolang.com/articles/1513