首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Go语言如何在没有实现功能的情况下写出完善的单元测试代码

背景

最近在研究用Go写一个自己的解释型语言,有一本书叫《Writing An Interpreter In Go》, 作者在讲解如何编写解释器的时候,都是从写一个开始的,也就是说作者习惯于先写单元测试,以测试驱动开发,其实这是一个非常好的习惯,不过,作者在写文件的时候,都是先假设这个结构体、函数已经存在了,并且没有把关键的对象抽象成接口,因此,作者在运行的时候,是无法完成测试的,因为连编译都过不了,必须一边完善代码,一边重复运行,一直到完成开发。

基于这种开发模式下,其实我更期望能有一个Mock实现,写测试代码的时候畅通无阻,即使是没有实现,也能把各个测试用例覆盖到,当真实的实现完成后,我们只需要把mock实现替换成真实的实现就好了。

这么做还带来另一个好处,如果公司有SDET岗位,则可以直接让测试人员编写单元测试,开发任务和测试任务可以并行。

gomock 框架

昨天闲着没事逛了逛 https://github.com/golang, 发现了一个非常有意思的框架: gomock, 官方的描述是,这是一个mocking framework, 在使用上也很简单,大致的步骤如下:

1、定义一个待实现的接口.

2、使用生成mock代码.

3、测试:

看了这个步骤,想必大家应该猜到了,mocking framework 使用的是根据你的接口定义来自动生成一个Mock实现,我们还可以往这个实现里注入数据。

期望接口调用参数

我们可以通过 为这个mock对象注入期望值

测试通过:

测试不通过:

对于参数类型的期望,在调用这个Mock函数的时候会直接抛错异常

期望返回值

同样可以为某个函数注入返回值

测试通过:

测试不通过:

功能强的还不止这个,如果我们在测试一个循环,

希望的是每次调用 都返回不同的值,该怎么办?

答案很简单,依次调用

接下来,让我们来实战一下吧。

gomock 实战

我们以《Writing An Interpreter In Go》这本书中的 语言的 作为例子

我们看一下 的目录结构:

Lexer和Token

lexer的功能很简单,每次调用,都是返回下一个

的结构

比如下面的语句

lexter 在调用三次后会得到三个Token, 依次是:

测试思路

其实测试方法就是:给定一段代码,用Lexer解析后,能得到指定顺序的Token,而是完全可以实现的。

使用gomock

安装gomock

生成mock代码

编写lexer_test.go

测试数据

input: 输入的语句

tokens: 期望的Token

生成一个真实的MonkeyLexer实例

当然,这里我们没有实现,所以返回是

构建MockLexer实例

由于没写完真正的lexer, 那么我们就开始Mock吧

为了方便在mock实例和真实实例之间进行切换,我们可以通过环境变量来控制当前的测试实例是什么,如果要使用mock进行测试,我们只需要在运行 前执行:

以下是真正的测试代码,在没真实实现的情况下,我们可以写测试代码了,而且如果运行 也是能通过的。

下载完整的代码:

https://github.com/xujinzheng/monkey

测试

使用mock实例进行测试

使用真实实例测试

我们将测试数据修改一下,假设 , 但不修改期望值,让测试报错

再次运行测试

这里就报错了,说明我们的真实实例实现得有问题,需要修复这个BUG

的使用到这里就结束了,除了上面介绍到的一些功能, 还有很多其他丰富的方法,大家可以去 GoDoc 获取更详细的接口信息。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190506A0KVFB00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券