测试与基准测试的区别
本章我们将要讨论的最后一个概念是基准测试。testing
包提供了对基准测试的支持,通过 testing.B
类型进行操作。基准测试的签名与测试非常相似:
func BenchmarkName(b *testing.B) {
// implementation
}
这个签名突出了 Go 基准测试的一些要求:
-
基准测试是导出的函数,其名称以
Benchmark
开头。 -
Benchmark
名称可以包含一个额外的后缀,用于指定测试覆盖的内容。后缀也必须以大写字母开头,正如我们在Name
中看到的那样。 -
Benchmarks
必须接收一个*testing.B
类型的参数。正如我们目前所解释的,这是测试与测试运行器交互的方式。你可以随意命名该参数,但 Go 开发者通常使用b
来表示它。 -
Benchmarks
不能有返回类型。
基准测试是一个重要的 Go 性能分析工具
测试验证程序的功能,而基准测试验证代码的性能。在你的测试策略中,应该同时使用这两者。 |
基准测试也可以通过 go test
命令运行,但我们必须指定测试运行器,我们对基准测试感兴趣,使用 –bench
标志。我们必须提供一个正则表达式,匹配我们想要运行的包。我们可以通过以下命令运行当前目录下的所有基准测试:
go test -bench .
testing.B
类型也可以访问记录错误和标记测试失败的方法,正如我们在 testing.T
类型的介绍中看到的那样:b.Error
、b.Errorf
、b.Fatal
和 b.Fatalf
。与测试类似,基准测试也存在于测试文件中,这些文件必须以 _test.go
为后缀,以便 Go 测试运行器能够识别。
让我们在 engine_test.go
文件中为 Add
函数编写一个基准测试:
func BenchmarkAdd(b *testing.B) {
e := calculator.Engine{}
// 运行 Add 函数 b.N 次
for i := 0; i < b.N; i++ {
e.Add(2, 3)
}
}
BenchmarkAdd
示例中,Add
函数会在循环中运行 b.N
次。Go 的测试运行器会控制 N
的值,并会逐渐增加它,直到它认为测量结果已经稳定。
与所有性能测试一样,你应该小心在本地机器上运行基准测试。由于你的计算机正在处理其他任务,基准测试的测量结果可能会有很大差异。
现在,我们运行基准测试,看到如下输出:
$ go test -bench . ./chapter02/calculator -v
pkg: github.com/PacktPublishing/Test-Driven-Developmentin-Go/chapter02/calculator
cpu: Intel(R) Core(TM) i5-8279U CPU @ 2.40GHz
BenchmarkAdd-8 1000000000 0.2684 ns/op
PASS
ok github.com/PacktPublishing/Test-Driven-Developmentin-Go/chapter02/calculator 0.408s
基准测试运行的输出突出了以下内容:
-
基准测试的名称:
BenchmarkAdd
-
用于运行基准测试的 CPU 核心数量,作为测试名称的后缀:
8
-
基准测试执行的次数:
1000000000
-
单次测试迭代的平均时间,以纳秒为单位:
0.2684 ns/op
我们的函数非常简单,因此运行时间非常短。我们将在第 8 章《测试微服务架构》中探索更复杂的基准测试示例。