Go编写测试经验总结| 青训营笔记

183 阅读3分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的第1篇笔记。

在青训营项目提交后进行总结回顾,这次青训营最大的收获之一就是多人合作如何确保项目质量。除了直接阅读其他人提交的代码之外,最简单的方式就是编写测试,每次git仓库变动时通过运行测试确保原有和新增代码的正确性。

Go自带的testing模块可用于编写测试,常用的包括testing.M, testing.T, testing.B三个部分。

编写测试的流程如下

  1. 测试前、测试后准备 在web项目中通常需要设置路由、连接数据库、配置日志等功能,测试环境进行这类设置有两种方法。 一种实现的方式为直接启动项目,在测试中通过封装http请求进行测试。这种方式比较简单,但是测试程序不能探测到后端服务函数调用的过程,因此无法直接debug、计算测试代码覆盖率、竞态检测。 另一种方式是直接调用路由函数,可参考 测试 | Gin Web Framework (gin-gonic.com)。这需要在测试程序中初始化服务器,这部分代码可以写在名为 TestMain(m *testing.M) 的函数中,进行初始化后调用 m.run() 执行测试,然后进行后处理。

2.单元测试 单元测试命名方式为 TestXXX(t *testing.T),在测试中可以使用 assert.Equal(t, v1, v2)assert.NotEqual(t, v1, v2)简单的判断err、http状态码等参数。也可以进行复杂的逻辑判断,并用 t.Errorf("") 输出日志并标记该测试失败, t.Fatalf("")输出日志、标记该测试失败并立即停止执行。

3.Benchmark测试 Benchmark测试函数命名方式为 BenchmarkXxx(b *testing.B), 有串行测试和并行测试两种方式。 串行测试的典型方式为:

func BenchmarkFoo(b *testing.B) {
    for i:=0; i<b.N; i++ {
        dosomething()
    }
}

如果测试前需要初始化:

func BenchmarkFoo(b *testing.B) {
    init()
    b.ResetTimer()
    for i:=0; i<b.N; i++ {
        dosomething()
    }
}

并行测试:

func BenchmarkFoo(b *testing.B) {
    // b.SetParallelism(10)
    b.RunParallel(func(pb *testing.PB) {
        for pb.Next() {
            dosomething()
        }
    })
}

并行测试通过go协程并发执行,默认情况下同时执行的 go routine 数为cpu数,可以通过b.SetParallelism设置每个cpu上执行的go routine数量来达到增加并发数的目的。

4.执行测试 除了在IDE中通过图形化界面调用测试外,还可以使用go test命令在命令行中执行测试。 相关参数: -v : 显示详细的执行过程,有时候执行结果被缓存,显示cache时也可以通过该参数强制重新执行。 -bench : 默认只执行单元测试 TestXXX,通过该参数指定执行BenchmarkXXX测试。 -benchmem :测试结果显示内存使用情况 -c:计算代码覆盖率,默认只会计算同一个包内?文件?的代码 -coverpkg=? : 指定计算代码覆盖率的路径,如 -coverpkg=./...代表计算当前目录下所有文件的代码覆盖率。 -coverprofile=? : 输出测试覆盖率文件,可通过go tool cover工具查看具体到行的覆盖率测试情况。 -cpuprofile ? : 使用pprof工具记录测试过程中的cpu调用情况,输出至 ?文件 -memprofile ? : 使用pprof工具记录测试过程中的内存分配情况,输出至 ?文件

pprof、coverpkg在使用http请求测试的方式下无法探测到后端的代码,只会探测到网络调用(不确定)?

除了这些记录以外,还有很多工具没有使用到,日后还需要多加学习!