Go 语言编写单元测试

Go 语言对于单元测试是很重视的,且不说其他的作者的背景啊,开源库啊,第三方的支持之类的,有两点让我对 Go 语言关于单元测试的重视程度的有信心的点在于:

Go 语言源代码和内置库自身的单元测试完备性

Go 语言自带单元测试命令

从这两点,我认为测试在 Go 语言中具有非常重要的地位,所以在这篇文章中,我也尝试讲一些关于 Go 语言单元测试的东西。

编写 Go 单元测试代码

Go 的测试方法看上去相对比较低级,它依赖于命令 go test 和一些能用 go test 运行的测试函数的编写约定。但是,我认为这就是所谓的 Go 风格,用 Go 以来,我的感受是 Go 语言就是保持了 C 语言编程习惯的一门语言。

首先,为了开始这篇文章,我写写一个简单的函数用作后面要测试的例子,但是,考虑到后面可能要讲一些稍微复杂一点的内容,所以,这个例子我留有一些可以改变的地方,大家可以选择着看:

Go 语言编写单元测试

这个例子就是这么简单,将这个文件命名为 main.go,然后我们就应该编写测试代码了。测试代码的文件放置的位置可以随意,package 也可以随意写,但是,文件名必须以 _test 结尾,所以,我这里就命名为 main_test.go

这里编写测试函数,有几个需要注意的点:

每个测试文件必须以 _test.go 结尾,不然 go test 不能发现测试文件

每个测试文件必须导入 testing

功能测试函数必须以 Test 开头,然后一般接测试函数的名字,这个不强求

根据这些条件,我们可以写出一个测试文件:

Go 语言编写单元测试

测试文件写完之后,我们就应该执行测试了,打开命令行工具,敲入这条命令:go test main_test.go main.go -v -cover

然后就应该等待测试结果了,这里加了两个参数,分别是 -v 和 -cover,如果不加上的话你会发现只有 Test Pass 的简单提示,而看不到我们加了参数的具体提示:

=== RUN TestAdd --- PASS: TestAdd (0.00s) PASS coverage: 50.0% of statements ok command-line-arguments 0.008s 基于表的测试方式

在 Go 语言中,有一种常用的测试套路,叫做基于表的测试方式,其核心就是我们需要针对不同的场景,其实也就是不同的输入和输出来验证一个功能。例如我们要验证的 Add 函数,我们需要验证的功能点有很多,例如:

两个正数相加是否正确

两个负数相加是否正确

一个正数加上一个负数是否正确

有一个数为 0 是否正确

那么,我们就可以使用 基于表的测试方式 了,代码可以这样写:

Go 语言编写单元测试

Mock 依赖

前面介绍的测试都是比较简单的,功能简单的话我们就可以直接给定输入,然后看输出是否符合预期,这样就可以很简单得写完单元测试了。但是,有的时候,由于业务逻辑的复杂性,功能代码并不会就这么直接,往往还会掺杂很多其他组件,这就给我们的测试工作带来很大的麻烦,我这里列举几个常见的依赖:

组件依赖

函数依赖

组件依赖和函数依赖是两种比较常见的依赖,但是,这两种依赖也是可以扩展开来说的,既可能来自于我们自己编写的组件/函数,也可能是引入其他人写的。但是,无妨,对于这些情况,我们都会做一些分析。

组件依赖处理

使用 Go 语言开发项目的时候,我们应该经常会抽离组件模块的,既然抽离了组件和模块,那么久离不开组件的依赖了,既然有依赖,在测试的时候我们很多时候都是希望屏蔽掉依赖组件的影响,从而更好得测试现有代码的细节;或者说,我们希望根据自己的测试目标,控制依赖组件的行为。但是,如果我们还想简单得通过控制输入和输出来控制依赖组件的行为,这个难度还是比较大的,所以,在这种情况下,我们一般会考虑传一个 Stub 组件进入,从而达到控制依赖组件行为的效果。

举一个例子先,例如我们比较常见的 Service 层和 DAO 层的操作,Service 处理完逻辑之后,交给 DAO 层进行持久化,或者需要调用 DAO 层从持久化中获取一些必要的数据;在测试的时候,我们很多时候不希望真的持久化或者从持久化中获取数据,那么就会对 DAO 层进行一些 Mock。首先,先给出一个运行的例子:

Go 语言编写单元测试

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/56ec83ef964b0afcee7e97d920f408cd.html