Fork me on GitHub

版权声明 本站原创文章 由 萌叔 发表
转载请注明 萌叔 | https://vearne.cc

1.引言

Golang1.18 引入了一个模糊测试的功能。文本萌叔将会简单介绍下这个特性。

2.模糊测试

传送门
比如我们编写了一个工具包来做除法

package fuzz

func Div(a, b int) int {
    return a / b
}

由于疏忽忽略了某些边界条件。显然在上面的代码中,b不能等于0,否则会发生运行时错误。

普通的单元测试

func TestDiv(t *testing.T) {
    testcases := []struct {
        a, b, want int
    }{
        {10, 2, 5},
        {5, 3, 1},
        {-6, 3, -2},
        {-6, -3, 2},
    }
    for _, tc := range testcases {
        result := Div(tc.a, tc.b)
        if Div(tc.a, tc.b) != tc.want {
            t.Errorf("Div: %q, want %q", result, tc.want)
        }
    }
}

由于对分支条件和异常情况考虑的不周全,自测的单元测试能够正常通过。但是一旦b=0,程序将会崩溃。

模糊测试 fuzz test

我们可以编写一个模糊测试的用例

func FuzzXxx(f *testing.F) { ... }

func FuzzDiv(f *testing.F) {
    testcases := []struct {
        a, b int
    }{
        {10, 2},
        {5, 3},
        {-6, 3},
        {-6, -3},
    }
    for _, tc := range testcases {
        /*
         测试组件根据我们提供的参数,反射获得参数类型
         并试图穷举可能的取值
        */
        f.Add(tc.a, tc.b) // Use f.Add to provide a seed corpus
    }
    f.Fuzz(func(t *testing.T, a, b int) {
        q := Div(a, b)
        if q != a/b {
            t.Errorf("Before: %q, after: %q", q, a/b)
        }
    })
}

执行模糊测试

go test -fuzz=Fuzz

执行的过程中,会在当前目录下生成一个testdata目录

(py3_env) fuzz [master●●●] % tree .
.
├── fuzz.go
├── fuzz_test.go
└── testdata
    └── fuzz
        └── FuzzDiv
            └── 378303d09d9499e4e6c708a92079f30db6f554529fd9eb86ac9a9639481fb23d


上图标红的位置,提示我们是哪条测试用例没有通过

(py3_env) fuzz [master●●●] % cat testdata/fuzz/FuzzDiv/378303d09d9499e4e6c708a92079f30db6f554529fd9eb86ac9a9639481fb23d
go test fuzz v1
int(-6)
int(0)

执行Div(-6, 0)时,出现了panic

还可以使用-fuzztime来控制模糊测试最大执行时间

go test -fuzz=Fuzz -fuzztime 30s

3. 参考资料

1.Tutorial: Getting started with fuzzing


微信公众号

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据