一文掌握 Golang 模糊测试(Fuzz Testing)

这篇具有很好参考价值的文章主要介绍了一文掌握 Golang 模糊测试(Fuzz Testing)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

模糊测试(Fuzz Testing)

模糊测试(Fuzz Testing)是通过向目标系统提供非预期的输入并监视异常结果来发现软件漏洞的方法。可以用来发现应用程序、操作系统和网络协议等中的漏洞或错误,特别是容易被忽视的边界情况。模糊测试的基本思路是在测试过程中生成大量的随机数,然后将这些数据输入到被测试的程序中,监测程序的异常运行结果来分析程序中的缺陷和漏洞。

Golang 中的模糊测试

Golang 从 1.18 版本开始将模糊测试整合进了标准库,通过标准库 testing/fuzz 来实现模糊测试,Golang 引入模糊测试可以帮助开发者进一步保障和提高应用程序的安全性。

Golang 中的模糊测试是通过数据构造引擎自动构造出(也可以借助开发者提供的初始数据)大量随机数据,作为程序的输入来进行测试的一种方式。模糊测试会监测程序运行过程中是否出现 panic、断言失败、无限循环等异常情况。这些通过数据构造引擎生成的数据被称为语料(corpus) 。模糊测试是一种持续测试的手段,如果不限制执行的次数或者执行时间,就会一直执行下去。

模糊测试和单元测试类似的地方是测试文件也是以 _test.go 为后缀名,不同的是模式测试函数需要以 Fuzz 为前缀,后面跟上一个或多个字符或字符组合来标识测试用例的名称(一般使用被测的函数名称),参数必须是 f *testing.F。

看个例子

以 json 格式校验工具 https://github.com/luduoxin/json-validator-go 为例,在 validator 包中的 scanner.go 文件中新增一个除法函数,代码如下:

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

这个函数显然没有考虑除数为 0 的情况,如果使用单元测试,使用的测试数据没有考虑除数为 0 的情况的话,这个问题就不会被发现,但是使用模糊测试就可以测出这种问题。然后在 validator 包中的 scanner_test.go 文件中添加模糊测试用例,代码如下:

func FuzzDiv(f *testing.F) {
    f.Fuzz(func(t *testing.T, a, b int) {
        Div(a, b)
    })
}

然后运行模糊测试用例,如下命令是运行所有模糊测试用例:

$ go test -fuzz .
fuzz: elapsed: 0s, gathering baseline coverage: 0/2 completed
failure while testing seed corpus entry: FuzzDiv/120fad832ddff45a1b2b70e7a31805a5c8d84f773566e0d19799aeda53b3f9c0
fuzz: elapsed: 0s, gathering baseline coverage: 0/2 completed
--- FAIL: FuzzDiv (0.02s)
    --- FAIL: FuzzDiv (0.00s)
        testing.go:1349: panic: runtime error: integer divide by zero
            goroutine 55 [running]:
            runtime/debug.Stack()
                /usr/local/Cellar/go/1.18.3/libexec/src/runtime/debug/stack.go:24 +0x90
            testing.tRunner.func1()
                /usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1349 +0x1f2
            panic({0x119ccc0, 0x12ed080})
                /usr/local/Cellar/go/1.18.3/libexec/src/runtime/panic.go:838 +0x207
            github.com/luduoxin/json-validator-go/validator.Div(...)
                /Users/ning/projects/go/json-validator-go/validator/scanner.go:634
            github.com/luduoxin/json-validator-go/validator.FuzzDiv.func1(0x0?, 0x0?, 0x0?)
                /Users/ning/projects/go/json-validator-go/validator/scanner_test.go:71 +0x33
            reflect.Value.call({0x1199380?, 0x11d2428?, 0x13?}, {0x11c45aa, 0x4}, {0xc000188360, 0x3, 0x4?})
                /usr/local/Cellar/go/1.18.3/libexec/src/reflect/value.go:556 +0x845
            reflect.Value.Call({0x1199380?, 0x11d2428?, 0x514?}, {0xc000188360, 0x3, 0x4})
                /usr/local/Cellar/go/1.18.3/libexec/src/reflect/value.go:339 +0xbf
            testing.(*F).Fuzz.func1.1(0x0?)
                /usr/local/Cellar/go/1.18.3/libexec/src/testing/fuzz.go:337 +0x231
            testing.tRunner(0xc000180820, 0xc0001a83f0)
                /usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1439 +0x102
            created by testing.(*F).Fuzz.func1
                /usr/local/Cellar/go/1.18.3/libexec/src/testing/fuzz.go:324 +0x5b8
            
    
