鉴源论坛 · 观模丨浅谈随机测试

news/2024/5/14 18:15:29/文章来源:https://blog.csdn.net/TICPSH/article/details/127917295

作者 | 黄杉 华东师范大学软件工程学院博士

          苏亭 华东师范大学软件工程学院教授

首发 | 鉴源论坛 · 观模

01

 什么是随机测试

(Random Testing)

随机测试是一种使用随机、相互独立的程序输入来对计算机程序进行测试的黑盒软件测试(在完全忽略程序内部实现细节的情况下进行测试)技术。在处理完随机且独立的程序输入后,程序输出的结果将会和软件规格说明(software specifications)中所描述的软件行为进行比对来判断该测试是否通过。

随机测试的核心思想接近于无限猴子定理[1](The Infinite Monkey Theorem),所以随机测试也被称为Monkey Testing。无限猴子定理是来自Émile Borel的一本出版于1909年的概率相关的书籍,其中描述了这样一个场景:当一只猴子在打字机键盘上不限时间地随机敲击,它可能输出任何给定文章,例如莎士比亚的完整作品,并且这种可能性随着时间的增长会不断地接近100% 。换用测试的语言来描述则是测试程序通过不断地生成测试输入,其能完整测试整个程序并寻找到程序中异常的可能性会不断增大。

02

早期的随机测试

最早对随机测试技术的使用可以追溯到上个世纪五十年代,那时的数据还存储在穿孔卡片(Punched Card)上。程序员会将扔进垃圾桶中的卡片或者标记有随机数字的卡组作为计算机程序的输入来进行随机测试。

当随机测试被广泛认定为测试程序的最差方式时,Duran和Ntafos两人在1981年正式地对使用随机测试技术对程序进行测试的有效性进行了调研,结果表明相对于系统化的测试技术,随机测试是一个成本低收益高的替代品。

后来在1983年,苹果公司的Steve Capps开发了一款名为“The Monkey”的随机输入生成工具用来对传统的MacOS应用进行测试。他对工具的命名就是化用了无限猴子定理。

1991年,一款名叫 “crashme” 的工具发布。这款工具意在通过随机执行带有随机参数的系统调用来测试Unix以及类Unix操作系统的鲁棒性。

03

随机测试的优缺点

3.1 优点

(1)容易实现和使用。随机测试并不需要知晓程序细节,并且输入也通过随机生成。

(2)对程序不存在偏见。由于随机测试的输入都是随机生成的,不存在人为因素影响,也就不会因为对程序某一部分信任而忽略掉潜在的漏洞。

(3)能快速查找漏洞。随机测试的测试速度快,通过快速和大量的测试,能够在短时间内找到大量的候选漏洞(对漏洞的确认还需要人工参与)。

3.2 缺点

(1)寻找漏洞的精度不高由于随机测试的完全随机性,寻找到的漏洞很可能是一些无关紧要的错误。

(2)过于随机导致对程序的代码覆盖率不高。大部分人认为对程序的测试过于依赖随机,不如通过人工白盒测试的方式来更精确地测试程序。

04

随机测试进阶

模糊测试(Fuzzing)

在1988年的一个风雨交加的夜晚,威斯康星大学的Barton Miller教授在自己的公寓中通过一条电话线连接他在学校中的计算机。暴风雨引发了电话线中的信号错乱,以至于所连接的Unix终端不断接收到糟糕的命令输入,最终导致了系统崩溃。频发的崩溃使这位讲授操作系统课程的教授感到惊讶,因此他脑海中浮现了一个对Unix系统进行鲁棒性测试的念头。于是他在给学生的课程作业中写道:

The goal of this project is to evaluate the robustness of various UNIX utility programs, given an unpredictable input stream. This project has two parts. First, you will build a fuzz generator...  Second, you will take the fuzz generator and use it to attack as many UNIX utilities as possible, with the goal of trying to break them... [2]

教授在作业中要求学生开发一个模糊生成器(fuzz generator),这个生成器可以产生不可预测的输入流,然后将这些杂乱的输入给到Unix系统设施,然后试图攻陷这些设施并找到和分析引发错误的随机输入和原因。这就是模糊测试的诞生,教授在作业中使用的fuzz一词也就被用来命名这一技术。

从上文可以看到模糊测试在诞生之初和随机测试十分相似,都是通过随机的输入来对计算机程序进行功能行为测试。下面的Python代码片段给出了一个最简单的模糊器(fuzzer)例子。这个模糊测试器接收三个参数:最大长度(max_length)、字符的ASCII码起始值(char_start)以及字符的ASCII码从起始到结束的范围(char_range)。该模糊器将生成一个长度为max_length的包含ASCII码在[char_start, char_start + char_range)范围内的字符串。

