博客:cbb777.fun
全平台账号: 安妮的心动录
github: https://github.com/anneheartrecord
下文中我说的可能对,也可能不对,鉴于笔者程度无限,请君自辨。有问题欢送大家找我探讨
在 Go 1.18 开始提供了 Fuzzing 能力的反对,testing 包在咱们常见的 T B 类型之外新增了 F 的类型,用于反对含糊测试
Fuzzing Test
日常测试代码的时候咱们常常应用 table driven test 的形式来结构一组输出和预期的后果,之后调用咱们的待测函数,查看后果是否和咱们的预期匹配,也就是咱们平时说的 Mock 数据
这就引出了一个问题,这个 table 要多大呢?
通常大家都只是写一个【失常】的 case 一个【异样】的 case
然而这些样例其实是不够的,比方一些异样值、corner case,可能无奈解决,或者可能有程序挂掉、平安问题等等
而 fuzzing test 的作用就是帮咱们主动生成输出数据,以下是维基百科对于 fuzzing test 的定义
Fuzzing is a technique where you automagically generate input values for your functions to find bugs
含糊测试可能【继续】、【主动】地生成一系列【半随机】的数据作为待测函数的输出,来找到程序里暗藏的 bug,对于边界 case 可能很好的验证。含糊测试中的输出不是由人工指定的,而是主动生成的随机数据,所以能够躲避掉人工主观判断造出来的数据。
含糊测试通常能够不依赖于开发测试人员定义好的数据集,取而代之的则是一组通过数据结构引擎自行结构的一系列随机数据。含糊测试会讲这些数据作为输出提供给待测程序,并且监测程序是否呈现 panic、断言失败、有限循环,或者其余的异常情况
这些通过数据结构引擎生成的数据被称为 语料(corpus),另外含糊测试其实也是一种继续测试的伎俩,因为如果不限度执行的次数或者执行的最大工夫,它就会始终不停的执行上来
Go 含糊测试
让咱们来看看一个 Golang 实现的含糊测试长什么样
签名局部:从常见的func TestXxx(t *testing.T)
变成了func FuzzXxx(f *testing.F)
seed corpus:一组用户提供的语料,fuzzing 引擎会应用这个语料来生成随机数据。其实就是一个样本,之后引擎就晓得要生成什么类型的随机数据了
Fuzzing arguments: 承受 *testing.t 和想要随机生成的数据类型
含糊测试的要求
- 含糊测试必须是一个名称相似于
FuzzXxx
的函数,仅承受一个*testing.F
参数,无返回值 - 含糊测试必须在
*_test.go
中运行 - Fuzz target(含糊指标)必须是对
(*testing.F).Fuzz
的办法调用,参数是一个函数,并且这个函数的第一个参数是*tesing.T
,而后是含糊参数(fuzzing argument),没有返回值 - 一个含糊测试中必须只有一个含糊指标
- 所有种子语料库(seed corpus)必须具备与含糊参数雷同的类型,程序雷同
-
含糊参数只能是以下的类型
string, []byte int, int8, int16, int32/rune, int64 uint, uint8/byte, uint16, uint32, uint64 float32, float64 bool
须要留神的一点是,在 Go 执行的过程中,多个 fuzzing target 是并行来解决的,底层会有多个 worker,调度的程序也不肯定,所以不能做长久化,也不能依赖一些全局状态,不要尝试扭转入参
运行含糊测试
咱们仍然能够应用 go test
命令来跑含糊测试,只是须要加上一个 -fuzz=FuzzTestName
的选项。同时这个包下所有其余类型的 test 都会优先于含糊测试执行,毕竟比拟消耗资源,随机数据生成是有样本的。
执行后果如下
~ go test -fuzz FuzzFoo
fuzz: elapsed: 0s, gathering baseline coverage: 0/192 completed
fuzz: elapsed: 0s, gathering baseline coverage: 192/192 completed, now fuzzing with 8 workers
fuzz: elapsed: 3s, execs: 325017 (108336/sec), new interesting: 11 (total: 202)
fuzz: elapsed: 6s, execs: 680218 (118402/sec), new interesting: 12 (total: 203)
fuzz: elapsed: 9s, execs: 1039901 (119895/sec), new interesting: 19 (total: 210)
fuzz: elapsed: 12s, execs: 1386684 (115594/sec), new interesting: 21 (total: 212)
PASS
ok foo 12.692s
Fuzzing test 的局限性,在单元测试中因为测试输出是固定的,所以能够和把失去的后果和预期后果进行比拟来判断执行后果是否与预期相符合。
然而在应用 fuzzing 的时候,咱们无奈预测输入后果是什么,因为测试的输出除了咱们代码只能给指定的用例之外,还有 fuzzing 随机生成的输出,所以咱们无奈提前晓得预期后果是什么
本文由 mdnice 多平台公布