FAIL
exit status 1
FAIL    github.com/luduoxin/json-validator-go/validator 0.527s

用例执行了一会后就报出了除数不能为 0 的 panic。执行模糊测试的过程中会在当前文件夹生成 testdata 目录,导致用例没有通过的数据会保存在这个目录下,下次再次执行用例的时候会再次使用这些数据作为语料。

$ tree
.
├── scanner.go
├── scanner_test.go
└── testdata
    └── fuzz
        └── FuzzDiv
            └── 120fad832ddff45a1b2b70e7a31805a5c8d84f773566e0d19799aeda53b3f9c0

打开未通过的语料内容,本机的数据如下(每个人执行的用例未通过的语料会有差异):

go test fuzz v1
int(-89)
int(0)

可以看出被除数是 -89,除数是 0,因为 0 不能作为除数,所以会报错。

提供自定义语料

Golang 的模糊测试允许开发者提供初始语料,初始语料可以通过 f.Add 方法添加,也可以将语料按照要求的格式写入 testdata/fuzz/FuzzXXX/ 中的语料文件中。重写 FuzzDiv 方法,添加一些语料,代码如下:

func FuzzDiv(f *testing.F) {
	testcases := []struct {
		a, b int
	}{
		{10, 2},
		{5, 3},
		{-6, 3},
		{-6, -3},
	}
	for _, v := range testcases {
		// 根据提供的语料,反射获得参数类型并穷举可能的值
		f.Add(v.a, v.b)
	}
	f.Fuzz(func(t *testing.T, a, b int) {
		Div(a, b)
	})
}

执行模糊测试用例的其他参数

可以使用 -fuzztime 参数来控制模糊测试的执行时间:

go test -fuzz . -fuzztime 5s

可以指定要执行的模糊测试用例:

go test -fuzz=FuzzDiv -fuzztime 5s

使用指定的未测试通过的数据做测试,使用 -run=file 指定数据文件:

go test -fuzz=FuzzDiv -run=FuzzDiv/378303d09d9499e4e6c708a92079f30db6f554529fd9eb86ac9a9639481fb23d

目前 Golang 的模糊测试支持被测函数使用的参数类型如下:

[]byte, string, bool, byte, rune, float32, float64, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64

模糊测试和单元测试的区别

单元测试需要开发者根据函数逻辑,给定一组或几组输入和输出数据,然后调用被测试函数执行,若返回值与输出数据一致,则说明函数测试通过。因为用于测试的数据是开发者提供的,难免会有遗漏的测试场景,因此即使单元测试通过,并不能说明程序是健壮的。而模糊测试是通过数据构造引擎自动构造出大量随机数据作为函数的输入参数,可以充分测试函数的健壮性。文章来源地址https://www.toymoban.com/news/detail-469982.html

