单元测试规则
- 所有测试文件以_test.go结尾
- 所有的测试方法以 func TestXxx(*testing.T),如果这个命名和实现正确在文件会有个可以运行的标志
- 初始化逻辑放到TestMain中 TestMain结构大致如下
func TestMain(m *testing.M){
//测试前:数据装载、配置初始化等前置工作
code := m.Run()
//测试后:释放资源等收尾工作
os.Exit(code)
}
覆盖率
go test judement_test.go judement.go--cover
用来测试你的测试代码中的覆盖程度是否已经测试完全了。
单元测试的Tips
- 一般覆盖率:50%~60%,较高覆盖率80%
- 测试分支相互独立、全面覆盖
- 测试单元粒度足够小,函数单一职责
单元测试Mock
这里推荐的是monkey:github.com/bouk/monkey
快速Mock函数
- 为一个函数打桩
- 为一个方法打桩
能够使得自己的测试方法不再依赖本地的文件
基准测试
简介
Go 语言的基准测试是一种测量程序性能的方法,通常用于测试函数或代码片段的执行速度。基准测试与单元测试相似,都是通过 testing 包实现的,但基准测试的目标是性能评估,而非功能验证。
功能
- 优化代码,需要对当前的代码分析
- 内置的测试框架提供了基准测试的能力
基本结构
Go 中的基准测试使用函数名以 Benchmark 开头,并接受 *testing.B 类型的参数。 基准测试的基本函数签名为:
func BenchmarkXxx(b *testing.B) {
for i := 0; i < b.N; i++ {
// 要测试的代码
}
}
- b *testing.B:
- 提供控制循环执行次数的功能。
- 包含统计基准测试结果的方法。
- b.N:
- 决定基准测试的循环次数,由 Go 的测试框架自动调整以保证测试时间足够长。
- 循环测试:
- b.N 是动态调整的次数,因此测试代码必须写在循环中。
示例代码
测试字符串的拼接功能
package main
import (
"strings"
"testing"
)
func BenchmarkConcatStrings(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = "Hello" + " " + "World"
}
}
func BenchmarkJoinStrings(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = strings.Join([]string{"Hello", "World"}, " ")
}
}
运行基准测试
go test -bench=.
输出:
BenchmarkConcatStrings-8 1000000000 0.3584 ns/op
BenchmarkJoinStrings-8 2000000000 0.5023 ns/op
常用命令
运行基准测试
go test -bench=.
-bench=.: 运行所有基准测试。
指定基准测试函数
go test -bench=BenchmarkFuncName
输出更多详细信息
go test -bench=. -benchmem
-benchmem:输出内存分配统计信息,包括每次操作的分配次数和字节数。
优化基准测试
避免测试干扰
- 消除IO操作:基准测试中尽量避免网络或文件操作,因为这些操作会导致测试结果不稳定
- 避免打印操作:fmt.Println等打印操作会增加基准测试的时间
控制内存分配
可以通过-benchmem查看内存分配情况,从而优化代码
基准测试结果解读
BenchmarkConcatStrings-8 1000000000 0.3584 ns/op
BenchmarkJoinStrings-8 2000000000 0.5023 ns/op
字段解释
- BenchmarkConcatStrings-8: 基准测试的名字和运行的逻辑 CPU 数(如 8)。
- 1000000000: 基准测试的循环次数(b.N 的值)。
- 0.3584 ns/op: 每次操作的平均耗时(纳秒)。