golang 单元测试框架实践
一、简介
日常开发中, 测试是不能缺少的,每次手动测试非常费时费力,通过单元测试可以达到一次实现多次利用;
单元测试主要是通过模拟业务中的参数,调用我们的函数,然后获取执行结果,再判断结果是否符合规则;同时还可以对某一个方法进行性能分析
在Go 标准库中有一个叫做 testing
的测试框架, 可以用于单元测试和性能测试. 它是和命令 go test
集成使用的,测试文件是以后缀 _test.go
命名的, 通常和被测试的文件放在同一个包中.
规则:
- 单元测试代码的go文件必须以_test.go结尾,Go语言测试工具只认符合这个规则的文件
- 单元测试的函数名必须以Test开头,是可导出公开的函数。备注:函数名最好是Test+要测试的方法函数名
- 测试函数的签名必须接收一个指向testing.T类型的指针作为参数,并且该测试函数不能返回任何值
二、实验环境
单元测试我们大部分情况下无需增加或修改业务代码,只需增加单元测试代码即可,在这个实验过程中,我们简单编写一个简单的业务代码,用来模拟项目中的业务代码;然后再添加单元测试代码进行测试。
2.1 编写被测试的代码
我们找一个空文件夹,新建一个main.go文件,在文件中将一下代码复制进去并保存
package main
func Sum(count int) int {
count--
return count
}
2.2 编写单元测试代码
接着我们继续在当前文件夹下新建单元测试代码,按照简介中的规则,我们需要新建一个名为main_test.go
的文件,然后在文件中编写测试代码,示例代码如下
package main
import (
"testing"
)
//单元测试
func TestSum(t *testing.T) {
//准备参数
param := 10
//执行函数
ret := Sum(param)
//判断结果是否符合预期
if ret != 9 {
t.Error("Sum result failed")
}
}
//性能测试
func BenchmarkSum(b *testing.B) {
//准备参数
param := 10
//执行函数
for i := 0; i < b.N; i++ {
Sum(param)
}
}
三、单元测试使用
3.1 普通测试
普通测试主要是验证返回的结果是否符合预期,执行的命令如下所示
go test -v main_test.go main.go
命令执行后,返回的结果如下所示
从上图中可以看到,单元测试提示测试通过,说明我们程序符合预期
3.2 性能测试
性能测试主要是通过多次调用程序,总耗时来分析程序的性能,类似于AB压力测试,执行命令如下所示
go test -v -bench="BenchmarkSum$" --run=none main_test.go main.go
命令中的-bench="BenchmarkSum$"
参数代表要窒息哪一个方法,执行结果如下所示
在上图中可以看到程序被调用了1000000000次,平均耗时0.254ns
3.3 性能分析
性能分析主要是查看方法中具体的瓶颈,比如A方法调用了C、B、D多个方法,具体耗时在什么位置,我们可以在上一条性能测试的命令中加入-cpuprofile cpu.out
参数(文章附录有多种分析指标类型)加入到性能测试中的具体信息保存
go test -v -bench="BenchmarkSum$" --run=none -cpuprofile cpu.out main_test.go main.go
通过go 自带工具分析保存的文件
go tool pprof cpu.out
命令执行之后返回信息如下图所示
通过第三方工具视图分析
apt install graphviz && go tool pprof -http=":" cpu.out
命令执行之后,会返回一个localhost域名加随机端口的网址,打开网址之后,能看到如下信息,因为我测试的方法比较简单
四、附录
各参数含义翻译
-blockprofile block.out
将goroutine阻塞配置文件写入指定文件
当所有测试完成时。
按照-c的方式编写测试二进制文件。
-blockprofilerate n
控制细节提供的goroutine阻塞配置文件
调用运行时。SetBlockProfileRate与n。
参见" go doc run . setblockprofilerate "
剖析器的目标是平均每个阻塞事件采样一次
n纳秒的程序花费被阻塞。默认情况下,
如果以及。块配置文件没有设置这个标志,所有的阻塞事件
,相当于-test.blockprofilerate=1。
-coverprofile cover.out
在所有测试通过后,向文件写入覆盖率配置文件。
设置覆盖。
-cpuprofile cpu.out
退出前将CPU配置文件写入指定文件。
按照-c的方式编写测试二进制文件。
-memprofile mem.out
通过所有测试后,将分配配置文件写入该文件。
按照-c的方式编写测试二进制文件。
-memprofilerate n
启用更精确(和昂贵)的内存分配配置文件
设置runtime.MemProfileRate。参见" go doc run . memprofilerate "。
要配置所有内存分配,使用-test.memprofilerate=1。
-mutexprofile mutex.out
将互斥锁争用配置文件写入指定文件
当所有测试完成时。
按照-c的方式编写测试二进制文件。
-mutexprofilefraction n
样本1在n堆栈的踪迹goroutines持有a
争用互斥锁。
作者:汤青松
日期:2020-08-11
- C++继承与派生(原理归纳)
- Linux下如何查看自己的服务器有没有无线网卡
- WAMP配置虚拟主机
- linux开关端口问题
- Python 3.6实现单博主微博文本、图片及热评爬取
- 用Django实现一个可运行的区块链应用
- Python的dict实现原理及与Java的比较探究
- 关于位域如何节省内存(C++)
- mysql的小知识点(关于数据库的导入导出 对于windows)
- Python网络编程中的套接字名和DNS解析
- hdu 4009 Transfer water(最小型树图)
- NumPy二元运算的broadcasting机制
- md5算法原理一窥(其一)
- 实现属于自己的TensorFlow(一) - 计算图与前向传播
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Linux的压缩和解压缩的方法总结
- RTSP/GB28181/HIKSDK/Ehome协议视频融合平台EasyCVR编译C++报参见“XXX”的声明错误
- 详解 Linux 常用目录的作用
- CentOS6环境下搭建路由器的方法
- centos7下NFS使用与配置的步骤
- 基于DOM4J的XML文件解析类
- Win7安装和配置Apache2.4服务器的详细方法
- shiro会话管理示例代码
- Windows Apache2.4 VC9(ApacheHaus)详细安装配置教程
- 在centos 7中安装配置k8s集群的步骤详解
- Centos7.2 编译安装方式搭建 phpMyAdmin
- CentOS 6.5 web服务器apache的安装与基本设置
- Linux本机与服务器文件互传及Linux服务器文件上传下载命令写法
- linux利用read命令获取变量中的值
- 解决Centos7 安装腾达U12无线网卡驱动问题