测试

最下面是单元测试,单元测试对代码进行测试。再而上是集成测试,它对一个服务的接口进行测试。继而是端到端的测试,我也称他为链路测试,它负责从一个链路的入口输入测试用例,验证输出的系统的结果。再上一层是我们最常用的UI测试,就是测试人员在UI界面上根据功能进行点击测试。
单元测试
所有以_test.go为后缀名的源代码文件都是go test测试的一部分,不会被go build编译到最终的可执行文件中,xxx_test.go测试文件代码和被测试的源代码文件xxx.go放在同一个包内,一一对应。
比如项目下有某个包内有个源代码文件xxx.go有这么一个函数:
那么单元测试的文件xxx_test.go就放在相同的包内,测试函数的名字必须以Test开头,可选的后缀名必须以大写字母开头,需要一个*testing.T类型的参数,可以像下面这样按组测试,又称表格测试法:
执行测试程序
在项目根目录下直接执行go test .含义是:仅从当前目录下查找以_test.go为后缀的以Test开头的单元测试函数。
go test ./...含义是:找出当前的目录以及所有子目录(包括多级子目录)下所有的 xxx_test.go 测试代码。
go test ./xxx/xxx含义是:找出./xxx/xxx路径下的 xxx_test.go 测试代码,如果想执行指定目录以及其子目录的单元测试,需要指定目录为:./xxx/xxx/...,即在路径后加上/...,注意是 3 个.。
默认不执行基准测试,加上-bench参数来执行,如:go test -bench=.。
测试项目某个模块下的指定单元测试和指定的基准测试,如:go test -v service/*.go -bench BenchMethodName -benchmem -run TestMethodName
MethodName可以写正则表达式匹配,比如如果只想执行benchmark,可以把-run参数写成none或者^$,不存在正则匹配的单元测试也就只会执行基准测试了。
基准测试
基准测试就是在一定的工作负载之下检测程序性能的一种方法。基准测试函数以Benchmark为前缀,需要一个*testing.B类型的参数。
可以为基准测试添加-benchmem参数,来获得内存分配的统计数据:
BenchmarkSubstr-8中数字8表示GOMAXPROCS的值,即并发的线程数(并发的协程比该值大)数字
231的含义:是本次Benchmark循环体共执行的次数5152279 ns/op:本次Benchmark循环体每循环一次耗费5152279纳秒655590 B/op:本次Benchmark循环体每循环一次分配了655590字节2 allocs/op:本次Benchmark循环体每循环一次进行了2次内存分配
-benchtime=3s为基准测试限定执行时间。
benchstat
如果没有benchstat就先安装:go get golang.org/x/perf/cmd/benchstat
集成测试
集成测试和单元测试不一样,它不属于某个文件,集成测试可能涉及到多个文件中多个接口的测试,所以它需要放在一个单独的文件夹,完整项目。
suite和上面的assert在同一个包下:github.com/stretchr/testify
假设有如下2个函数需要编写单元测试:
单元测试文件代码如下:
SetupSuite()、TearDownSuite() 仅执行一次,典型使用场景是各个单元测试共用的数据库连接
而 SetupTest()、BeforeTest()、AfterTest()、TearDownTest()对套件中的每个测试都会执行一次
测试覆盖率
取得
coverprofile:go test -v -coverprofile=coverage.out查看:
go tool cover -html=coverage.out
编译到服务器上执行单元测试
编译: CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go test -c *.go -o testxxx
连上服务器后执行单元测试: ./testxxx -test.run TestXxx_Xxx
gomock
gomock是对interface方法功能的模拟。
通常有的功能的单元测试不好写,比如依赖了第三方服务提供的接口,但它还没实现好,此时单元测试的编写就需要mock第三方服务接口的调用。
通过mock还可以模拟异常场景。
安装
go install github.com/golang/mock/[email protected]
使用
新建person/male.go,写入如下内容:
新建user/user.go,写入以下内容:
生成mock代码: mockgen -source=./person/male.go -destination=./mock/male_mock.go -package=mock
新建user/user_test.go,写入如下内容:
文件目录:
gomonkey
上一节介绍的gomock是需要在设计了interface的前提下的mock,但如果没有设计interface,要怎么mock呢?此时就需要用到gomonkey了。
gomonkey的实现原理是通过reflect包实现,在运行时替换指定变量、指定函数。
注:gomonkey不是线程安全的,所以不要把它用到并发的单元测试中。
安装
go get github.com/agiledragon/gomonkey/[email protected]
在Mac下直接使用gomonkey会有如下这样的错误抛出:
注意:使用gomonkey在执行单元测试时需要禁用内联go test -gcflags=all=-l,否则mock不会成功。
典型用法
// 把gomonkey.ApplyMethod的例子写上
Last updated
Was this helpful?