golang 测试
1. testify assert
这里我们用到了一个很受欢迎的第三方库 testify
它不仅解决了 golang 没有断言的问题,还提供了许多模拟数据的功能
- 标准库
"testing" "github.com/stretchr/testify/assert"
func TestDemo(t *testing.T) {
assert.Nil(t, nil)
assert.NotNil(t, struct{}{})
assert.Equal(t, 5, 5)
assert.NotEqual(t, 5, 6)
}
执行 go test <filename> -v -v 参数是查看详细结果
2.testify Mock
Mock : 一些测试需要调用第三方服务,但是因为各种原因(接口还没写好,耗时操作等等)。我们需要本地模拟第三方接口进行测试。
Mock 需要实现被模拟类的所有方法
type EmailServiceMock struct {
mock.Mock
}
func (this *EmailServiceMock) Send(msg string) error {
args := this.Called(msg)
return args.Error(0)
}
func TestSend(t *testing.T) {
service := new(EmailServiceMock)
// 设定模拟数据
service.On("Send", "Hello World").Return(nil)
result := service.Send("Hello World")
assert.Nil(t, result)
}
3.Benchmark 测试
基准测试(Benchmark)应该注意避免在虚拟机以及云服务器上测试。虚拟机、云服务器上资源动态分配可能会导致测试结果有误。
- Benchmark 测试函数名应该以 Benchmark 开头
- 参数
BenchmarkFoo(b *testing.B) - b.N 是执行的次数
- 编写完毕后用
go test -bench=".*" -benchmem执行- -bench 可以使用正则表达式匹配
- -benchmem 显示内存情况
- -count 表示执行次数
- -benchtime=5s 表示执行时间,默认是 1s
- -cpu=2,4 表示使用 CPU 的核数(观察如下的测试结果: 函数名结尾的数字表示 CPU 核数)
下面看一个列子,观察两种不同方式初始化 slice 对性能的影响。
- 对于 slice
make([]int, 0, 100)表示初始化长度为 0,容量为 100 的 slice - 对于 HashTable
make(map[string]int, 10)表示容量为 10 - 对于 channel
make(chan int, 10)表示容量为 10 - 当超过容量(cap),扩容会带来一定的开销 ==> 观察下面的列子体会不同分配策略带来的影响
package test
import (
"math/rand"
"testing"
"time"
)
func FillingSlice(n int) []int {
rand.Seed(time.Now().UnixNano())
list := make([]int, 0)
for i := 0; i < n; i++ {
list = append(list, rand.Int())
}
return list
}
func FillingSliceWithCap(n int) []int {
rand.Seed(time.Now().UnixNano())
// make ==> type, len, cap
list := make([]int, 0, n)
for i := 0; i < n; i++ {
list = append(list, rand.Int())
}
return list
}
// Benchmark Test
func BenchmarkFillingSlice(b *testing.B) {
for k := 0; k < b.N; k++ {
FillingSlice(10000000)
}
}
func BenchmarkFillingSliceWithCap(b *testing.B) {
for k := 0; k < b.N; k++ {
FillingSliceWithCap(10000000)
}
}
执行 go test -bench=".*" -benchmem -count=6 .
goos: linux
goarch: amd64
pkg: tdmq.learn/test
BenchmarkFillingSlice-2 4 262980589 ns/op 423503132 B/op 50 allocs/op
BenchmarkFillingSlice-2 4 254879772 ns/op 423503132 B/op 50 allocs/op
BenchmarkFillingSlice-2 4 252118532 ns/op 423503132 B/op 50 allocs/op
BenchmarkFillingSlice-2 4 257549132 ns/op 423503110 B/op 50 allocs/op
BenchmarkFillingSlice-2 4 261797872 ns/op 423503104 B/op 50 allocs/op
BenchmarkFillingSlice-2 4 255670030 ns/op 423503106 B/op 50 allocs/op
BenchmarkFillingSliceWithCap-2 7 153076230 ns/op 80003072 B/op 1 allocs/op
BenchmarkFillingSliceWithCap-2 7 153764944 ns/op 80003072 B/op 1 allocs/op
BenchmarkFillingSliceWithCap-2 7 155534140 ns/op 80003072 B/op 1 allocs/op
BenchmarkFillingSliceWithCap-2 7 154345444 ns/op 80003072 B/op 1 allocs/op
BenchmarkFillingSliceWithCap-2 7 152601362 ns/op 80003072 B/op 1 allocs/op
BenchmarkFillingSliceWithCap-2 7 154338301 ns/op 80003072 B/op 1 allocs/op
4. testify 屏蔽耗时操作
耗时操作可能会干扰测试结果(比如网络波动等)
在做基准测试的时候,需要去屏蔽掉一些可能带来干扰的接口的时间
b.ResetTimeer重置计时器b.StopTimer()停止计时,b.StartTimer开始计时
func BenchmarkResetDemo(b *testing.B) {
// 发生耗时操作 !!!
fmt.Println("func Run....")
// 屏蔽耗时操作
b.ResetTimer()
for i := 0; i < b.N; i++ {
// 测试函数
Foo()
}
}
func BenchmarkDemo(b *testing.B) {
b.StopTimer()
// 发生耗时操作 !!!
fmt.Println("func Run....")
b.StartTimer()
for i := 0; i < b.N; i++ {
// 测试函数
Foo()
}
}
浙公网安备 33010602011771号