图 1

所以最原始的模糊测试和随机测试拥有相同的优缺点。其中最显著的问题就是由于其完全的随机性,寻找到的程序错误过于刁钻。可能找到的程序错误只是因为错误的输入导致而和程序本身实现无关,或者程序使用人员根本就不会使用像模糊测试器生成的输入,所以不会在软件设计的考虑范畴之内,甚至模糊测试根本就没有测试到程序的主要功能。

无论如何模糊测试还是有其可取之处的(尤其是测试速度快、易于实现),所以后来的研究者们不断想方设法地,尤其是针对如何更好地生成测试输入方面去提高模糊测试的精度(找到的错误确实是和软件规范说明或预期设想行为不符)和深度(能更多地去测试程序的主要功能)来完善模糊测试的实用性。实现这些目标的主要方法就是通过一些静态(基于覆盖率、基于变异)或动态(基于搜索、基于语法)的方式给模糊器提供额外的辅助信息来帮助模糊器更高效地生成、更有效地测试输入,而不再是完全随机,这也促使模糊测试从黑盒测试向灰盒测试进行转变。下文会进行具体介绍。

现在的模糊测试技术可以有几种划分方式(不限于此):

· 一种模糊测试技术可以是基于生成(generation-based)的或者基于变异(mutation-based),取决于它是在没有任何参考的情况下生成随机输入,还是在现有输入的基础上进行修改,也就是所谓的变异;

· 一种模糊测试技术可以是愚笨的(dumb)或者聪明的(smart),取决于它是否对测试输入的结构敏感;

· 一种测试技术可以是白盒、灰盒或者黑盒(基本上不再使用),取决于它是否对程序结构信息或者程序运行信息敏感。

目前最流行的模糊测试工具主要有AFL以及AFL的扩展系列,如AFLFast、AFL++、AFLGo等。

4.1 基于覆盖率的模糊测试(Coverage-Based Fuzzing)

对于如何提高模糊测试精度和深度的探索,其中一种是利用了代码覆盖率[3](code coverage)这一概念。代码覆盖率包括函数覆盖率(function coverage)、语句覆盖率(statement coverage)、边覆盖率(edge coverage)以及条件覆盖(condition coverage)率等多种覆盖准则,这些覆盖率都在一定程度上反映了测试用例对于程序代码的测试程度,即代码覆盖率越高,测试用例对代码的测试程度越高。近期的一项工作[4]也观察到模糊测试技术的代码覆盖率和能找到程序中的错误具有强相关性。

下面的Python代码片段将给出简单的例子。当输入inp为一个正数的时候,程序执行过程中将会执行第 2 行和第 3 行的代码语句,则语句覆盖率为 2 / 6 = 33.3%。另外对于条件覆盖率来说,整个函数中函数有三个 if 条件语句,每一个 if 条件语句都有真假两种情况,则根据组合原理该函数共有 6 个条件分支。在上述情况下,程序执行过程中只有第一个 if 条件语句为真的分支被执行,则条件覆盖为 1 / 6 = 16.7%。对于输入 inp 为零和负数的情况,语句覆盖为 3 / 6 = 50% 和 4 / 6 = 66.7%,条件覆盖率为 2 / 6 = 33.3% 和 3 / 6 = 50%。

图 2

在模糊测试中对于覆盖率的利用,主要是在测试用例的生成过程中。模糊器首先生成一定个数的随机输入,这些输入被称为种子(seed)。接着模糊器将这些种子输入程序,回收程序执行的结果和预先选定的覆盖率指标。接下来模糊器会根据覆盖率高低,将覆盖率低的种子丢弃,将覆盖率高的种子保留并对这些种子进行操作生成一批新种子再作为输入运行程序。重复上述过程到覆盖率不能够更进一步提高时,终止测试。

4.2 基于变异的模糊测试(Mutation-Based Fuzzing)

由于最初的模糊器完全靠随机生成程序输入,模糊测试很难生成出符合程序要求的合法输入,以至于很难测试到程序的核心功能,同时这也是代码覆盖率极低的一个原因。于是基于变异的模糊测试被提出来解决这个问题。

