Go语言3小时光速入门06——测试

go test工具

go test 命令是Go语言的测试驱动程序。

规定:在一个包目录中以_test.go结尾的文件不是go build命令的编译目标,而是go test命令的目标(也就是我们在第一章讲的)

在*_test.go文件中,三种函数需要特殊对待:

  1. 功能测试函数

功能测试函数以Test作为前缀进行命名,用来测试程序的一些逻辑功能的正确性,go test运行测试函数并报告pass还是fail。

  1. 基准测试函数

基准测试函数以Benchmark作为前缀进行命名,用来测试某些操作的性能,go test报告平均运行时间

  1. 示例函数

示例函数以Example作为前缀进行命名,用来提供机器检测过的文档

go test工具扫描*_test.go文件来寻找对应的函数,并在内部自行创建一个临时main包来调用它们,然后编译和运行,并汇报结果,最后清空临时文件。

通过go test选项-v可以输出包中每个测试用例的名称和执行时间。,-run选项参数是一个正则表达式,它可以使得go test只运行那些测试函数名匹配的给定模式的函数。

Test函数

这个前面的章节应该都已经用过了。每一个测试文件必须导入testing包。
Test函数声明格式:

func TestName(t *testing.T){
//...
}

功能测试函数必须以Test开头,可选的后缀名称必须以首字母大写开头,如:

func TestConnect(t *testing.T){//...}
func TestAdd(t *testing.T){//...}
func TestDestroy(t *testing.T){//...}

其中参数t提供了汇报测试失败和日志记录的功能(参数类型testing.T表明这个是用于Test函数的)。

基本功能测试

这个我们在之前用到很多了。这里就不多讲了。创建一个Test函数在里面调用要测试的功能函数传入需要的值然后去调用或者直接在Test函数里面执行功能逻辑即可。

随机测试:

在测试时我们很多时候需要生成随机的测试数据。(其实这里就是顺手讲下随机数生成)

func RandomCreate(){
	//用当前时间戳作为种子
	seed := time.Now().UTC().UnixNano()
	randCreator := rand.New(rand.NewSource(seed))
	for i:=0;i<100;i++{
		//生成随机
		fmt.Println(randCreator.Intn(5))
		fmt.Println(randCreator.Float64())
	}
}

*测试命令:

go test工具对测试库代码包很有用,但是也可以将它用于测试命令。包名main一般会产生可执行文件,但也可以当做库来导入...(也就是说,测试代码可以和产品代码在一个包里面,哪怕包名叫做main,并且里面有一个main函数,但是在测试过程中这个包当做库来测试,main函数被直接忽略)事实上我们还可以返回一个包级别变量修改函数变量来进行白盒测试(比如我们测试xxx操作后发短信,但是我们并不想短信真的发出去)


在测试过程中我们可以通过参数t中提供几个函数用于测试的控制,如:

t.Fail()和t.Error(): 该测试失败,该测试继续,其他测试继续执行
t.FailNow()和t.Fatal(): 该测试失败,该测试中止,其他测试继续执行

func TestError(t *testing.T){
	fmt.Println("开始测试")
	t.Error()
	fmt.Println("测试完成")
}

func TestFatal(t *testing.T){
	fmt.Println("开始测试")
	t.Fatal()
	//上面已经终止了这个不会打印
	fmt.Println("测试完成")
}

另外除了内置的Go单元测试控制外也可以下载Testify使用断言

覆盖率:

Dijkstra(对,就是最短路径算法那个Dijkstra)曾说"测试旨在发现bug,而不是证明其不存在"。无论有多少测试都无法证明一个包绝对没有bug。在最好的情况下,它们增强了我们的信心,证明这些包是可以在很多重要场景下使用的。

一个测试套件覆盖待测试包的比例被称为测试覆盖率。

语句覆盖率(部分语句在一次测试中至少执行一次)是覆盖率测试中一种最简单并且用得最多的方法。在go语言中内置了语句覆盖率工具,我们可以给go test加上-cover来输出代码测试覆盖率.

另外Go还提供了一个额外-coverprofile参数,用来将覆盖率相关的记录信息输出到一个文件。go test -cover -coverprofile=c.out

Benchmark函数

基准测试函数和前面的功能测试函数基本相同,区别在于基准测试函数名以Benchmark开头 ,参数t,类型为testing.B。

基准测试必须要执行参赛b.N次,这样的测试才有对照性,b.N的值是系统根据实际情况去调整的,从而保证测试的稳定性。

Benchmark函数一般格式如:

func BenchmarkTest(b *testing.B) {
	//这里可以写一些与性能无关不关心的代码,比如初始化之类的
	//.....

	//表明基准测试开始
	b.ResetTimer()
	
	//要测试的代码.....
	
	//表明基准测试结束
	b.StopTimer()
	//与性能测试⽆无关的代码
}

通过执行go test -bench命令执行基准测试

性能比较函数

性能比较函数通常是一个带有参数的函数,被多个不同的Benchmark函数传入不同的值来调用。

// Fib 是一个用递归低效计算第n个斐波那契数的函数
func Fib(n int) int  {
    if n <2{
        return n
    }
    return Fib(n-1) + Fib(n+2)
}

//性能比较函数
func benchmarkFib(b *testing.B, n int) {
    for i := 0; i < b.N; i++ {
        Fib(n)
    }
}
func BenchmarkFib1(b *testing.B)  { benchmarkFib(b, 1) }
func BenchmarkFib2(b *testing.B)  { benchmarkFib(b, 2) }
func BenchmarkFib3(b *testing.B)  { benchmarkFib(b, 3) }
func BenchmarkFib10(b *testing.B) { benchmarkFib(b, 10) }
func BenchmarkFib20(b *testing.B) { benchmarkFib(b, 20) }
func BenchmarkFib40(b *testing.B) { benchmarkFib(b, 40) }

默认情况下,每个基准测试至少运行1秒。如果在Benchmark函数返回时没有到1秒,则b.N的值会按1,2,5,10,20,50,…增加,并且函数再次运行。还可以使用-benchtime标志增加最小基准时间,以产生更准确的结果。

并行测试

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

//正常测试
func BenchmarkFunctionSome(b *testing.B) {

    for i := 0; i < b.N; i++ {
       //....
    }
}

//并行测试
func BenchmarkFunctionSome(b *testing.B) {

    b.RunParallel(func(pb *testing.PB) {
        for pb.Next() {
            //...
        }
    })
}

其他常用参数:

  1. -benchmem:性能测试的时候显示测试函数的内存分配的统计信息
  2. -count n:运行测试和性能多少此,默认一次
  3. -run regexp:只运行特定的测试函数
  4. -timeout t:测试时间如果超过t, panic,默认10分钟
    ...

Example函数

示例函数名字以Example开头,函数本身既没有参数也没有结果。

示例函数的目的:

  1. 作为文档,比起长篇乏味的描述,一个代码例子就显得更加简洁直观了。
  2. 通过go test运行如果函数最后包含一个类似于这样// 输出 :;测试程序将执行这个函数并检查输出到终端的内容匹配这个注释中的文本。
  3. 提供示例和模板代码

测试框架

除go内置的测试框架外,也有很多外部测试框架。如:

👉Goconvey

👉Ginkgo

👉Gospec

....

感兴趣的可以自行了解。

更新时间:2020-02-24 18:56:43

本文由 寻非 创作,如果您觉得本文不错,请随意赞赏
采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
原文链接:https://www.zhouning.group/archives/go语言3小时光速入门06测试
最后更新:2020-02-24 18:56:43

评论

Your browser is out of date!

Update your browser to view this website correctly. Update my browser now

×