Golang 性能测试-单元测试

Golang 测试总结

go test的初始化以及退出前的clear — TestMain

程序的初始化工作可以通过init()函数完成,Go的init有以下特点:

  • 先于main函数执行
  • 自动调用
  • 导入其他包时先执行import包的init函数,多次导入时只导入一次
  • 同一个包可以有多个init

测试程序中有时候可能需要完成一些setup 或者 teardown操作, go 1.4 之后加入了TestMain方法帮助我们完成这个任务. 当包含TestMain函数时, go test会执行该函数而不是直接运行测试.

It is sometimes necessary for a test program to do extra setup or teardown before or after testing. It is also sometimes necessary for a test to control which code runs on the main thread. To support these and other cases, if a test file contains a function:

1
func TestMain(m *testing.M)

then the generated test will call TestMain(m) instead of running the tests directly. TestMain runs in the main goroutine and can do whatever setup and teardown is necessary around a call to m.Run. It should then call os.Exit with the result of m.Run. When TestMain is called, flag.Parse has not been run. If TestMain depends on command-line flags, including those of the testing package, it should call flag.Parse explicitly.

A simple implementation of TestMain is:

1
2
3
4
5
6
func TestMain(m *testing.M) {
setup()
code := m.Run()
shutdown()
os.Exit(code)
}

Go Coverage test 覆盖率测试

1
2
PKGS=`go list github.com/xxx/xxx/... | grep -v /vendor`
go test -cover -p 1 -timeout=20m $PKGS
1
2
3
4
5
6
# 测试所有包的覆盖率
go test -cover -timeout=20m -coverpkg=tracing/... tracing/tests # -coverprofile=c.out
# 测试特定包的覆盖率
go test -cover -timeout=20m -coverpkg=tracing/util tracing/tests -coverprofile=c.out
# 查看覆盖率报告
go tool cover -html=c.out -o=tag.html

Golang 性能测试, pprof

golang 测试时保存profiling测试结果到文件:

1
go test -timeout 6000s -memprofile=mem.out -cpuprofile=cpu.out

profile文件分析:

1
2
3
4
go tool pprof -alloc_space xxx.test mem.out
go tool pprof -inuse_space xxx.test mem.out
top
top -cum

内存分析参数:

1
2
3
4
-inuse_space      Display in-use memory size
-inuse_objects Display in-use object counts
-alloc_space Display allocated memory size
-alloc_objects Display allocated object counts

profile分析测试只有在负载比较高的情况下才比较有意义。

Golang Benchmark 并发测试

func (*B) RunParallel

1
func (b *B) RunParallel(body func(*PB))

以并行的方式执行给定的基准测试。 RunParallel 会创建出多个 goroutine , 并将 b.N 个迭代分配给这些 goroutine 执行, 其中 goroutine 数量的默认值为 GOMAXPROCS 。 用户如果想要增加非CPU受限(non-CPU-bound)基准测试的并行性, 那么可以在 RunParallel 之前调用 SetParallelism 。 RunParallel 通常会与 -cpu 标志一同使用。

body 函数将在每个 goroutine 中执行, 这个函数需要设置所有 goroutine 本地的状态, 并迭代直到 pb.Next 返回 false 值为止。 因为 StartTimer 、 StopTimer 和 ResetTimer 这三个函数都带有全局作用, 所以 body 函数不应该调用这些函数; 除此之外, body 函数也不应该调用 Run 函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
func BenchmarkXXX(b *testing.B) {
templ := template.Must(template.New("test").Parse("Hello, {{.}}!"))
// RunParallel will create GOMAXPROCS goroutines
// and distribute work among them.
b.RunParallel(func(pb *testing.PB) {
// Each goroutine has its own bytes.Buffer.
var buf bytes.Buffer
for pb.Next() {
// The loop body is executed b.N times total across all goroutines.
buf.Reset()
templ.Execute(&buf, "World")
}
})
}

Golang 内存逃逸分析

TODO

Golang 内存模型

TODO

Golang 性能测试

Reference

打赏