软件测试之Fuzzing和基于属性的测试

软件测试之Fuzzing和基于属性的测试_第1张图片

基于属性的测试技术( Property-based testing),是指编写对你的代码来说为真的逻辑语句(即“属性”),然后使用自动化工具来生成测试输入(一般来说,是指某种特定类型的随机生成输入数据),并观察程序接受该输入时属性是否保持不变。如果某个输入违反了某一条属性,则用户证明程序存在一处错误,并找到一个能够演示该错误的便捷示例。

基于属性的测试技术的一个经典示例是测试一个sort(排序)函数,具体代码如下所示。

@given(st.lists(st.integers()))

def test_sort(s):

out = list(sorted(s))

assert set(out) == set(s)

assert all(x<=y for x,y in zip(out, out[1:]))

这个测试过程假定,给定一列整数,对其进行排序 - 保持元素的集合不变 - 生成一个有序输出

随后,测试框架将针对一些输入序列的集合自动化执行上述代码,并报告是否发现反例。

模糊测试是一种由来已久的实践技术,它通常是指向程序传递某些种类的随机生成数据(通常是纯随机的字节流,但可能以某种智能的方式对其进行了筛选过滤),期望发现能够引发崩溃的某种输入(因此,也同样能够演示该错误)。

近年来,很大程度上由AFL软件所引领的潮流是,以覆盖范围为指导的模糊测试实用技术,采用代码插桩/覆盖的形式,来研究那些更有可能产生有趣行为的输入;这种技术业已证明对大部分模糊测试目标是非常有效的。

在过去,模糊测试和基于属性的测试已知被认为是完全不同的两种技术。基于属性的测试主要起源于哈斯克尔快速审计(Haskell’s QuickCheck),因此通常与富类型语言、形式规约以及其他相关领域联系到一起;而另一方面,模糊测试则通常针对C/C++所编写的二进制程序进行测试,一般与安全范畴联系在一起——该技术的目标是发现可利用的内存破坏错误。

然而在本文中,我想要论证的观点是,模糊测试和基于属性的测试基本上是同一种技术,至少在某种抽象层面上来说是这样的。我希望,对这种相似性的识别能够帮助每一位从业者改进他们的工具和工作流程。

基于属性的测试Fuzzing

如果我们回退到大约一个抽象层面来看,基于属性的测试和Fuzzing显得非常相似。对两种技术而言,我们都需要:

测试系统

一次基于属性的测试过程的传统粒度是一个函数,而对于Fuzzer来说是一个二进制程序;但这两者只是“某些任意计算”的不同实现罢了。

待确认属性

基于属性的测试需要我们编写一条属性作为显式代码,而模糊测试只针对属性“不崩溃”进行测试。然而,通过简单范式“assert(property())”,我们可以将与不崩溃相关的任何属性转换为一句断言;测试人员已经使用该技术发现了非常巧妙的程序行为错误。

用于发现可能违反属性的输入的策略

快速审计,以及许多衍生的基于属性的测试套件,都使用类型驱动的生成策略,而模糊测试主要使用的是随机字节流、人工编码生成器或者已知良性输入的随机变种策略。然而,基本上所有这些方法都只是用于自动化生成输入数据的策略,测试人员期望这些输入数据能够触发违反测试系统所声明属性的行为。

在两种技术在实践和工具方面的用法有很多不同;然而很明显,两者同样存在着深度的相似性,而且两者并不存在根本性的不同。


关注的原因

Fuzzing和基于属性的测试都有悠久的发展历史,多样的工具生态圈以及用户爱好者社区。然而在我的印象中,两者相对很少重叠,而且在两者的生态圈之间没有大范围的跨界交流。我认为这是不对的,两者的工具应该更加紧密地靠拢。在下一篇文章中,我希望针对一些特定技术更加深入地研究其细节,并且希望使用这些技术实现一些基于属性的测试工具。


附录:Hypothesis工具介绍

Hypothesis是一款开源的基于属性的测试工具,主要使用Python语言实现。我认为,该工具在很多方面领先于世界上其他任何一款工具。然而从本文的主题来说,该工具的作者在我之前就意识到了Fuzzing和基于属性的测试之间的根本相似性,并且已经对其进行了撰文论述,同时在这款工具中引入了很多模糊测试领域的思想。

如果你拥有Python编程基础,那么你应该学习使用Hypothesis;如果没有,那么你应该学习理解Hypothesis,这样你就可以在自己的代码中借用其中最佳的思想。

本文由看雪翻译小组 木无聊偶 编译,来源MadeofBugs@Nelson Elhage 转载请注明来自看雪社区

你可能感兴趣的:(软件测试之Fuzzing和基于属性的测试)