变异的核心思想是对现有的种子(种子可以合法也可以不合法,但大多数情况下会使用合法的种子,这样通过变异得到的种子后代质量较高)以及通过变异得到种子后代进行操作来生成测试输入。具体的变异操作需要测试人员执行制定。假如针对一个计算机程序的一个合法的程序输入为“3+0”,那么在指定变异操作为随机增加、删除和替换字符串中的某一个字符这三种操作时,经过变异之后的输入就有多种可能,如“3 + - 0”、“3 +”、“3 / 0”。将这些通过变异得到的种子后代扔入程序中运行,这就是基于变异的模糊测试。

变异操作可以被设计为更加复杂精细的过程,例如结合其他种子质量评估指标进行变异或者进行某种针对性变异操作。上一小节末尾描述的将变异操作和覆盖率指标进行结合来反复对程序进行测试,这样可以很好地利用这两种方法的优势,从而增强模糊测试的有效性。著名的模糊测试工具AFL就是基于这样的思路开发的。

4.3 基于搜索的模糊测试(Search-Based Fuzzing)

基于搜索的模糊测试主要依赖于搜索算法。搜索算法也被称为启发式算法(heuristic algorithm),其核心思想是通过某些程序信息来启发和引导算法执行。这些算法的灵感大多是来自自然界的现象,如模拟退火算法和本小节会介绍的遗传算法。而它们之所以被称为搜索算法,是因为执行这些算法可以在较大的搜索空间中比随机算法或遍历算法更高效。同样以上一小节的计算机程序输入为例,模糊器对该程序进行模糊测试本质上就是在不断地探索其输入空间,该输入空间中包含了任意长度的合法或不合法的表示四则运算表达式的字符串。想要通过测试来挖掘出程序中隐藏的缺陷,就是在输入空间中搜索到特定的输入使得该程序在运行时出现异常行为;想要满足更广的程序覆盖率,就是在输入空间中搜索到特定的输入使得让该程序运行时执行更多的程序语句。

因此搜索算法也就自然而然地与模糊测试结合在了一起,来使模糊器生成更优质的程序测试输入。下面将对基于结合代码覆盖率的遗传算法的模糊测试进行简单的介绍。

我们构建一个简单函数 fun2,该函数将判断特定字符是否存在于输入字符串中,然后对应分支返回一个整型数字。

图 3

在这个例子中我们给定模糊器的初始种子,为“axxx”,“xxxb”、“xxxc”和“xxxd”。我们首先将这些种子作为输入来运行这个函数,得到每个种子的语句覆盖数量,分别是 3 、2 、2、2 。输入“axxx”是可以让程序执行第 2、3 和 8 行语句,而后三个输入只能执行第 2 和 8 行语句。第一轮测试已经结束,这时我们根据种子的语句覆盖数量来生成下一次测试输入集合,具体过程为从种子中选取语句覆盖数量最多的两个作为亲代来进行交叉变异(模拟自然界的遗传现象)。由于后三个种子的数据覆盖数量都为 2 ,则在选择时会随机选取。假设“axxx”和“xxxb”得到了选择,则继续对这两个种子进行交叉变异,此处交叉变异定义为交换两个种子的右半部分子串,即得到的子代为“axxb”和“xxxx”。重复这样的选择并交叉变异的过程直到子代数量等于初始种子数量。假定经过上述过程我们最后得到了“axxb”、“xxxx”、“axxc”和“xxxx”这四个子代,然后就继续重复整个执行过程,也就是将这些子代输入程序继续运行遗传算法来生成更加优质的测试输入,最终提高代码覆盖率和异常检测能力。

从上述例子中可以看到在子代中的“axxb”不仅将原本“axxx”的语句覆盖数量从 3 提升到了 4,并且能更深入地探索整个函数中的条件分支。但可以看到对于上述例子中假设得到子代整个算法已经无法再有进步了,因为这些子代不论怎么交叉变异也无法得到一个包含abc三个字母的字符串。在实际工业生产环境中算法本身会更加复杂,测试种子会经过精心生成和挑选,同时纳入更多指标进行算法引导,对交叉变异的过程也不会只是简单地字符串交换。

4.4 通过文法进行模糊测试(Fuzzing with Grammars)

当程序的输入具有一定规范和结构的(比如数据库或者API的输入),人们开始尝试通过文法(Grammar)来帮助模糊器生成合法规范的测试输入,属于前面提到的基于生成(Generation-based)的模糊测试技术。

下面展示了一个简单的文法,该文法描述的是含有小数或整数的加减乘除的四则运算表达式,如 (1 + 2) * (3.4 / 5.6 - 789) 。使用该文法,从 <start> 非终止符(non-terminal)开始展开,最终就可以得到一个可用于测试计算程序的合法的四则运算表达式。

图 4

