Golang相关测试框架
在 Go 语言里,最常用的测试框架有:自带的 testing 包、GoConvey 和 testify。
1、Go自带的testing包
testing 包是官方内置的,无需额外安装,也是大多数项目的首选。
(1)单元测试
- 测试文件必须以 _test.go 结尾,例如:calc_test.go
- 测试函数必须以 Test 开头(推荐写成 Test+函数名,更直观)
- 测试函数签名固定:func TestXxx(t *testing.T),不能有返回值
- 测试函数内部用 t.Errorf / t.Fatal 等方法输出错误
- t.Errorf:标记测试失败,但 继续执行后面的测试代码。
- t.Fatal:标记测试失败,并 立即中止当前测试函数。
- # 执行当前目录下所有 *_test.go 文件
- go test -v
- # 只执行指定文件中的测试
- go test -v calc_test.go calc.go
- # 执行指定的测试函数(-count=1 表示禁用缓存,强制重新运行)
- go test -v -run TestAdd calc_test.go calc.go -count=1
复制代码 更详细的参数请参考:Go test命令行参数 (2)性能测试
- 文件命名:和单测一样,文件必须以 _test.go 结尾,这样 go test 才能识别。
- 函数命名:基准测试函数要以 Benchmark 开头,且必须是导出函数,比如 BenchmarkAdd。
- 函数签名:基准测试函数必须接收一个 *testing.B 类型的参数,不能有返回值。
- 重置计时器:b.ResetTimer() 用来清空前面初始化代码的耗时,保证只统计真正的测试部分。
- 循环执行:基准测试里要用 for i := 0; i < b.N; i++ { ... },被测的代码放在循环里。
- b.N 的作用:Go 框架会自动调整 b.N,让测试至少运行 1 秒左右,这样结果更稳定。最终输出的是平均每次运行的耗时(比如 0.25 ns/op 表示每次 0.25 纳秒)。
在calc文件夹的calc_test.go文件中新增BenchmarkAbs和BenchmarkAdd方法。
基准测试的目标就是 尽可能准确地衡量一段代码的性能,包括运行时间、内存分配等。
- 核心思路:同一段代码运行很多次(b.N 次),用「总耗时 ÷ b.N」算出平均每次执行的耗时。
- b.N 的作用:b.N 由 Go 测试框架自动决定,会动态调整,保证测试至少运行 1 秒左右,避免样本太少导致结果不准。
- 运行过程:当执行 go test -bench=. 时,框架会先用很小的 b.N(比如 1、2、5、19)试跑几次,估算耗时,再逐步增大 b.N,直到结果稳定。
- 输出示例:比如报告里写 1000000000 0.25 ns/op,意思是运行了 10 亿次,每次平均耗时 0.25 纳秒。
- # 运行所有基准测试
- go test -bench=.
- # 运行所有基准测试并显示内存分配情况
- go test -bench=. -benchmem
- # 只运行基准测试,不运行单元测试
- go test -run=none -bench=.
- # 指定测试时间
- go test -bench=. -benchtime=3s
- # 指定运行轮数
- go test -bench=. -count=3
- # 组合使用多种参数
- go test -run=none -bench=. -benchmem -benchtime=3s -count=3
复制代码 2、GoConvey
https://github.com/smartystreets/goconvey GoConvey 是一款专门为 Golang 打造的测试框架,它不仅能帮你更方便地组织和运行单元测试,还自带了丰富的断言方法,让测试代码更简洁直观。更酷的是,它还支持 Web 界面:只要在项目里写好测试,用 go test 命令就能照常运行;如果你想要更直观的体验,可以直接运行 goconvey,然后在浏览器里访问 http://localhost:8080,就能看到实时的测试结果展示。 相比起纯粹使用标准库的 testing 包,Convey 让单元测试的书写和阅读都更流畅,尤其适合需要频繁跑测试、调试逻辑的开发过程。
(1)安装依赖:go get github.com/smartystreets/goconvey
(2)demo
3、testify
Testify 是 Go 语言生态里非常常用的一个 断言风格测试框架。它不仅提供了开发者最常用的断言方法(让测试代码更简洁、可读性更强),还额外封装了三个核心功能模块:
- Assertions(断言):内置了丰富的断言方法,避免重复编写样板式判断逻辑。
- Suite(测试套件):支持将一组相关测试组织在一起,方便共享初始化、清理等逻辑。
- Mock(模拟):提供强大的 Mock 能力,方便在单元测试中模拟依赖对象或外部接口。
借助 Testify,我们可以用更接近自然语言的方式编写测试,不仅提高开发效率,也让测试结果更易于理解。
官方文档:https://godoc.org/github.com/stretchr/testify (1)依赖安装:go get -u -v github.com/stretchr/testify
(2)测试用例
① assert包提供了断言工具,在执行时会将case标记为失败,但程序不会退出,而是继续往下执行。- package testify
- import (
- "testing"
- "github.com/stretchr/testify/assert"
- )
- func Test_assert(t *testing.T) {
- a := 2
- b := 3
- // 第一个断言失败(故意写错期望值)
- assert.Equal(t, 6, a+b, "第一个断言:2+3应该等于5,不是6")
- // 程序继续执行下面的断言
- t.Log("这行代码被执行了,说明程序没有中断")
- // 第二个断言通过
- assert.Equal(t, 5, a+b, "第二个断言:2+3应该等于5")
- // 第三个断言也会执行
- assert.True(t, a < b, "第三个断言:2应该小于3")
- t.Log("所有断言都已执行完毕")
- }
复制代码
② require包提供与asser包相同的全局函数,与assert不同的是,require会终止当前测试。- package testify
- import (
- "testing"
- "github.com/stretchr/testify/require"
- )
- func Test_require(t *testing.T) {
- name := "Tom"
- age := 18
- // 这个会失败并停止测试
- require.Equal(t, "dazuo", name, "测试会在这里停止")
- require.Equal(t, 18, age, "测试会在这里停止")
- // 这行不会被执行
- t.Log("这行代码不会被执行")
- }
复制代码
③ mock包提供了一种轻松编写模拟对象的机制,可以在编写测试代码时替代实际对象使用模拟对象。- func Test_mock(t *testing.T) {
- // 创建模拟对象
- mockS := &mockStorage{}
- // 设置对Store方法期望的调用,参数必须匹配;返回该方法调用时的返回值
- mockS.On("Store", "name", "Tom").Return(1, nil).Once()
- result, err := mockS.Store("name", "Tom")
- assert.NoError(t, err)
- assert.Equal(t, 1, result)
- mockS.AssertExpectations(t) // 断言所有预期的调用都发生了
- }
复制代码
若该方法没有被调用:- func Test_mock(t *testing.T) {
- // 创建模拟对象
- mockS := &mockStorage{}
- // 设置对Store方法期望的调用,参数必须匹配;返回该方法调用时的返回值
- mockS.On("Store", "name", "Tom").Return(1, nil).Once()
- mockS.AssertExpectations(t) // 断言所有预期的调用都发生了
- }
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |