对开发而言,测试的重要性相信对每个开发者而言是老生常谈的事情。虽然我们很有可能在开发过程中由于各种原因会希望后续补全,然而事实上我更建议采用“Tests that fail then pass”原则去处理在实际开发过程中遇到的问题。

在我们开发过程的初期阶段,开发质量的保持更多依赖开发人员自身素质保持。但是对一个团队而言,未必能够一直保持人员的高素质开发。在这个过程中,人员的变动,新老编码习惯的冲突,人员能力的残次不齐都有可能导致代码的腐化。在测试过程中,我们选择引入测试保障代码的质量

Go本身提供了基础的测试功能,但是这个功能在实际使用过程中仍有使用起来功能较弱的问题。比如我们在使用过程中,需要使用额外的库让测试代码更佳高效。在实际实践过程中,我推荐使用GinkgotestifyGoMock工具。

GoMock

GoMock工具是Golang官方提供的针对接口的代码生成测试工具。在实际的单元测试过程中,通常会选择Mock掉数据库(DB/KV)、外部服务调用操作部分,将这部分功能留在集成测试中完成。

比如我们将数据操作类型抽象成接口CreatorUpdaterDeleter等,借助接口的组合功能,针对我们需要的功能进行组合开发。在测试过程中,我们可以借助GoMock工具生成对应的测试辅助代码。

以对最简单的io.ReadeCloser使用代码为例:

package tddimport "io"func Read(r io.ReadCloser, buf []byte) (n int, err error) {n, err = io.ReadFull(r, buf)return
}

生成对应的mock方法,这里为了方便,我们使用-package参数定义包名,为了区分生成文件,添加了_ten_test.go后缀。

# 指定生成io.ReadCloser的mock方法
# 如果有专门的文件定义对应接口定义,则可以通过-source方法指定一次性提取所有接口
mockgen -package tdd io ReadCloser > reader_gen_test.go

接下来就是使用这个方法进行操作了,我们可以在reader_test.go文件中进行:

package tddimport ("io""reflect""testing""github.com/golang/mock/gomock"
)func TestRead(t *testing.T) {ctrl := gomock.NewController(t)defer ctrl.Finish()r := NewMockReadCloser(ctrl)r.EXPECT().Read(gomock.AssignableToTypeOf([]byte{})).SetArg(0, []byte{0x0, 0x1, 0x2, 0x3, 0x4}). // 设置参数值Return(5, io.EOF).                          // 设置返回值AnyTimes()                                  // 执行次数buf := make([]byte, 5)Read(r, buf)want := []byte{0x0, 0x1, 0x2, 0x3, 0x4}if !reflect.DeepEqual(want, buf) {t.Errorf("Read() failed. want=%v, got=%v.", want, buf)}
}

testify

我们在上面的例子中,会发现使用reflect.DeepEqual方式对比,然后调用t.Errorf方式输出错误信息。但是这里面其实相对来说要麻烦一点,另外一个则是对数据而言,如果内容较多,我们没办法一一对比可能出现的内容,这种情况下testify工具则可以提供一种更便捷的方式帮助我们进行测试的管理。

为了方便对比这个测试内容,我们把上面DeepEqual的判断条件取反,获取的错误的内容对比验证一下:

# DeepEqual
=== RUN   TestRead
--- FAIL: TestRead (0.00s)/Users/kevin/Desktop/tdd/reader_test.go:26: Read() failed. want=[0 1 2 3 4], got=[0 1 2 3 4].
FAIL

现在,我们将测试文件替换为testify方式进行:

package tddimport ("io""testing""github.com/golang/mock/gomock""github.com/stretchr/testify/assert"
)func TestRead(t *testing.T) {ctrl := gomock.NewController(t)defer ctrl.Finish()r := NewMockReadCloser(ctrl)r.EXPECT().Read(gomock.AssignableToTypeOf([]byte{})).SetArg(0, []byte{0x0, 0x1, 0x2, 0x3, 0x4}). // 设置参数值Return(5, io.EOF).                          // 设置返回值AnyTimes()                                  // 执行次数buf := make([]byte, 5)Read(r, buf)want := []byte{0x0, 0x1, 0x2, 0x3}if !assert.Equal(t, want, buf, "Read failed") {return}
}

获取测试结果:

