Golang测试

Posted by Laiaike on 2024-04-23

Golang测试

testing 为 Go 语言 package 提供自动化测试的支持。通过 go test 命令,能够自动执行如下形式的任何函数:

1
func TestXxx(t *testing.T)

测试文件名以_test结尾。

测试类型

1
2
3
4
5
TestXxxx(t *testing.T)    // 基本测试
BenchmarkXxxx(b *testing.B) // 压力测试,N的大小为程序自行判断
BenchmarkXxxx(b *testing.PB) // Parallel benchmarks并行测试
TestMain(m *testing.M) // 测试Main函数
TestXxxx(f *testing.F) // fuzz模糊测试

模糊测试

1
func FuzzXxxx(f *testing.F) 
  1. 首次运行go test,只会使用种子语料库,而不会生成随机测试数据。通过这种方式可以用来验证种子语料库的测试数据是否可以测试通过。(fuzz test without fuzzing)
  2. 运行go test -fuzz=Fuzz,会基于种子语料库生成随机测试数据用于模糊测试。(fuzz test with fuzzing)
  3. 如果test失败,testdata/fuzz/FuzzXxxx目录下会存储引起Fuzzing测试失败的测试数据。
  4. 再次运行go test,会自动运行testdata/fuzz/FuzzXxxx目录下的测试数据。

注意go test默认会执行所有以TestXxx开头的单元测试函数和以FuzzXxx开头的模糊测试函数,默认不运行以BenchmarkXxx开头的性能测试函数,如果我们想运行 benchmark用例,则需要加上 -bench 参数。

如果_test.go文件里有其它单元测试函数或者模糊测试函数,但是只想运行FuzzXxxx模糊测试函数,我们可以执行go test -run=FuzzXxxx命令。

Golang单测

面向对象

不要每次new client,复用,后续使用时只需调用c.courseClient

1
2
3
4
5
6
7
8
9
type courseServiceImpl struct{
courseClient client.CourseClient
}

func NewCourseService(courseClient client.CourseClient) courseService {
return &courseServiceImpl{
courseClient : courseClient,
}
}

写单测,希望规避掉与外界发http请求的步骤。

不使用courseClientImpl(有三方请求调用),使用mockCourseClient:打桩,规避调用第三方系统的逻辑,直接使用正确的调用(预期)结果。

在软件开发中,打桩(Stubbing)通常是指在测试过程中替换掉某些组件的行为,以模拟或者控制测试环境。在编程中,可以通过编写桩代码或者使用桩框架来实现打桩。

总结:

  1. 不要每次new,而是复用
  2. 分层,非平铺直叙

interface的正确用法

场景:interface有50个方法,但是只需要使用到其中一个方法;但是需要实现所有方法才算实现了这个interface。可能出现一些误用。

https://go.dev/wiki/CodeReviewComments#interfaces

interface应由使用方实现,而不是由提供方实现(只有使用方有mock的诉求)。

单测打桩工具

go mock
1
go:generate mockgen -source=interface.go -destination=./mock/mock_human.go -package=mock
1
2
3
mockHuman.EXPECT().Speak().DoAndReturn(func() string {
// mock speak的方法
})

调用次数和预设不同就会报错。

go monkey