到了这里,关于一文掌握 Golang 模糊测试(Fuzz Testing)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 可靠性测试(reliability testing)

    我们认为软件可靠性始终是重要的,但它对于任务关键型、安全关键型和高使用率系统是必不可少的。如您所料,可靠性测试可用于降低可靠性问题的风险。可靠性故障背后的常见问题包括内存泄漏、磁盘碎片和耗尽、间歇性基础设施问题以及超时值低于可行值。 可靠性定义

    2024年02月16日
    浏览(42)
  • SpringBoot单元测试(unit testing)

    目录 1.什么是单元测试? 2.单元测试的优点 3.关于单元测试框架 4.单元测试的实现

    2024年02月16日
    浏览(44)
  • 如何做好测试?(四)集成测试(Integration Testing, IT)

    集成测试(Integration Testing, IT) ,是一种软件测试方法,旨在验证不同组件、模块或子系统之间的交互和集成是否正常工作。它侧重于测试系统的组件之间的接口和数据传递,以确保它们能够正确协同工作,并检测潜在的集成问题。 集成测试适用于以下情况: 对于网上购物

    2024年02月07日
    浏览(38)
  • 【软件测试】黑盒测试black box testing

    又称为功能测试function testing、行为测试behavior testing 黑盒测试测试不知道代码细节的软件 Black box testing test software without knowing how it is coded. 测试目的:判断输入和输出是否符合软件要求 1. 不需要知道代码细节 2. 相互独立 3. 可以在说明书完成后就设计测试用例,不用等代码完

    2024年04月23日
    浏览(40)
  • 单元测试(unit testing)到底是什么?

    做开发的同学应该都听说过单元测试(unit testing),因为对单元测试的理解程度不同,所以对单元测试的看法也可能有所不同。本文就来深入讲解一下单元测试的概念、作用和是否需要做单元测试。 单元测试(unit testing)是软件开发中的一种最低级别的测试方式,对软件中的

    2024年02月08日
    浏览(54)
  • 【测试开发】单元测试、基准测试和性能分析(以 Go testing 为例)

    你写不出 bug-free 的代码。 你认为自己写出了 bug-free 的代码,但它在你意想不到的地方出错了。 你觉得自己写出了永不出错的代码,但它的性能十分糟糕。 “测试左移”距离真正落地或许还有不短的距离,但在开发过程中注重自己的代码质量,至少养成 写单测 的习惯还是很

    2024年02月04日
    浏览(47)
  • 十分钟理解回归测试(Regression Testing)

    回归测试是一个系统的质量控制过程,用于验证最近对软件的更改或更新是否无意中引入了新错误或对以前的功能方面产生了负面影响(比如你在家中安装了新的空调系统,发现虽然新的空调系统可以按预期工作,但是本来亮的等却不亮了)。其主要目标是确保旨在改进的修

    2024年02月05日
    浏览(75)
  • 【Testing】基于Mockito的FeignClient单元测试

           在微服务框架模式下,往往需要在外部服务没有准备好的情况下进行测试。本文主要是讨论在SpringCloud体系下,以FeignClient进行通信时,对其进行mock的方式。 微服务B通过FeignClient依赖其他服务调用。 3.1)构建基础测试类 3.2)Mock FeignClient 主要就是初始化feignClient的方式(

    2024年02月12日
    浏览(37)
  • 探索Angular测试艺术:Angular Testing Recipes

    项目地址:https://gitcode.com/juristr/angular-testing-recipes Angular Testing Recipes是一个开源项目,由开发者Juri Strumpfloeger精心打造,旨在为Angular开发者提供一系列实用的测试策略和示例代码。该项目以GitCode为平台,以Markdown格式分享了关于单元测试、组件测试、服务测试等方面的实战技

    2024年04月22日
    浏览(34)
  • Python 面试:单元测试unit testing & 使用pytest

    calc.py test_calc.py employee.py test_employee.py 输出为: setupClass setUp test_apply_raise tearDown .setUp test_email tearDown .setUp test_fullname tearDown .teardownClass Ran 3 tests in 0.001s OK employee.py test_employee.py 输出为: setupClass setUp test_apply_raise tearDown .setUp test_email tearDown .setUp test_fullname tearDown .setUp tearDown

    2024年02月10日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包