对于表达式  (1 + 2) * 3 的部分推导过程如下,过程中遵循最左推导。推导中剩下的部分读者可以自行尝试完成。

图 5

通过这样来产生测试输入相比于纯随机的方式不仅产生的种子质量高,并且符合程序输入规范,能够节省无效测试用例的时间开销从而提高测试效率。

05

总结

随机测试为软件测试提供了一个在黑盒情况下快速和大量地测试程序的全新思路,其进阶版模糊测试更是在经过包括上述基于覆盖率、基于变异、基于搜索以及文法辅助在内的多种方法的增强之后,成为了当前工业环境下软件测试的主流选择,被广泛应用于人工智能测试、自动驾驶系统测试、数据库系统测试、API测试等各种测试场景。虽然克服了随机测试和模糊测试诞生之初的缺陷和问题,当下的模糊测试仍然有待提高进步,例如对模糊测试过程中对触发的程序错误的类型进行识别、整理和分类,以及对引发错误的根源诱因的分析等。学界和工业界也对传统静态分析工具如符号执行技术和模糊测试技术相结合的道路在不断地探索。

参考资料:

[1] “Infinite Monkey Theorem.” In Wikipedia, September 1, 2022. https://en.wikipedia.org/w/index.php?title=Infinite_monkey_theorem&oldid=1107846001.

[2] Bart Miller. 1988.  https://pages.cs.wisc.edu/~bart/fuzz/CS736-Projects-f1988.pdf

[3] “Code Coverage.” In Wikipedia, July 7, 2022. https://en.wikipedia.org/w/index.php?title=Code_coverage&oldid=1096923322.

