在做一些通用组件代码时,测试用例覆盖是一个非常好的习惯
代码的测试覆盖,常用的到功能点为两个,一个是断言,一个是mock数据
mock数据我感觉这个包不大好用,还是只说断言吧
下面将以示例的方式对轮子包 testify
做一个说明
断言
一个简单的示例
这里不在对test基础使用做过多介绍,例如用例命名、文件名之类的,使用方法自行查阅资料
// test/run.go
package main
func Add(a, b int) int {
return a + b
}
上面是一个业务代码,我们对Add
方法做用例测试
使用标准库testing
包
// test/run_test.go
package test
import (
"testing"
)
func TestAdd(t *testing.T) {
got := Add(2, 2)
want := 4
if got != want {
t.Errorf("Add(2,2) should be 4")
}
}
运行这个用例 go test -run ^TestAdd$ limiter/test -v
[-v 显示详细信息 ^$ 表示正则匹配只运行这个用例]
=== RUN TestAdd
--- PASS: TestAdd (0.00s)
PASS
ok limiter/test 0.635s
其中的等于用例,需要自行通过if
语句判断
接下来再看下第三方库github.com/stretchr/testify
的使用
package test
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestAdd(t *testing.T) {
assert.Equal(t, Add(2, 2), 4, "Add(2,2) should be 4")
}
再次运行
=== RUN TestAdd
--- PASS: TestAdd (0.00s)
PASS
ok limiter/test (cached)
同样的效果,使用assert
库,代码也不是说多简洁,而是将用例有if语句判断,然后输出日志这种传统思维,转变成断言判断这种以结果为测试的思维导向
这种更倾向于测试结果化
常用的断言方法
最后一个参数大部分是断言的描述
- 等于
assert.Equal(t, Add(2, 2), 4, "Add(2,2) should be 4")
- 不等于
assert.NotEqual(t, 3, 5)
- true or false
assert.True(t, true, "should is true")
assert.False(t, false, "should is false")
- 是否是nil
assert.Nil(t, nil)
- contains 包含
assert.Contains(t, "hello world", "world") // 字符串
assert.Contains(t, [3]int{1, 2, 3}, 2) // 数组
assert.Contains(t, map[string]int{"a": 1, "b": 2}, "a") // map
assert.Contains(t, []string{"a", "b", "c"}, "b") // slice
- 是否是error
assert.Error(t, errors.New("a error"), errors.New("a error"))
assert.NoError(t, err) // err变量是否为nil
assert.ErrorIs(t, err, context.Canceled) // err变量是否是context.Canceled类型的err
- 是否是empty
assert.Empty(t, []string{})
assert.Empty(t, map[string]int{})
assert.Empty(t, "")
- zero 是否为零值
assert.Zero(t, 0) // 整数
assert.Zero(t, 0.0) // 小数
assert.Zero(t, false) // 布尔
一个语法糖,少传一个参数
func TestAssert(t *testing.T) {
asserts := assert.New(t)
asserts.Equal(2, 2)
asserts.Equal(3, 3)
// 下面这种写法,每次都要将testing.T传进去
// assert.Equal(t, 2, 2)
// assert.Equal(t, 3, 3)
}
require断言
assert.Zero(t, 0.1)
assert.Zero(t, false)
假如第一个断言失败,后面的断言不允许执行,require 就是来解决这个问题
assert
与require
的区别
- assert断言失败,测试函数继续执行;
- require断言失败,测试函数直接退出;
assert支持的方法,require也都支持
package test
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestRequire(t *testing.T) {
require.Equal(t, 2, 1)
fmt.Println("==由于前面require失败,所以这里不会执行=====")
}
func TestAssert(t *testing.T) {
assert.Equal(t, 2, 1)
fmt.Println("===虽然前面assert会失败 但是仍会继续执行===")
}
通过上面代码,应该会有个清晰的认知了