工作需求,各个服务的代码需要陆陆续续加入单元测试。作为这次单元测试和持续集成持续发布的推动人,这几天都在查找golang单元测试相关的资料和实践。
单元测试的作用:
提高代码的可维护性。
代码的可维护性是指增加一个新功能,或改变现有功能的成本,成本越低,可维护性即越高。
是修改代码乃至未来代码重构的信心保证。
持续集成的重要部分。
单元测试需要注意的点:
单元测试的测试用例要覆盖常用的输入组合、边界条件和异常。
单元测试代码本身要尽量简单,如果测试代码太复杂,那么其本身就可能有bug。
golang的第三方单元测试框架很多,最后我选择了GoConvey这个框架,它有如下特点:
1,基于go test的单元测试框架
2,开箱即用
3,丰富的断言库,具体断言例子可看下方链接
https://github.com/smartystreets/goconvey/blob/master/examples/assertion_examples_test.go
4,支持自定义断言
5,支持跳过用例
6,集成了web界面来执行大规模的单元测试,同时带有代码覆盖率的统计
GoConvey使用:
首先,在要测的函数的文件下方,新建一个“要测的文件名_test“.go文件。
func TestGetChildrenMetal(t *testing.T) {
configOnce.Do(configInit)
loggerOnce.Do(loggerInit)
db.InitOnce.Do(db.DbInitOnce)
Db2.Db = db.Gdb.Db
convey.Convey("测试GetChildrenMetal", t, func() {
metalList := Db2.GetChildrenMetal("czce")
convey.Convey("测试品目个数是否大于0", func() {
convey.So(len(metalList), convey.ShouldBeGreaterThan, 0)
})
convey.Convey("测试品目是否包含Cu", func() {
convey.So(metalList, convey.ShouldContain, "Cu")
})
})
}
因为有些函数是要和db交互,会打log,读配置文件,所以我决定使用sync.once
来做这些初始化,once是可以全局执行一次的函数对象,正适合我们的这些db连接,log初始化,配置文件读取。
上面断言的使用可以参考第3点GoConvey官方的文档
执行单元测试:
go test -count=1 -v ./… 2>1 | tee mylog.txt
-count=1 是为了让单元测试不要使用cache机制,因为go1.10推出了诸多新特性之一就是让单元测试引入了cache机制,具体这里不再赘述。
./… 是为了在当前目录下所有的文件都被执行单元测试
2>1 | tee mylog314.txt 是为了把单元测试的结果导入到文件中,因为要计算通过率,供后续流程使用。
好了,目前为止,单元测试的大致流程就是这些,接下来还有mock测试和http接口测试。