持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情
1. 单元测试
1.1 单元测试的编写规则
- 所有测试文件以
_test.go结尾 - 函数以
func TestXxx(t *testing.T)命名 - 初始化逻辑放在
func TestMain(m *testing.M)当中
1.2 t *testing.T的方法
1)当我们遇到一个断言错误的时候,标识这个测试失败,会使用到:
t.Fail() : 测试失败,测试继续,也就是之后的代码依然会执行
t.FailNow() : 测试失败,测试中断
在 t.FailNow() 方法实现的内部,是通过调用 runtime.Goexit() 来中断测试的。
2)当我们遇到一个断言错误,只希望跳过这个错误,但是不希望标识测试失败,会使用到:
t.SkipNow() : 跳过测试,测试中断
在 t.SkipNow() 方法实现的内部,是通过调用 runtime.Goexit() 来中断测试的。
3)当我们只希望打印信息,会用到 :
t.Log() : 输出信息
t.Logf() : 输出格式化的信息
注意:默认情况下,单元测试成功时,它们打印的信息不会输出,可以通过加上 -v 选项,输出这些信息。但对于基准测试,它们总是会被输出。
4)当我们希望跳过这个测试,并且打印出信息,会用到:
t.Skip() : 相当于 Log + SkipNow
t.Skipf() : 相当于 Logf + SkipNow
5)当我们希望断言失败的时候,标识测试失败,并打印出必要的信息,但是测试继续,会用到:
t.Error() : 相当于 Log + Fail
t.Errorf() : 相当于 Logf + Fail
6)当我们希望断言失败的时候,标识测试失败,打印出必要的信息,但中断测试,会用到:
t.Fatal() : 相当于 Log + FailNow
t.Fatalf() : 相当于 Logf + FailNow
2. 基准测试
2.1 基准测试介绍
当我们尝试去优化代码的性能时,首先得知道当前的性能怎么样。Go 语言标准库内置的 testing 测试框架提供了基准测试(benchmark)的能力,能让我们很容易地对某一段代码进行性能测试。
- 函数以
func BenchmarkHello(b *testing.B)命名的为基准测试
2.2 t *testing.B的方法
b.N
benchmark 用例的参数 b *testing.B,有个属性 b.N 表示这个用例需要运行的次数。b.N 对于每个用例都是不一样的。
那这个值是如何决定的呢?b.N 从 1 开始,如果该用例能够在 1s 内完成,b.N 的值便会增加,再次执行。b.N 的值大概以 1, 2, 3, 5, 10, 20, 30, 50, 100 这样的序列递增,越到后面,增加得越快。
计时方法
有三个方法用于计时:
b.StartTimer():开始对测试进行计时。该方法会在基准测试开始时自动被调用,我们也可以在调用 StopTimer 之后恢复计时;b.StopTimer():停止对测试进行计时。当你需要执行一些复杂的初始化操作,并且你不想对这些操作进行测量时,就可以使用这个方法来暂时地停止计时;b.ResetTimer():对已经逝去的基准测试时间以及内存分配计数器进行清零。对于正在运行中的计时器,这个方法不会产生任何效果。本节开头有使用示例。
并行执行
通过 b.RunParallel() 方法能够并行地执行给定的基准测试。b.RunParallel()会创建出多个 goroutine,并将 b.N 分配给这些 goroutine 执行,其中 goroutine 数量的默认值为 GOMAXPROCS。
2.3 基准测试结果
对上述结果中的每一项,你是否都清楚是什么意思呢?
2000000:基准测试的迭代总次数 b.N898 ns/op:平均每次迭代所消耗的纳秒数368 B/op:平均每次迭代内存所分配的字节数9 allocs/op:平均每次迭代的内存分配次数
testing 包中的 BenchmarkResult 类型能为你提供帮助,它保存了基准测试的结果,定义如下:
type BenchmarkResult struct {
N int // The number of iterations. 基准测试的迭代总次数,即 b.N
T time.Duration // The total time taken. 基准测试的总耗时
Bytes int64 // Bytes processed in one iteration. 一次迭代处理的字节数,通过 b.SetBytes 设置
MemAllocs uint64 // The total number of memory allocations. 内存分配的总次数
MemBytes uint64 // The total number of bytes allocated. 内存分配的总字节数
}