测试|青训营笔记

99 阅读3分钟

这是我参与「第五届青训营」伴学笔记创作活动的第 15 天


这是我参与「第五届青训营」伴学笔记创作活动的第 15 天

前言

因为项目中接到了负责测试的任务,今天深入的聊一聊测试

单元测试

单元测试文件说明

  • 文件名必须是_test.go结尾的,这样在执行go test的时候才会执行到相应的代码。
  • 你必须import testing这个包。
  • 所有的测试用例函数必须是Test开头。
  • 测试用例会按照源代码中写的顺序依次执行。
  • 测试函数TestX()的参数是testing.T,我们可以使用该类型来记录错误或者是测试状态。
  • 测试格式:func TestXxx (t *testing.T),Xxx部分可以为任意的字母数字的组合,但是首字母不能是小写字母[a-z],例如Testintdiv是错误的函数名。
  • 函数中通过调用testing.TErrorErrorfFailNowFatalFatalIf方法,说明测试不通过,调用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 可以批量执行多个目录下的多个指令(需要多加一个参数,具体可以参考文档)。

参考材料:


码风略丑 读者见谅 --2023/2/17