IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> 新功能!Go 模糊测试 -> 正文阅读

[开发测试]新功能!Go 模糊测试

我们曾探讨过如何有效地测试 Go 代码,完善的测试方案能让程序更加健壮与安全。

将于 2022 年 2 月发布的 Go 1.18 是一个大版本:除了备受关注的泛型之外,还有一个非常大的特性将会加入,它就是模糊测试(Fuzzing test)。

为什么需要模糊测试

撰写测试代码能够验证功能特性,提前发现程序错误。我们在设计测试用例时,一般会采用错误猜测增加一些异常用例,检测被测对象在非正常情况下处理异常的能力,以发现被测对象中潜在的缺陷。

但是,采用这种测试设计会面临一个问题:测试用例通常是模糊的。为什么这么说呢?这里列几个原因:

  • 在有限的时间内无法穷举所有可能的输入。

  • 脑力的限制使得我们没法想到所有可能的异常情况。

  • 愈加复杂的系统设计,例如依赖于操作系统、网络、中间件、数据库等组件,程序代码与这些系统组合形成的 bug,我们是无法预知的。

举个例子。假设有一个功能函数,它接收两个整数输入并做一些处理逻辑。那么我们会如何写测试用例呢?

朴素的做法是为期望函数处理的每个数字编写一个测试用例。如果用例数据有 [-100,0]、[222,33]、[-1212,22],此时就有了三个测试用例。但很明显这里漏了一大类情况,例如都是负数?

更有甚者,由于处理逻辑的特殊性,测试用例仅在输入为 [2323,444] 时发生异常,而其他输入数字都正常工作。这应该怎么测试覆盖?

开发人员无法测试所有可能的输入值。此时,模糊测试就体现出了价值。

模糊测试是一种自动化测试技术,其依赖随机函数生成测试用例,并将这些用例不断地输入程序进行测试,以发现代码可能受到影响的问题。

模糊测试的用例是不重复、随机的,这能带给我们意想不到的输入和结果,可以达到我们错过的边缘情况。

Go 模糊测试支持

