测试
Go自带一个轻量级的测试框架testing
,以及go test
命令,用于实现单元测试和性能测试。testing
与其他语言的测试框架类似,可以针对响应函数编写测试用例,也可以基于框架写相应的压力测试用例。可以从如下几个方面保证代码质量:
确保每个函数是可运行的,并且运行结果是正确的
确保写出的代码性能,
testing
会展示每个测试用例执行的时间及时发现程序设计的逻辑错误,让问题尽早暴露
使用testing
测试
testing
测试使用案例
目标测试包结构,该包主要提供加减乘除四个方法:
cal
├── cal.go
├── cal_test.go
└── sub_test.go
cal.go
:
package cal
func Plus(a, b int) int {
return a + b
}
func Sub(a, b int) int {
return a - b
}
func Multi(a, b int) int {
return a * b
}
func Division(a, b int) int {
return a / b
}
cal_test.go(
针对加乘除三个函数测试):
package cal
import (
"testing"
)
func TestPlus(t *testing.T) {
res := Plus(1, 2)
e := 3 // 期望值
if res != 3 { // 失败
t.Fatalf("执行失败:期望值 %v, 目标值 %v ", e, res) // 发生致命错误,并格式化错误信息
}
t.Logf("执行成功:期望值 %v, 目标值 %v", e, res) // 打印日志
}
func TestDivision(t *testing.T) {
res := Division(1, 2)
t.Logf("执行成功:目标值 %v", res)
}
// 测试除零的情况
func TestDivisionByZero(t *testing.T) {
res := Division(1, 0)
t.Logf("执行成功:目标值 %v", res) // 打印日志
}
sub_test.go
(针对减法函数测试):
package cal
import "testing"
func TestSub(t *testing.T) {
res := Sub(1, 2)
if res != -1 {
t.Fatalf("执行失败:期望值 %v, 目标值 %v ", -1, res) // 失败并打印信息
}
}
执行命令go test -v
可以测试当前所在文件夹的包中的所有测试用例:
$ go test -v
=== RUN TestPlus # Plus方法通过
cal_test.go:14: 执行成功:期望值 3, 目标值 3
--- PASS: TestPlus (0.00s)
=== RUN TestDivision # Division方法通过
cal_test.go:19: 执行成功:目标值 0
--- PASS: TestDivision (0.00s) # 这是运行时间
=== RUN TestDivisionByZero # Division除0不通过
--- FAIL: TestDivisionByZero (0.00s)
panic: runtime error: integer divide by zero [recovered]
panic: runtime error: integer divide by zero
goroutine 8 [running]:
testing.tRunner.func1.2(0x11217e0, 0x1215b40)
/usr/local/go/src/testing/testing.go:1143 +0x332
testing.tRunner.func1(0xc000001800)
/usr/local/go/src/testing/testing.go:1146 +0x4b6
panic(0x11217e0, 0x1215b40)
/usr/local/go/src/runtime/panic.go:965 +0x1b9
cal.Division(...)
/Users/yangsx/GoLandProjects/notes-golang/src/cal/cal.go:16
cal.TestDivisionByZero(0xc000001800)
/Users/yangsx/GoLandProjects/notes-golang/src/cal/cal_test.go:23 +0x12
testing.tRunner(0xc000001800, 0x114d280)
/usr/local/go/src/testing/testing.go:1193 +0xef
created by testing.(*T).Run
/usr/local/go/src/testing/testing.go:1238 +0x2b3
exit status 2
FAIL cal 0.353s
只打印测试失败结果
去除-v
参数即可,如下测试就没有打印任何成功的测试用例:
$ go test
--- FAIL: TestDivisionByZero (0.00s)
panic: runtime error: integer divide by zero [recovered]
panic: runtime error: integer divide by zero
goroutine 18 [running]:
testing.tRunner.func1.2(0x11217e0, 0x1215b40)
/usr/local/go/src/testing/testing.go:1143 +0x332
testing.tRunner.func1(0xc000082600)
/usr/local/go/src/testing/testing.go:1146 +0x4b6
panic(0x11217e0, 0x1215b40)
/usr/local/go/src/runtime/panic.go:965 +0x1b9
cal.Division(...)
/Users/yangsx/GoLandProjects/notes-golang/src/cal/cal.go:16
cal.TestDivisionByZero(0xc000082600)
/Users/yangsx/GoLandProjects/notes-golang/src/cal/cal_test.go:23 +0x12
testing.tRunner(0xc000082600, 0x114d280)
/usr/local/go/src/testing/testing.go:1193 +0xef
created by testing.(*T).Run
/usr/local/go/src/testing/testing.go:1238 +0x2b3
exit status 2
FAIL cal 0.726s
针对某个测试文件测试
注意,一定要带上被测试的原文件:
$ go test sub_test.go cal.go
ok command-line-arguments 0.421s
针对某个测试函数测试
仅测试TestSub
单元测试函数:
$ go test -v -test.run TestSub
=== RUN TestSub
--- PASS: TestSub (0.00s)
PASS
ok cal 0.235s
使用注意事项
测试文件必须以
_test.go
结尾,前缀则不要求与源码文件相同测试函数必须以
Test
开头,后缀通常是被测函数的名称(不是必需的),并且首字母必须大写,否则不会识别。比如TestDivision
,TestDivisionByZero
测试函数的参数必须为
t testing.T
测试函数体中需要打印日志的情况可以使用
t.Logf
方法打印如果出现错误,也就是不符合期望值,可以调用
t.Error()
,t.Fatalf()
等方法标记当前测试失败如果测试过程中发生异常,测试用例失败
testing
的原理
testing
的原理go test
工具将测试文件cal_test.go
引入到自己的main
中在
main
中调用所有的测试用例
类似如下伪代码:
func main() {
TestXXX()
...
}
goconvey
https://github.com/smartystreets/goconvey
特点:
测试代码优雅简洁
直接集成Go原生测试
全自动编译测试
详细展示测试结果以及覆盖率
高可读性的命令行输出结果
半自动化书写测试用例
安装:
$ go get github.com/smartystreets/goconvey
# 或者
$ go install github.com/smartystreets/goconvey
使用案例
目标测试文件 calc.go
:
package goconvey
import "errors"
func Add(a, b int) int {
return a + b
}
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
}
创建测试文件 calc_test.go
:
package goconvey
import (
. "github.com/smartystreets/goconvey/convey" // 导入convey包,使用Convey函数以及So等函数
"testing" // go testing 测试框架支持
)
func TestAdd(t *testing.T) {
// 使用Convey方法声明一个测试的范围,主要包含 描述、以及一个用于执行测试逻辑的func()
Convey("将两个数相加", t, func() {
// 用于断言的通用方法,他可以接收如下三个参数
// 1, 实际值
// 2, 判断方式,这里是相同
// 3, 期望值
// 如果实际值不等于期望值,则代表测试未通过
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(1, 2), ShouldEqual, 2)
})
}
func TestDivision(t *testing.T) {
Convey("将两个数相除", t, func() {
// 不同的测试情况,请使用嵌套的Convey方法
Convey("除数不为0", func() {
r, err := Division(4, 2)
So(r, ShouldEqual, 2)
So(err, ShouldBeNil)
})
Convey("除数为0", func() {
_, err := Division(4, 0)
So(err, ShouldNotBeNil)
})
})
}
断言函数索引
Assertions · smartystreets/goconvey Wiki (github.com)
使用go test原生命令测试
$ go test
# 四个测试方法,共有四个测试结果
. # 代表一个So判断
1 total assertion
.
2 total assertions
.
3 total assertions
... # 代表三个So判断
6 total assertions
PASS
ok notes-golang/goconvey 0.693s
使用go test -v
,查看更详细的结果:
$ go test -v
=== RUN TestAdd
将两个数相加 ✔ # ✔ 代表So的通过次数
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 ✔✔ # ✔ 代表So的通过次数,有可能为✘,就代表So不通过的个数
除数为0 ✔
6 total assertions
--- PASS: TestDivision (0.00s)
PASS
ok notes-golang/goconvey 0.236s
使用goconvey提供的工具测试
$ goconvey
2021/12/15 10:30:32 goconvey.go:116: GoConvey server:
2021/12/15 10:30:32 goconvey.go:121: version: v1.7.2 gomodifytags goplay gotests
2021/12/15 10:30:32 goconvey.go:122: host: 127.0.0.1
2021/12/15 10:30:32 goconvey.go:123: port: 8080
2021/12/15 10:30:32 goconvey.go:124: poll: 250ms
2021/12/15 10:30:32 goconvey.go:125: cover: true
2021/12/15 10:30:32 goconvey.go:126:
2021/12/15 10:30:32 tester.go:19: Now configured to test 10 packages concurrently.
2021/12/15 10:30:32 goconvey.go:243: Serving HTTP at: http://127.0.0.1:8080
2021/12/15 10:30:32 goconvey.go:146: Launching browser on 127.0.0.1:8080
2021/12/15 10:30:32 integration.go:122: File system state modified, publishing current folders... 0 3279069840
2021/12/15 10:30:32 goconvey.go:159: Received request from watcher to execute tests...
2021/12/15 10:30:32 goconvey.go:154:
2021/12/15 10:30:32 executor.go:69: Executor status: 'executing'
2021/12/15 10:30:32 coordinator.go:46: Executing concurrent tests: notes-golang/goconvey
2021/12/15 10:30:32 parser.go:24: [passed]: notes-golang/goconvey
2021/12/15 10:30:32 executor.go:69: Executor status: 'idle'

测试覆盖率,点击可以查看已覆盖以及未覆盖的go代码:


全自动编译测试
服务启动后,会在后台监测代码的变动并重新进行单元测试。如果自动编译测试不生效可以使用刷新按钮强制刷新
如果想要暂停自动编译测试,可以使用暂停按钮暂停

测试失败的展示

半自动化书写测试用例

最后更新于
这有帮助吗?