go test - 模糊测试
ddatsh
go fuzzing
通过持续给程序不同的输入来自动化测试,并通过分析代码覆盖率来智能的寻找失败的 case。这种方法可以尽可能的寻找到一些边缘 case,发现平时很难发现的问题
1.18 整合进标准库
模糊测试会监测程序运行过程中是否出现 panic、断言失败、无限循环等异常情况
// div.go
func Div(a, b int) int {
return a / b
}
go test -fuzz .
// div_test.go
import "testing"
func FuzzDiv(f *testing.F) {
f.Fuzz(func(t *testing.T, a, b int) {
Div(a, b)
})
}
fuzz: elapsed: 0s, gathering baseline coverage: 0/1 completed
fuzz: elapsed: 0s, gathering baseline coverage: 1/1 completed, now fuzzing with 8 workers
fuzz: elapsed: 0s, execs: 134 (1846/sec), new interesting: 0 (total: 1)
--- FAIL: FuzzDiv (0.07s)
--- FAIL: FuzzDiv (0.00s)
testing.go:1504: panic: runtime error: integer divide by zero
goroutine 147 [running]:
runtime/debug.Stack()
runtime/debug/stack.go:24 +0x9b
testing.tRunner.func1()
testing/testing.go:1504 +0x1ee
panic({0x662a20?, 0x7f9240?})
runtime/panic.go:914 +0x21f
example.Div(...)
example/div.go:4
example.FuzzDiv.func1(0x0?, 0x0?, 0x0?)
example/div_test.go:7 +0x2c
reflect.Value.call({0x65ebe0?, 0x6a5738?, 0x693260?}, {0x693dc7, 0x4}, {0xc000167560, 0x3, 0x30?})
reflect/value.go:596 +0xce7
reflect.Value.Call({0x65ebe0?, 0x6a5738?, 0x7eabc0?}, {0xc000167560?, 0x693260?, 0x57614d?})
reflect/value.go:380 +0xb9
testing.(*F).Fuzz.func1.1(0x4367c0?)
testing/fuzz.go:335 +0x347
testing.tRunner(0xc00017dd40, 0xc000177050)
testing/testing.go:1595 +0xff
created by testing.(*F).Fuzz.func1 in goroutine 6
testing/fuzz.go:322 +0x597
Failing input written to testdata\fuzz\FuzzDiv\db4a66cd17474c4b
To re-run:
go test -run=FuzzDiv/db4a66cd17474c4b
FAIL
exit status 1
FAIL example 0.106s
用例执行了一会后就报出了除数不能为 0 的 panic。执行模糊测试的过程中会在当前文件夹生成 testdata 目录,导致用例没有通过的数据会保存在这个目录下,下次再次执行用例的时候会再次使用这些数据作为语料
-fuzztime 控制模糊测试的执行时间:
go test -fuzz . -fuzztime 5s