关于模糊测试,早在 2017 年就已经有了提案(详见 issu #19109、#44551)。Go 模糊测试开源库 go-fuzz 作者 dvyukov 和 @kcc 建议 cmd/go 原生支持模糊测试,就像 tests、benchmarks 和 race detection 一样,是 Go 的一等公民。

提案得到了 Go 官方的支?持,今年 6 月已将模糊测试置于 tip 上进行 beat 测试。若无意外,模糊测试将于 1.18 版本得到正式发布。

接下来,我们使用 gotip 来尝鲜模糊测试

下载安装 gotip
$?go?install?golang.org/dl/gotip@latest
$?gotip?download

安装完毕后,gotip 作为 go 命令的替代品,现在可以运行以下命令进行模糊测试

$?gotip?test?-fuzz=Fuzz
编写模糊测试用例

与单元测试一样,模糊测试代码必须写在 *_test.go 的文件中,测试函数命名形如 FuzzXxx。该函数必须传递一个 *testing.F 参数,就像传递给 TestXxx 函数的 *testing.T 参数一样。

func?FuzzXXX(f?*testing.F)?{
????f.Fuzz(func(t?*testing.T,?m?string,?n?int)?{
??????err?:=?doSomething(m,?n)
??????//?check?for?errors?in?err?here
????})
}

模糊测试模板函数形如上述代码。在第二行中,我们通过 f.Fuzz 函数填充一个常规的测试函数,测试函数包括了 *testing.T 类型的 t,功能函数 doSomething 所需要的 string 类型的 mint 类型的 n

Go 将会自动生成 mn 参数的随机测试用例。

下面是一个 Go 官网博客给出的测试 net/url 包函数的模糊测试示例。

//go:build?go1.18
//?+build?go1.18

package?fuzz

import?(
????"net/url"
????"reflect"
????"testing"
)

func?FuzzParseQuery(f?*testing.F)?{
????f.Add("x=1&y=2")
????f.Fuzz(func(t?*testing.T,?queryStr?string)?{
????????query,?err?:=?url.ParseQuery(queryStr)
????????if?err?!=?nil?{
????????????t.Skip()
????????}
????????queryStr2?:=?query.Encode()
????????query2,?err?:=?url.ParseQuery(queryStr2)
????????if?err?!=?nil?{
????????????t.Fatalf("ParseQuery?failed?to?decode?a?valid?encoded?query?%s:?%v",?queryStr2,?err)
????????}
????????if?!reflect.DeepEqual(query,?query2)?{
????????????t.Errorf("ParseQuery?gave?different?query?after?being?encoded\nbefore:?%v\nafter:?%v",?query,?query2)
????????}
????})
}

其中 queryStr 参数为 string 类型,这代表模糊测试随机生成的输入用例类型。

测试结果

d45314b009907941a60db2298bc7c099.png

模糊测试

模糊测试会大量消耗机器资源。在默认情况下,它启用 GOMAXPROCS 个 worker 并行运行模糊测试,且永不停止。

我们可以通过以下运行参数,对模糊测试进行控制。

-fuzz?name
????Run?the?fuzz?test?with?the?given?regexp.?Must?match?at?most?one?fuzz
????test.
-fuzztime
????Run?enough?iterations?of?the?fuzz?test?to?take?t,?specified?as?a
????time.Duration?(for?example,?-fuzztime?1h30s).
????The?default?is?to?run?forever.
????The?special?syntax?Nx?means?to?run?the?fuzz?test?N?times
????(for?example,?-fuzztime?100x).
-keepfuzzing
????Keep?running?the?fuzz?test?if?a?crasher?is?found.?(default?false)
-parallel
????Allow?parallel?execution?of?a?fuzz?target?that?calls?t.Parallel?when
????running?the?seed?corpus.
????While?fuzzing?with?-fuzz,?the?value?of?this?flag?is?the?maximum?number?of
????workers?to?run?the?fuzz?target?simultaneously;?by?default,?it?is?set?to
????the?value?of?GOMAXPROCS.
????Note?that?-parallel?only?applies?within?a?single?test?binary.
-race
????Enable?data?race?detection?while?fuzzing.?(default?false)
-run
????Run?only?those?tests,?examples,?and?fuzz?tests?matching?the?regular
????expression.
????For?testing?a?single?seed?corpus?entry?for?a?fuzz?test,?the?regular
????expression?can?be?in?the?form?$test/$name,?where?$test?is?the?name?of
????the?fuzz?test,?and?$name?is?the?name?of?the?file?(ignoring?file
????extensions)?to?run.

总结

模糊测试是安全领域内常见的技术,黑客们常使用类似的方法查找系统漏洞。

在测试设计中,我们人工提供的测试用例总是有限的,而错误很可能就发生在被忽略的角落。模糊测试通过自动生成随机数据输入到程序中,监视程序运行情况以发现可能的发生的错误。

在 Go 开源领域,go-fuzz 是一个非常不错的模糊测试工具(感兴趣可以通过参考链接自行学习),但是它没有像使用原生的 Go 工具,例如竞态检测和基准测试一样,那么方便灵活。

目前 Go 原生支持的模糊测试已经 beta 测试了,并将于 Go 1.18 版本发行。这是一个和泛型一样值得期待的功能,两者共同改变着我们开发和测试 Go 程序的方式,让我们拭目以待。

参考

Fuzzing is Beta Ready ?https://go.dev/blog/fuzz-beta

testing: add fuzz test support https://github.com/golang/go/issues/44551

Design Draft: First Class Fuzzing https://go.googlesource.com/proposal/+/master/design/draft-fuzzing.md

proposal: cmd/go: make fuzzing a first class citizen, like tests or benchmarks https://github.com/golang/go/issues/19109

go-fuzz https://github.com/dvyukov/go-fuzz

往期推荐

d69f14fbb75bd339b5fad446c16dcfea.png

机器铃砍菜刀

欢迎添加小菜刀微信

加入Golang分享群学习交流!

感谢你的点赞在看哦~

bccb5df90afae1ab70c3ae31f5aefdd9.gif

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2021-11-24 08:14:59  更:2021-11-24 08:16:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/18 6:02:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码