Go语言基础之测试篇

117 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天

Go语言基础——单元测试

一、什么是单元测试

单元测试是指对软件中的最小可测单元进行检查和验证,单元就是人为规定的最小的被测功能模块。在C语言中,一个单元指的是一个函数,在C++中一个单元指的可以是函数也可以是一个类,单元具体是什么,要根据实际情况去具体定义

image-20230122120929283

二、Go语言中的单元测试

go语言自带一个测试框架testing和go test命令来实现单元测试。

单元测试的优点:

  1. 可以确保项目中的每个函数是可以运行的,且运行结果符合预期
  2. 确保写出来的代码的性能是没有问题的
  3. 能即时发现该单元中的程序设计的逻辑错误

如何使用单元测试

1.项目中的包结构

image-20230122115509750

  1. 确保测试的单元和测试的代码在同一包下
  2. 测试文件的命名必须以“_test.go”来结尾
  3. 源代码的包为源代码和测试代码共同在的包,二测试代码的包为main

2.测试代码的编写

  1. 一个测试文件中可包含多个测试函数
  2. 测试函数必须以Test开头,后面为测试的函数的名字
  3. 测试函数的形参为t *testing.T

test_test.go的代码

package main
​
import (
    "testing"
)
​
func TestHelloTom(t *testing.T) {
    output := HelloTom()
    expectOutput := "Tom"
    if output != expectOutput {
        t.Errorf("Expected %s do not match actual %s", expectOutput, output)
​
    }
​
    //t.Logf("Expected %s  match actual %s", expectOutput, output)
}
​

test.go中的代码

package main
​
func HelloTom() string {
    return "Jerry"
}

3.如何跑测试代码

运行测试用例指令
   go test      //如果运行正确,无日志,错误时输出日志
   go test -v   //运行正确或错误都输出日志

如果用的goland也可以直接右键运行

image-20230122121957627

上述例子的输出结果:

image-20230122120624798

我们可以很清晰的看到,我们预期的结果和我们的代码跑出来的结果是不同的,也可以很好的去定位到代码。

我们将test.go中的jerrry改为Tom

image-20230122121209228

此时fail变为了pass,代码是否运行成功是不是一模了然呢?

go的测试代码没有main函数也可以运行,是不是很方便呢

tesing包详解

tesing包中的结构

  1. testing.T:普通测试用例

  2. testing.B:基准测试,对函数运行时间进行统计,也可以称为压力测试

    测试函数以Benchmark开头,后面跟上测试的函数名

    image-20230122124145190

    100000000:迭代次数

    ns/op:平均每次迭代消耗时间

    B/op:平均每次迭代消耗内存

    allocs/op:平均每次迭代内存分配次数

    func BenchmarkHelloTom(b *testing.B) {
        //打开内存
        b.ReportAllocs()
    ​
        for i := 0; i < b.N; i++ {
            HelloTom()
        }
    }
    
  3. testing.F:模糊测试,可以自动生成测试用例

  4. testing.M:main函数测试

    func TestMain(m *testing.M) {
        //测试之前,数据装载,配置初始化等前置工作
        code := m.Run()
        //测试之后,释放资源等收尾工作
        os.Exit(code)
    }
    
  5. testing.PB:可以进行并发测试

    func BenchmarkHelloTom2(b *testing.B) {
        b.RunParallel(func(pb *testing.PB) {
            for pb.Next() {
                HelloTom()
            }
        })
    }