Golang压力测试
2021-08-03 本文已影响0人
TZX_0710
Go Test工具
Go语言中的测试依赖go test命令。编写测试代码和编写普通的Go代码过程是类似的,并不需要学习新的语法、规则或工具。
go test 命令是一个按照一定约定和组织的测试代码的驱动程序。在包目录内,所有以_test.go为后缀名的源代码都是go test测试的一部分。不会被go build编译到最终可执行文件中。
在*_test.go文件中有三种类型函数。单元测试,基准测试和示例函数
类型 格式 作用 单元测试函数 函数名前缀为Test 测试程序的一些逻辑行为是否正确 基准测试 函数名前缀为Benchmark 测试函数的性能 示例函数 函数名前缀为Example 为文档以提供示例文档 go test 命令会遍历所有的*_test.go文件中符合上述命名规则的函数,然后生成一个临时的main包用于调用相应的测试函数,然后构建并运行、报告测试结果,最后清理测试中生成的文件。
Golang单元测试对文件名和方法名,参数都有很严格的要求
1.文件名必须以xx_test.go命名 2.方法必须是Test[^a-z]开头 3.方法参数必须是t *testing.T 4.使用 go test执行单元测试
go的参数解析:
usage: go test [build/test flags] [packages] [build/test flags & test binary flags] //-c:编译go test称为可执行的二进制文件,但是不运行测试 //-i:安装测试包依赖的package ,但是不运行测试 //build flags 编译运行过程中需要使用到的参数,一般设置为空 //packages 关于包的管理一般设置为空 //flags for test binary 关于go test过程中经常使用到的参数。
参数 作用 -test.v 是否输出全部的单元测试用例(不管成功或者失败),默认没有加上,所以只输出失败的单元测试用例。 -test.bench patten 只跑哪些性能测试用例 -test.benchmem 是否在性能测试的时候输出内存情况 -test.benchtime t :性能测试运行的时间默认是s -test.cpuprofile cpu.out 是否输出cpu性能分析文件 -test.memprofile mem.out 是否输出内存性能分析文件 -test.blockprofile block.out 是否输出内部goroutine阻塞的性能分析文件 -test.memprofilerate n 内存性能分析的时候有一个分配了多少的时候才打点记录的问题。 -test.blockprofilerate n 基本同上,控制的是 -test.parallel n 性能测试的程序并行cpu数,默认等于GOMAXPROCS -test.timeout t 如果 -test.cpu 1,2,4 程序运行在哪些CPU上面,使用二进制的1所在位代表,和nginx的nginx_worker_cpu_affinity是一个道理 -test.short 将那些运行时间较长的测试用例运行时间缩短
测试函数
测试函数必须导入testing包,测试函数的基本格式如下
//打印名字 func ShowName() (str string) { str = "张三" return } //测试函数 import ( "testing" ) func Test func TestShowName(t *testing.T) { }
基准测试
基准测试的参数为testing.B 如下只介绍基础 的基准测试和参数使用
//基准测试函数 引入的参数是testing.B //基准测试函数 func BenchmarkShowName(b *testing.B) { for i := 0; i < b.N; i++ { strings.Split("1,2,3,4",",") } } //测试指令BenchmarkShowName-12 9657868 124.2 ns/o //BenchmarkShowName-12表示对Split函数进行基准测试,数字12表示GOMAXPROCS的值, //1000000000 和124.2 ns/op 表示每次调用ShowName函数好使124.2ns这个结果是基于10000000次调用的平均值 //我们还可以基准测试添加-benchmem参数获取内存分配的统计数据 go test -bench=ShowName -benchmem BenchmarkShowName-12 9324096 123.2 ns/op 64 B/op 1 allocs/op //64B/op表示每次操作内存分配了64字节。 1allocs/op表示分配了1次内存。
示例函数
示例函数的作用是为文档以提供示例文档
func ExampleName(){ /// } //编写示例代码的好处 //1.示例函数能够作为文档直接使用,例如基于文本的godoc中能把示例函数与对应的函数或包相关联 //示例函数只要包含了//Output:也是可以通过 go test运行的可执行测试。
示例函数的作用
压力测试
Go语言自带有一个轻量级的测试框架testing和自带的go test命令来实现单元测试和性能测试,testing框架和其他语言中的测试框架类似,你可以基于这个框架写针对相应函数的测试用例,也可以基于该框架写相应的压力测试用例。
编写测试用例
- 创建**_test.go文件
- 引入testing包
- 所有的测试用例函数必须是Test开头
- 测试用例会按照源代码中写的顺序依次执行
- 测试函数TestXxx()的参数是testing.T,我们可以使用该类型来记录错误或者是测试状态
- 测试格式:func TestXxx(t *testing.T),Xxx部分可以为任意的字母数字组合,但是首字母不能小写,例如Testsay就是错误的函数名
- 函数中通过用esting.T的Error, Errorf, FailNow, Fatal, FatalIf方法,说明测试不通过,调用Log方法用来记录测试的信息。
package gotest //打印名字 func ShowName() (str string) { str = "张三" return } //test包 package gotest import ( "fmt" "testing" ) func Test_ShowName_1(t *testing.T) { name := ShowName() if name == "张三" { fmt.Println("Right") } else { fmt.Println("Error") } } //result E:\code\goproject\src\gotest>go test Right PASS ok gotest 0.079s
如何编写压力测试
压力测试用例必须遵循如下格式,其中XXX可以是任意字母数字的组合,但是首字母不能是小写字母
func BenchmarkXXX(b *testing.B) { ... } go test不会默认执行压力测试的函数,如果要执行压力测试需要带上参数-test.bench,语法:-test.bench="test_name_regex",例如go test -test.bench=".*"表示测试全部的压力测试函数
package gotest import ( "testing" ) func Benchmark_Division(b *testing.B) { for i := 0; i < b.N; i++ { //use b.N for looping Division(4, 5) } } func Benchmark_TimeConsumingFunction(b *testing.B) { b.StopTimer() //调用该函数停止压力测试的时间计数 //做一些初始化的工作,例如读取文件数据,数据库连接之类的, //这样这些时间不影响我们测试函数本身的性能 b.StartTimer() //重新开始时间 for i := 0; i < b.N; i++ { Division(4, 5) } }
执行命令
go test webbench_test.go -test.bench=".*"
,可以看到如下结果:Benchmark_Division-4 500000000 7.76 ns/op 456 B/op 14 allocs/op Benchmark_TimeConsumingFunction-4 500000000 7.80 ns/op 224 B/op 4 allocs/op PASS ok gotest 9.364s