[4] Marcel Böhme, László Szekeres, and Jonathan Metzman. 2022. On the reliability of coverage-based fuzzer benchmarking. In Proceedings of the 44th International Conference on Software Engineering (ICSE '22). Association for Computing Machinery, New York, NY, USA, 1621–1633. https://doi.org/10.1145/3510003.3510230

[5] “The Fuzzing Book.” Accessed November 5, 2022. https://www.fuzzingbook.org/.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_224141.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Springboot常用参数注解

访问路径为http://localhost:8080/ PathVariable GetMapping("/get/{id}/blank/{name}")public Map getValue(PathVariable("id") Integer id,PathVariable("name") String name,PathVariable Map<String,String> kv){Map map new Hash…

大一新生HTML期末作业 学生个人网页设计作业 HTML5响应式个人简历网站模板 web前端网页制作课作业

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

CNN (吴恩达 2021

week1-2 02_边缘检测例子_哔哩哔哩_bilibili ​ ​ 我们之前在说面部识别介绍过&#xff0c;要识别面部&#xff0c;都是从细微的边缘入手&#xff0c;一层一层聚类&#xff0c;最终实现人脸的识别。神经网络由浅层到深层&#xff0c;分别可以检测出图片的边缘特征 、局部特…

web前端大一实训 HTML+CSS+JavaScript王者荣耀(60页) web课程设计网页规划与设计 HTML期末大作业 HTML网页设计结课作业

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

【MySQL进阶】深入理解B+树索引底层原理

【MySQL进阶】深入理解B树索引底层原理 文章目录【MySQL进阶】深入理解B树索引底层原理一、前言——没有索引的查找1、在一个页中的查找2、在很多页中查找3、总结二、索引1、一个简单的索引方案2、InnoDB中的索引方案3、B 树4、聚簇索引5、二级索引6、回表7、联合索引三、InnoD…

【MySQL数据库笔记 - 进阶篇】(二)索引

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4da;专栏地址&#xff1a;暂定 &#x1f4dd;视频地址&#xff1a;黑马程序员 MySQL数据库入门到精通 &#x1f4e3;专栏定位&#xff1a;这个专栏我将会整理 B 站黑马程序员的 MySQL…

linux备份mysql8.0数据库脚本

文章目录环境要求步骤1、创建一个.sh文件编写shell脚本2、添加定时任务环境要求 linux系统&#xff0c;安装了mysql8.0 步骤 1、创建一个.sh文件编写shell脚本 创建文件的命令&#xff1a; vim ***.shshell文件文件参考自文章 链接 export LANGen_US.UTF-8 #注意&#xf…

Python如何爬取免费爬虫ip

做过大数据抓取的程序员应该都知道&#xff0c;正常市面上的爬虫ip只分为两种&#xff0c;一种是API提取式的&#xff0c;还有一种是账密形式隧道模式的。往往因为高昂费用而止步。对于初学者觉得没有必要&#xff0c;我们知道每个卖爬虫ip的网站有的提供了免费IP&#xff0c;可…

webpack5 Preload / Prefetch解决按需求加载速度

代码分离 | webpack 中文文档webpack 是一个模块打包器。它的主要目标是将 JavaScript 文件打包在一起&#xff0c;打包后的文件用于在浏览器中使用&#xff0c;但它也能够胜任转换&#xff08;transform&#xff09;、打包&#xff08;bundle&#xff09;或包裹&#xff08;pa…

PDPS软件:机器人控制输送带运行虚拟仿真操作方法

目录 概述 旋转台设备运动机构介绍 旋转台设备模型导入与安装 旋转台设备操作创建 机器人控制旋转台设备离线程序命令添加 仿真运行 概述 旋转台也是工业机器人生产线中常用的外围设备&#xff0c;工件安装在旋转台的夹紧机构上&#xff0c;旋转台通过旋转实现工作位置的…

最新最全面的Spring详解(二)——classpath扫描和组件管理

前言 本文为 【Spring】classpath扫描和组件管理 相关知识&#xff0c;下边将对Component 和及其派生出的其他注解&#xff0c;自动检测类和注册beanDifination&#xff0c;组件命名&#xff0c;为自动检测组件提供scope&#xff0c;使用过滤器自定义扫描&#xff0c;在组件中定…

我说MySQL里每张表不要超过100w数据,面试官让我回去等通知?

V-xin&#xff1a;ruyuanhadeng获得600页原创精品文章汇总PDF 目录 1、面试题2、面试官心理分析3、面试题剖析 1、面试题 事务的几个特点是什么&#xff1f;数据库事务有哪些隔离级别&#xff1f;MySQL的默认隔离级别&#xff1f; 2、面试官心里分析 用mysql开发的三个基本…

深度学习项目:男女性别识别【附完整源码】

性别分类对于人机交互应用和计算机辅助生理或心理分析等商业领域的许多应用至关重要&#xff0c;因为它包含有关男女特征差异的广泛信息。 本次案例收集了接近二十万的男女数据集图片。 文章目录性别分类简介使用 Python 进行性别分类的机器学习项目导入相关库和数据模型搭建…

<SQL编程工具MySQL、SQLyog安装及环境配置教程>——《SQL》

目录 1.MySQL安装&#xff1a; 1.1 MySQL下载安装&#xff1a; 1.2 MySQL环境变量配置&#xff1a; 2.SQLyog安装&#xff1a; 2.1 SQLyog下载安装&#xff1a; 3.写在最后的话&#xff1a; 后记&#xff1a;●由于作者水平有限&#xff0c;文章难免存在谬误之处&…

winform语言切换C#设计笔记(八)

一、修改当前区域性 string languageName“zh-CN”; Thread.CurrentThread.CurrentUICulture new CultureInfo(languageName); 二、定义语言切换类Mullanguage或方法如下&#xff1a; private static Dictionary<string, ResourceManager> ResManagerDic new Dictionar…

一文讲解如何学习 Linux 内核网络协议栈

协议栈的细节 下面将介绍一些内核网络协议栈中常常涉及到的概念。 sk_buff 内核显然需要一个数据结构来表示报文&#xff0c;这个结构就是 sk_buff ( socket buffer 的简称)&#xff0c;它等同于在<TCP/IP详解 卷2>中描述的 BSD 内核中的 mbuf。 sk_buff 结构自身并不…

【论文解读】Attentional Feature Fusion

【论文解读】Attentional Feature Fusion一、研究背景二、Multi-scale Channel Attention Module &#xff08;MS-CAM&#xff09;三、Attentional Feature Fusion&#xff08;AFF&#xff09;四、Iterative Attentional Feature Fusion&#xff08;IAFF&#xff09;五、实例&a…

[附源码]java毕业设计价格公示系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【Ajax进阶】跨域和JSONP的学习

✍️ 作者简介: 前端新手学习中。 &#x1f482; 作者主页: 作者主页查看更多前端教学 &#x1f393; 专栏分享&#xff1a;css重难点教学 Node.js教学 从头开始学习 ajax学习 文章目录了解同源策略和跨域  同源策略    什么是同源    什么是同源策略跨域    什么是…

调优工具常用命令

语法格式 mysqldumpslow [ OPTS... ] [ LOGS... ] //命令行格式常用到的格式组合 -s 表示按照何种方式排序c 访问次数l 锁定时间r 返回记录t 查询时间al 平均锁定时间ar 平均返回记录数at 平均查询时间 -t 返回前面多少条数据 -g 后边搭配一个正则匹配模式&#xff0c;大小写…