在过去的几个月里,我对许多由Go语言编写的API进行了测试。非常有趣!用Go语言写代码也很有趣。值得注意的是,没有测试就不会有高质量的代码,所以我将在本文中重点探讨测试。
单元测试
和Python一样,Go是一种“开箱即用”的语言,所以自然地它包含了testing包,testing包提供了对自动运行单元测试的支持。以下是其文档摘录:
Go提供了testing包用于支持自动测试。它与“go test”命令协同使用,该命令可以自动执行任何形式的函数
func TestXxx(*testing.T)
Xxx可以是任意文数字组成的字符串(但首字母不能小写),用于识别测试程序。
但是,testing包提供的功能非常简单,所以我引入了名为testify的包,testify提供了测试套件和更友好的断言。
无论你是否使用testing或其他例如testify的第三方包,Go编写单元测试的方式都是将测试代码包含在以_test.go结尾的文件中,并和被测试代码放在同一目录。例如,有个名为customers.go的文件用于处理客户管理业务逻辑,你可以对这些代码编写单元测试,并将单元测试代码放进名为customers_test.go的文件中,并和customers.go在一个目录。然后,当对该目录执行“go test”命令的时候,单元测试代码将自动运行。实际上,“go test”找出所有名为*_test.go的文件并执行。你可以在“How to Write Go Code”一文的Testing章节找到更多关于Go单元测试细节。
集成测试
这里我要给出一些怎样组织集成测试的事例。让我们再次以测试处理客户管理的API为例。根据目的,集成测试将通过HTTP从外部访问API端点。与单元测试不同,单元测试是从内部测试API处理程序的业务逻辑。如上面所说,集成测试代码也要和API代码存放在相同的包中。
对于集成测试,我通常会为测试对象创建相应的目录,例如core-api。然后在那里创建main.go文件,用于设置测试所需的常量:
对于与customer API相关的集成测试,我创建了名为customer_test.go的文件,内容如下:
借助testify包,我就可以定义测试套件了,这是一个包含testifysuite.Suite匿名字段,名为CustomerTestSuite的结构体。Go语言通过组合替代继承,因此在测试套件中嵌入suite.Suite将使我可以在CustomerTestSuite中定义SetupTest和TearDownTest方法。在SetupTest中为所有测试函数做统一设置(在每个测试函数被执行前调用),并在TearDownTest中为所有测试函数做统一销毁(在每个测试函数被执行后调用)。
上面的例子中,SetupTest设置了一些变量,这样就能在每个测试函数中使用这些变量。下面是测试函数的例子:
对于实际HTTP调用后端API的测试过程,我在utils.go的create_customer函数中定义:
注意,我使用了grequests包,它是Python Requests库的Go语言实现。通过使用grequests,我可以用优雅的方式封装HTTP请求和响应,并轻松处理JSON。
回到TestCreateCustomerNewEmailPhone测试函数,一旦收到了调用创建客户API的响应,就调用另一个名为assert_success_response的协助函数,该函数使用了testify的assert包验证HTTP响应代码是否为200,并具体确认返回的JSON响应参数(如error_msg, error_code, req_id)是否和我们期望的一样:
为实际运行集成测试,我在包含测试文件的目录中执行了“go test”命令。
这个模式用于应对日益增长的API端点集成测试需求颇有价值。
测试覆盖率
在Go语言“开箱即用”系列工具中,有一部分是测试覆盖工具。要使用它,需要运用多个覆盖测试参数来运行“go test”。下面是一个用于生成测试覆盖率的shell脚本:
上面bash脚本的第一部分在运行“go test”时带入covermode=count参数,将统计每个子包(auth、customers等)。然后再将coverprofile输出文件(CTMP)合并到单个文件(CREAL)中。
第二部分通过带入covermode=count、coverpkg=[逗号分隔的包列表]参数运行“go test”, 对文件all_test.go进行集成测试。该文件启动一个HTTP服务器暴露API,然后在集成测试目录中调用“go test”访问API。
最后,通过运行mergecover工具,将来自单元测试和集成测试的覆盖率数据合并到CMERGE文件中。
至此,就能通过go tool cover -html=$CMERGE -o coverage.html命令生成html文件了,并能在浏览器中进一步查看coverage.html。目标是每个包的测试覆盖率超过80%。
AD Time
关于作者: 十年网络安全行业,八年Java EE研发、架构、管理,三年开源对象数据库社区运营,一年大数据、机器学习产线管理,知乎@rosenjiang。
领取专属 10元无门槛券
私享最新 技术干货