=== RUN   TestRead
--- FAIL: TestRead (0.00s)/Users/kevin/Desktop/tdd/reader_test.go:25:Error Trace:   reader_test.go:25Error:         Not equal:expected: []byte{0x0, 0x1, 0x2, 0x3}actual  : []byte{0x0, 0x1, 0x2, 0x3, 0x4}Diff:--- Expected+++ Actual@@ -1,3 +1,3 @@-([]uint8) (len=4) {- 00000000  00 01 02 03                                       |....|+([]uint8) (len=5) {+ 00000000  00 01 02 03 04                                    |.....|}Test:        TestReadMessages:       Read failed
FAIL
coverage: 100.0% of statements

另外,在testify工具中,还提供了assert.JSONEq等等非常有用的函数,可以自行研究一下。同时,testify工具还提供了Testsuite功能,用于方便的设置Setup和Teardown函数。

你会发现testify工具还提供了mock功能,不过在实际过程中,不太建议使用该功能

Ginkgo

Ginkgo是针对Go程序进行BDD开发的工具,虽然它默认搭配使用gomega工具,不过我们还是建议你选择testify工具。你可以使用下面的方法快速接入testify

package foo_testimport (. "github.com/onsi/ginkgo""github.com/stretchr/testify/assert"
)var _ = Describe(func("foo") {It("should testify to its correctness", func(){assert.Equal(GinkgoT(), foo{}.Name(), "foo")})
})

Ginkgo工具提供了完善的文档介绍,你可以参考工具官方文档了解具体的使用。另外一个Ginkgo非常有用的是它可以方便接入已有的测试日志捕获程序,比如你是JUnit的用户,你可以选择将日志格式输出成JUnit XML格式:

package foo_testimport (. "github.com/onsi/ginkgo". "github.com/onsi/gomega""github.com/onsi/ginkgo/reporters""testing"
)func TestFoo(t *testing.T) {RegisterFailHandler(Fail)junitReporter := reporters.NewJUnitReporter("junit.xml")RunSpecsWithDefaultAndCustomReporters(t, "Foo Suite", []Reporter{junitReporter})
}

总结

文章总结了一些常见的涉及测试的工具,希望对你在实践过程中有所帮助。顺带,我还没忘记要完成这个系列。:D

Go 写测试必学的三个库:Ginkgo、testify和GoMock相关推荐

  1. python操作excel_使用Python操作Excel时必学的3个库

    Python对Excel的操作我主要用xlwt.xlrd.xlutils这三个库. 1.xlwt主要用来创建并写入数据到Excel.已经存在的表不可以写入. 以下使用Python写九九乘法表到Exce ...

  2. 高效测试必学 | 用pytest生成测试报告

    1.pytest-html生成报告 pytest借助pytest-html插件生成测试报告,不用自己编写生成报告代码. github源码地址: https://github.com/pytest-de ...

  3. php trader bbands,外汇交易必学的三种技术指标之 布林线(Bollinger Bands)

    在交易外汇之前,首先要先学会如何看基础K线,透过K线了解市场的反应,接着才是开始学习技术指标.在MT4上有数十种技术指标,加上交易者自定义的指标少则上百多则上千种指标! 其实我们真正要学的技术指标并不 ...

  4. Python学记(三)turtle库

    Python标准库:turtle库 Mark一下上次课的两个编程习题 获得用户输入的一个整数,参考该整数值,打印输出"Hello World",要求:‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫ ...

  5. 干货来袭!3天0基础Python实战项目快速学会人工智能必学数学基础全套(含源码)(第3天)概率分析篇:条件概率、全概率与贝叶斯公式

    第1天:线性代数篇:矩阵.向量.实战编程 第2天:微积分篇:极限与导数.梯度下降.积分.实战编程 第3天:概率分析篇:条件概率与全概率.贝叶斯公式.实战项目 目录 前言 一.概率与机器学习 1.1 概 ...

  6. 简单介绍三个C语言图形库C语言其实最擅长的是写纯数据处理的程序 . 非得用C语言写个界面程序那将会变得很困难 . 我刚开始学C语言就是从hello world 开始的 , 后来慢慢开始学从三个数中找

    C语言其实最擅长的是写纯数据处理的程序 . 非得用C语言写个界面程序那将会变得很困难 . 我刚开始学C语言就是从hello world 开始的 , 后来慢慢开始学从三个数中找出最大值 , 和对数组进行 ...

  7. 深度学习入门必学(第三篇:循环神经网络01)

    深度学习入门必学(第三篇:循环神经网络01) 一,第三篇:循环神经网络01 来自 一,第三篇:循环神经网络01

  8. react 进阶必学 hook (三):useContext 面馆分店开张了

    系列文章传送门: react 进阶必学 hook (一):useState 来一碗大碗宽面 react 进阶必学 hook (二):useEffect 专治不吃宽面 react 进阶必学 hook ( ...

  9. Socket编程知识必学/SELECT 编程

    Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如 connect.accept.recv或recvfrom这样的阻塞程序 ...

最新文章

  1. 分析周鸿祎的安全卫士360[转]
  2. 边缘与锐化滤波(MATLAB)
  3. 站长就是个太监^_^
  4. 吐血整理 《计算机网络 五层协议之物理层(上)》
  5. 区块链学堂(2):最简单的智能合约
  6. RabbitMQ死信实战(消费者1)
  7. 【算法分析】实验 4. 回溯法求解0-1背包等问题
  8. Java 8 新特性 Optional 类学习,理解并应用。NullPointerException空值检测
  9. 超神!卡内基博士ImageNet夺冠后转战NLP!
  10. iptables学习笔记:使用NAT实现简单的无线AP
  11. 树莓派-解决apt-get upgrade速度慢的方法[更换阿里云源]
  12. 图形算法 - 模糊函数比较,Blur Function Compare。
  13. python学习day_04_字典
  14. Oracle的卸载过程步骤
  15. 美国旅游签证申请的行程单参考模板
  16. 最新实用油猴脚本推荐
  17. tensorflow下手写汉字识别及其可视化
  18. 一步步学习改变思维习惯
  19. PS中矢量形状图层的合并交叉等运算
  20. Android 系统内的守护进程 - core类中的服务 (5) : logd

热门文章

  1. 中科院计算机控制学院难度,16年自动化所复试失败经验
  2. 代码阅读方法与最佳实践
  3. H2/H∞半车悬架控制仿真分析
  4. 高德SD地图数据生产自动化技术的路线与实践(道路篇)
  5. 计算机专业未来规划作文英文,我的未来计划英语作文范文(通用10篇)
  6. kafka日志清理策略,compact和delete
  7. 自动在副屏/虚拟屏启动100%鲜橙汁 | 可用于上班摸鱼
  8. 影院活动管理系统 项目测试与部署
  9. Frp内网穿透实现远程桌面连接
  10. 如何删除Windows更新后残留的文件