本文作为阶段性总结,陆陆续续使用 golang 也有2年时间了。 大约也是从2年多以前要求自己写的每一行代码都能经过测试,最近一年时间要求尽量覆盖到每一行代码。 更严谨一些的情景,例如重要的一致性数据等,还要求自己将条件判断列出决策树情景进行用例覆盖。

Python栈内使用pytest以及配套的设施做起来已经非常熟悉,今天来总结一下 golang 里测试 的常规使用方法。

先来看一下go中的测试

按照官方文档的介绍1,go中写测试是相当方便的,有点像dlang2。 不过后者推荐直接将测试写到源代码文件中,编译器可以根据需要直接处理。

回到 golang 中的测试, 在源代码所在目录里直接以 *_test.go 命名里面带上测试用例即可。

$ go test

约定俗成与几个坑

setup与teardown

在golang里测试方法原生是没有支持的,需要自己实现。也可以参考这里的文档用法,自行加上支持。

一种比较简单原始的做法

断言与检查

一般来说做检查断言分为两种情况,叛乱表达式是否为真,以及返回的变量内容是否符合逾期; 后者一般也即相等比较。而对象相等在各个语言里实现思路不一定一样,一般笔者采用做法还是检查 每个成员变量的内容,避免一些过于细节的问题导致测试意外跑不过。

在 golang 里可以使用 gotest.tools 包里提供的断言功能

数据库的测试

并行引发的问题

默认 go test 会使用 GOMAXPROCS 变量,也就是CPU核数来并发运行测试,以缩短运行时间。 这个功能固然在大多数情况下很棒。不过如果测试的数据库都在同一个下面,那么并发运行可能会 引发测试数据依赖互相错乱导致的问题。可以加上 -p 1 参数(参考 go build 命令), 限制以单核运行。

$ go test -p 1

撰文时另外搜索到似乎还有更好的解决方案3允许并行运行,可以考虑尝试。

覆盖率

值得一提的性能测试

提供这样一个便利的方式运行性能测试是相当值得赞赏的,虽然在其他栈里也可以自行添加相关设施 ,不过直接在标准库里支持还是表现出官方对性能的重视程度。

这里可能有这样几项基本的原则

来看一下例子

gin与其他HTTP的测试

这个测试思路实际上与其他语言环境例如Python中类似,由标准库创建的请求, 经过HTTP标准中间件(其他语言里例如WSGI,RACK等)的处理,相当于模拟一个HTTP请求, (实际上区别应该只在于实际处理请求是将网络内容读到字符串再进行解析后又中间层再转给框架) 发给 服务端框架处理,再得到响应后检查。参考以下代码:

GET请求

构造请求

添加参数

POST等需要BODY的请求

JSON结果的检查

暂时先这些

\_\_END\_\_