如何在 Go 中写出高效的单元测试
本周在团队做了一次关于 Go 单元测试的分享,分享题目为《Testing in Go-how to write efficient unit test》。
内容大纲
单元测试的重要性
Go 单元测试基础知识
表格测试和 HTTP 测试
其它测试框架
其它 Mock 库
与 Docker 集成
单测的重要性
能够尽早的发现 bug
方便 debugging
方便代码重构
提升代码质量
使整个过程敏捷
讲这部分的目的是为了让团队达成共识---单测很重要,我们必须要做好单元测试。
Go 单测基础知识
基本规则
通常我们的单元测试代码都放在以 _test.go 结尾的文件中,该文件一般和目标代码放在同一个 package 中。
测试的方法以为 Test 开头,并且拥有唯一一个 *Testing.T 的参数。
go test
使用
go test
测试当前包go test some/pkg
测试一个特定的包go test some/pkg/...
递归测试一个特定包下面的所有包go test -v some/pkg -run ^TestSum$
测试特定包下面的特定方法go test -cover
查看单测覆盖率go test -count=1
忽略缓存运行单测,注意如果以递归方式(./...)测试的时候,默认会使用 cache
表格测试
使用匿名结构体批量构建自己的测试 case
采用子测试的方式让测试输出更友好
HTTP 测试
使用
httptest.NewRecorder
来测试 HTTP Handler 而不需要真正进行 HTTP 监听可以使用
errorReader
来提高测试覆盖率
Go 单测基础知识这部分的内容主要是向大家讲解 Go 官方单测库 testing 以及命令行 go test 的使用。
可以看到官方自带的库已经足够好用, 不仅带有 subtest 还有 httptest 的相关内容,对于中小型的项目而言使用官方的 testing 库足够。
其它测试框架
虽然官方 testing
库足够优秀,但在一些较大项目上,它还是有很多需要完善的地方,如:
断言不够友好,需要通过大量 if
持续集成不够,每次都要手动跑测试
BDD 无支持
测试 case 的文档自动化不够
所以我这里介绍了三种测试框架,针对以上几点都有一定的改进。
Testify
和
go test
无缝集成,直接使用该命令运行支持断言,写法更简便
支持 mocking
https://github.com/stretchr/testify (10k+ 关注)
GoConvey
支持 BDD
能够使用
go test
来运行测试能够通过浏览器查看测试结果
自动加载更新
GinkGo
https://github.com/onsi/ginkgo (4K+ 关注)
也是一个 BDD 测试框架
能够使用
go test
有自己的断言库
Gomega
也支持自动加载更新
其它 Mock 库
到目前为止我们已经掌握了 Go 官方库 testing 和其它常见的测试框架的用法,能够方便我们编写和运行常规的单元测试。
但我们的系统往往比较复杂,依赖很多服务和基础组建,比如一个 Web 服务往往依赖 MySQL、Redis 等,这里主要讲解采用模拟(mock-屏蔽掉这些服务的实际调用)的方式来测试我们的代码逻辑。
GoMock
https://github.com/golang/mock (4k+ 关注)
golang 官方推出的 mock 库
针对接口进行 mock
支持 mock 和 stub
采用
mockgen
生成代码
HTTPMock
针对 HTTP Request 来进行 mocking
能够自定义任意的 HTTP Response
截止 HTTP Request 直接返回自定义的 Response
给予正则匹配
SQLMock
针对
database/sql
的所有接口进行 mock基于正则表达式进行匹配
支持 查询、更新、事务等mock
与 Docker 集成
虽然我们可以采用 Mock 的方式屏蔽掉某些服务,但是还是存在某些服务比较复杂,很难 mock(如 MongoDB) ,而且有时我们确实想和依赖的服务做某些集成测试。
此时我们可以用 Docker 来快速构建我们的测试依赖环境,并且用完即释放、非常高效,下面就是一个包含 MongoDB 的 Dockerfile:
总结
本次分享主要从单元测试的重要性入手,依次讲解了官方库 testing、社区测试框架(Testify、GoConvey、GinkGo)、Mock 相关技术、Docker 集成的内容,总结如下:
单元测试应该是一个团队共识
单元测试并不难
使用 Mock 能够使我们单元测试高效
应该面向接口编程,方便做 mock (gomock)
官方库足够优秀,包含表格测试、http 测试相关内容
社区有很多优秀测试框架,能够让我们更好的实践 BDD或者TDD
Docker 能够适用于更复杂的测试场景
参考
版权声明: 本文为 InfoQ 作者【_why先生】的原创文章。
原文链接:【http://xie.infoq.cn/article/6bb120f616bdb57da996d0ba6】。文章转载请联系作者。
评论