这是我参与「第五届青训营」伴学笔记创作活动的第 15 天
这是我参与「第五届青训营」伴学笔记创作活动的第 15 天
前言
因为项目中接到了负责测试的任务,今天深入的聊一聊测试
单元测试
单元测试文件说明
- 文件名必须是
_test.go结尾的,这样在执行go test的时候才会执行到相应的代码。 - 你必须
import testing这个包。 - 所有的测试用例函数必须是
Test开头。 - 测试用例会按照源代码中写的顺序依次执行。
- 测试函数
TestX()的参数是testing.T,我们可以使用该类型来记录错误或者是测试状态。 - 测试格式:
func TestXxx (t *testing.T),Xxx部分可以为任意的字母数字的组合,但是首字母不能是小写字母[a-z],例如Testintdiv是错误的函数名。 - 函数中通过调用
testing.T的Error,Errorf,FailNow,Fatal,FatalIf方法,说明测试不通过,调用Log方法用来记录测试的信息。
基准测试
go test <module name>/<package name> 用来运行某个 package 内的所有测试用例。
- 运行当前 package 内的用例:
go test example或go test . - 运行子 package 内的用例:
go test example/<package name>或go test ./<package name> - 如果想递归测试当前目录下的所有的 package:
go test ./...或go test example/...。
go test 命令默认不运行 benchmark 用例的,如果我们想运行 benchmark 用例,则需要加上 -bench 参数。
-bench 参数支持传入一个正则表达式,匹配到的用例才会得到执行,例如,只运行以 Fib 结尾的 benchmark 用例:
$ go test -bench='Fib$' .
参数:
-benchtime=5s // 测试次数递增限制时间
-benchtime=50x //-benchtime 的值除了是时间外,还可以是具体的次数。
-benchmem //内存信息
不同的函数复杂度不同,O(1),O(n),O(n^2) 等,利用 benchmark 验证复杂度一个简单的方式,是构造不同的输入。对刚才的 benchmark 稍作改造,便能够达到目的。
func BenchmarkGenerate1000(b *testing.B) { benchmarkGenerate(1000, b) }
func BenchmarkGenerate10000(b *testing.B) { benchmarkGenerate(10000, b) }
func BenchmarkGenerate100000(b *testing.B) { benchmarkGenerate(100000, b) }
func BenchmarkGenerate1000000(b *testing.B) { benchmarkGenerate(1000000, b) }
BenchmarkGenerate1000-8 34048 34643 ns/op
BenchmarkGenerate10000-8 4070 295642 ns/op
BenchmarkGenerate100000-8 403 3230415 ns/op
BenchmarkGenerate1000000-8 39 32083701 ns/op
定时器
b.ResetTimer() // 重置定时器 // 屏蔽准备活动时间
b.StopTimer() // 暂停计时器
b.StartTimer()// 开始计时器
mock打桩
Mock 是什么
mock 测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。这个虚拟的对象就是mock对象。mock对象就是真实对象在调试期间的代替品。
mockery
mockery 与 Go 指令(directive) 结合使用,我们可以为 interface 快速创建对应的 mock struct。即便没有具体实现,也可以被其他包调用。我们通过 LazyCache 的例子来看它的使用方法。
假设有一个第三方服务,我们把它封装在 thirdpartyapi 包里,并加入 go directive,代码如下:
package thirdpartyapi
//go:generate mockery -name=Client
// Client defines operations a third party service has
type Client interface {
Get(key string) (data interface{}, err error)
}
我们在 thirdpartyapi 目录下执行 go generate,在 mocks 目录下生成对应的 mock struct。目录结构如下:
~ $ tree thirdpartyapi/
thirdpartyapi/
├── client.go
└── mocks
└── Client.go
1 directory, 2 files
在执行 go generate 时,指令 //go:generate mockery -name=Client 被触发。它本质上是 mockery -name=Client 的快捷方式,优势是 go generate 可以批量执行多个目录下的多个指令(需要多加一个参数,具体可以参考文档)。
参考材料:
- lailin.xyz/post/go-tra…
- geektutu.com/post/hpg-be…
- blog.csdn.net/wwh57886781…
- segmentfault.com/a/119000001…
码风略丑 读者见谅 --2023/2/17