• 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
    

    命令执行后,返回的结果如下所示
    image

    从上图中可以看到,单元测试提示测试通过,说明我们程序符合预期

    3.2 性能测试

    性能测试主要是通过多次调用程序,总耗时来分析程序的性能,类似于AB压力测试,执行命令如下所示

    go test -v -bench="BenchmarkSum$"  --run=none main_test.go  main.go
    

    命令中的-bench="BenchmarkSum$"参数代表要窒息哪一个方法,执行结果如下所示
    image

    在上图中可以看到程序被调用了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
    

    image
    通过go 自带工具分析保存的文件

    go tool pprof cpu.out
    

    命令执行之后返回信息如下图所示
    image

    通过第三方工具视图分析

    apt install graphviz  && go tool pprof -http=":" cpu.out
    

    命令执行之后,会返回一个localhost域名加随机端口的网址,打开网址之后,能看到如下信息,因为我测试的方法比较简单

    image

    四、附录

    各参数含义翻译

    -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

  • 相关阅读:
    组合模式
    过滤器模式
    桥接模式
    适配器模式
    原型模式
    建造者模式
    抽象工厂
    工厂方法
    静态工厂
    单例模式
  • 原文地址:https://www.cnblogs.com/tangqingsong/p/13580150.html
Copyright © 2020-2023  润新知