Golang 单元测试框架 gocheck 使用介绍

345 阅读6分钟
原文链接: click.aliyun.com

什么是好的单元测试框架?

单元测试应该在的功能和参数上验证程序的正确性;单元测试过后,机器状态应该保持不变;单元测试的运行、通过、失败不依赖于别的测试,可以人为构造数据,以保持单元测试的独立性。

Gocheck 简介

gocheck 是 golang 语言比较健全且简单的单元测试框架,gocheck 在 golang 官方的testing package 之上,丰富了很多功能,丰富了单元测试常用的 assert 断言,判断动词deep multi-type 对比,字符串比较以及正则匹配。测试用例组织集合方面按suite组织测试用例,支持suite级别的 setup() 和 teardown()。对于临时文件支持创建、删除临时文件和目录。

Assert 断言的使用

Assert 根据预期 Checker 值检验接口返回值与预期值是否匹配,如果它们不匹配,则会记录错误,测试记录不通过,并且测试用例将停止。func (c *C) Assert(obtained interface{}, checker Checker, args ...interface{}) 那么如上代码所示的hecker接口是怎么来实现验证的呢?hecker接口是必须与 Assert 和 Check 验证方法一起使用的检查器。

首先需要定义好Checker接口,代码如下:

b9ab252f7d62dc5474f4a8603cadbcb8259abe6a

其中的 CheckerInfo 为一个结构体,用来定义我们基准校验的参数格式。

checker 中有比较多的检查器,一般可以满足我们正常情况下的各种检查需求,比如ErrorMatches 检查器验证错误值是否为非零并与提供的正则表达式匹配。

检查器代码可以这么写:

a560f3c624e0c5b60f2b03091c1f42bbb89d9f8c

Assert校验代码:

e318d6d416608bc08f7d3bbd9ab4b247ddade93d

以上就是一个接口的简单校验流程。同时 Checker 检查器提供了比较丰富的检查器方法,下面简单列几种:

DeepEquals 全等校验,类型必须相同,校验比较严格,一般很少使用,因为校验结果失败的概率比较高;

Equals 相当于 ==校验,比全等校验相对来说要宽松一点;

FitsTypeOf 校验类型是否一致;

HasLen 校验长度是否一致;

IsNil 校验返回值是否为空;

func Not(checker Checker) 反转提供的检查器的逻辑,生成的检查器将在原始检查器失败的情况下成功,反之亦然。

临时文件的使用

采用临时文件方法,满足单元测试要读写文件需求。

对于测试的过程中我们经常要用到前期的大批量的读写文件操作,但是大量的数据文件可能会导致测试完成后服务器状态改变,为了遵循”单元测试过后,机器状态保持不变”的原则,我们需要在单元测试结束后自动清理掉单元测试运行中用到和产生的大量临时文件存储的数据。gocheck 可以创建一个临时目录,在测试结束时自动删除它,省去了手动清理的步骤。

示例代码:

1a1e2fbf6ff87f9da2d614ed78c4728c90ba7b03

跳过测试的使用

用于对测试 suite 的过滤,当有些测试 suite 是特定情况才需要在报告中体现的时候,可以选择用这个方法,方便测试报告生成和测试过程中的特意过滤。

可以使用 SetUpSuite,SetUpTest 中的 skip 方法或测试方法本身跳过测试。这允许根据自定义因素选择性地忽略测试,例如正在运行的体系结构,提供给测试的标志或资源的可用性(网络等)。

例如,除非提供 -live 选项进行测试,否则以下测试套件将跳过套件中的所有测试

示例代码:

6d64ecf80e77f4c07ebb4fec5e2c2e21ea53a0cb

Mock server api 相关的测试使用

对于测试的过程中我们经常会遇到需要调用外部 api 的情况,这样的话外部 api 的响应成功与否直接影响我们当前单元测试的成功与否,与单元测试要求的独立性背道而驰,所以我们最后用 mock 数据的方法来保证单元测试的独立性。

利用 gocheck 的 SetUpSuite() 和 TearDownSuite() 方法,可以新建一个 http test server,结束时关闭它。

8e7cd8ff354f4baaffc7923eb337566bc2a26374

知乎提问代码测试实例

大家都知道知乎的提问和回答功能是整个知乎社区比较重要的一个功能,在知乎社区有疑问提出问题后,想要修改自己提出的问题的详细描述这部分功能代码要怎么进行测试呢?下面就来讲讲这个比较小的点要怎么去进行单元测试。

1. 需求分析

测试提问的详细内容更新这个功能函数,变量有详细内容具体信息,更新原因,更新时间,更新用户这个四个变化的参数,其中更新时间和更新用户部分可以直接获取,也不是我们单测的重点,那么重点就剩两个更新具体信息和更新原因,更新原因是一个给出的list去筛选,所以不是关注重点,更新具体详细内容是此次测试的重点。开始分析这个参数的限制条件,在提问中问题详情字数限制3000字,并且必填。

2. 测试代码编写

2.1 所用函数库分析

因为需求中要求3000字,所以为了保证服务器测试前后一致性,需要用到临时文件函数,对3000字文档进行临时存储,用完销毁操作。

2.2 具体单元测试函数编写

2.2.1 命名规范

单元测试文件命,根据需要测试的文件命名,比如被测试文件名为 question.go,那么测试文件名即为 question_test.go

2b0d95992447fa749ee85d18464b75861b43de3b

2.2.2 代码编写

创建临时文件夹以及临时文件内容

ef5e0b55752504c520cd286ff1d9de48e549a569

参数传递时将临时文件内容当问题详细内容参数,这样在测试代码运行结束后问题详细内容的参数就会被销毁不会在服务器上产生多余的文件。

ed0817408f553e4e0c3e50242817744b90d1a73e

3. 结果分析

每次底层数据库变成,存储变更,外部以来接口服务变更,但是数据结构和调用结果不变更的情况下可以利用单元测试结果对现有业务逻辑进行快速检查。

最后

 ●  Gocheck 框架对 golang 代码进行单元测试比原生的单元测试框架写起来更方便和快速,函数库基本可以满足大部分的使用场景。
 ●  整个框架本身在 github 开源可以添加自己需要的函数库。
 ●  更详细的使用说明参见 gocheck 的 api 文档。

原文发布时间为:2018-10-18 本文作者:icy 本文来自云栖社区合作伙伴“ Golang语言社区”,了解相关信息可以关注“Golang语言社区”。