TA的每日心情 | 无聊 4 天前 |
---|
签到天数: 1050 天 连续签到: 1 天 [LV.10]测试总司令
|
推荐一些在go里面的测试工具。其中最著名的testify就是不得不推荐的了。很多开源项目都在用这个库构建测试用例。说到这里突然想到之前有人给goleveldb提交pr代码写自己的单元测试时引入了这个库,我还“批斗”了他,说修改代码和引入新的库是两码事,请你分开做hhhh,现在想想还蛮不好意思的。回归正题,我们来简单介绍一些testify这个库。
testify
testify这个库主要有三个核心内容,assert, mock, suite。assert就是断言,可以封装了一些判断是否相等,是否会有异常之类的。文章篇幅有限,这里就不对assert的api一一介绍了,感兴趣的朋友们可以看衍生阅读的相关文章。这里我主要介绍mock和suite模块。
mock
在我们要准备测试的时候经常需要准备一些数据,mock模块通过实现接口的方式来伪造数据。从而在测试的时候可以用这个mock的对象作为参数进行传递。废话不多说我们看下怎么简单的实践一下。
首先我们定义一个接口:
- //go:generate mockery --name=Man
- type Man interface {
- GetName() string
- IsHandSomeBoy() bool
- }
复制代码 这个接口定义了一个男孩子,一个方法是获取他的名字,第二个方法是看他是不是帅哥。这里我还推荐使用go:generate的方式执行mockery(执行go get -u -v github.com/vektra/mockery/.../安装)命令去生成对应的mock对象(生成的代码会放在当前目录的mocks目录下,当然你也可以在命令上添加参数指定生成路径),这样就不需要我们去实现mock对象的一些方法了。下面我们看下生成的代码是怎么样的。
- // Code generated by mockery v2.10.0. DO NOT EDIT.
- package mocks
- import mock "github.com/stretchr/testify/mock"
- // Man is an autogenerated mock type for the Man type
- type Man struct {
- mock.Mock
- }
- // GetName provides a mock function with given fields:
- func (_m *Man) GetName() string {
- ret := _m.Called()
- var r0 string
- if rf, ok := ret.Get(0).(func() string); ok {
- r0 = rf()
- } else {
- r0 = ret.Get(0).(string)
- }
- return r0
- }
- // IsHandSomeBoy provides a mock function with given fields:
- func (_m *Man) IsHandSomeBoy() bool {
- ret := _m.Called()
- var r0 bool
- if rf, ok := ret.Get(0).(func() bool); ok {
- r0 = rf()
- } else {
- r0 = ret.Get(0).(bool)
- }
- return r0
- }
复制代码 那么我们怎么使用呢?看看下面代码:
- func TestMan_All(t *testing.T) {
- man := mocks.Man{}
- // 可以通过这段话来添加某个方法对应的返回
- man.On("GetName").Return("Elliot").On("IsHandSomeBoy").Return(true)
- assert.Equal(t, "Elliot", man.GetName())
- assert.Equal(t, true, man.IsHandSomeBoy())
- }
复制代码 suite
有时候我们可能需要测的不是一个单独的函数,是一个对象的很多方法,比如想对leveldb的一些主要方法进行测试,比如简单的读写,范围查询,那么如果每个功能的单元测试都写成一个函数,那么可能这里会重复初始化一些东西,比如db。其实这里是可以做到共享一些状态的,比如数据写入之后就可以测试把这个数据读出来,或者范围查询。在这里的话其实用一种比较紧密的方式把他们串联起来会比较好。那么suite套件就应运而生。
|
|