测试用例自动生成的分支限界算法及实验研究
【摘要】:作为软件测试(包括白盒测试和黑盒测试)里的一个基本问题,面向路径的测试用例自动生成则尤为重要,这是因为白盒测试中的许多诸如控制流测试和数据流测试问题以及黑盒测试中的一些问题都可以归结为面向路径的测试用例生成问题。其非形式化描述为:给定一个程序P和P中一条路径W,设P的输入空间为D,求x∈D,使得P以x为输入运行,所经过的路径为W。这个问题的实质在于约束系统的建立和求解。
约束求解是人工智能的一个传统研究方向。很多实际问题,包括面向路径的测试用例生成,都可以用约束求解问题来描述。但是测试中的很多问题都是NP-难的,甚至有可能是不可判定的问题,如何在可接受的时间内对其进行求解是一个非常棘手的问题。这样,面向路径的测试用例自动生成就转化成了如下问题:如何将约束求解中的方法移植到测试中,使得测试的过程更加高效。
本论文依托国家自然科学基金项目“基于抽象内存模型的复杂类型测试用例生成方法研究”(课题编号:61202080)、国家高技术研究发展计划(863计划)“网构化软件协同生产和运行演化集成平台及服务环境”(课题编号:2012AA011201)、国家自然科学基金重大研究计划“代码自动化覆盖测试的关键技术研究与系统研发”(课题编号:91318301)和计算机体系结构国家重点实验室开放课题“单元测试中基于分支限界的测试用例生成技术研究”(课题编号:CARCH201201),基于代码测试系统CTS(Code Testing System)的抽象内存模型,通过建立高效的约束求解引擎来进行面向路径的测试用例自动生成问题的研究。具体的研究内容包括:
1、基于分支限界算法的约束求解框架
面向路径的测试用例生成问题是一类约束满足问题,这类问题需要通过合适的搜索或寻优算法来求解。分支限界作为全局求解算法提供灵活的回溯机制,可以在局部无解时回到更高的层次以调整搜索的范围并尽量减少访问搜索树上节点的数量。并通过合适的规则扩展叶子节点,包括合理对自由变量进行排序,在尽量少的次数内给变量找到可行解或者尽快判断局部无解,以及在找到可行解后尽量多的剪枝。同时为了便于搜索算法的实施,引入了状态空间搜索来为搜索过程建模。
2、基于程序切片技术的变量初始区间削减和不相关变量移除
根据符号分析、控制流图和区间运算的特点,切片准则从相关变量集及路径条件两个角度获得。出现在同一个表达式中的变量,为了满足表达式的约束它们之间的取值互相影响。路径条件是指在区间运算过程中会产生路径分支的数据流值。通过程序切片技术获取和每个变量相关的表达式信息,建立一个变量和区间初始化值的映射字典。通过查询映射字典,在不排除部分可行解的情况下对变量初始区间进行削减。而对于待覆盖路径来说,并非所有变量的取值都会影响这条路径是否会被执行。通过程序切片技术,在状态空间搜索开始前可以提取到和路径有关的变量,而将和路径不相关的变量从搜索空间中移除,这样可以极大地缩小算法的复杂度。
3、基于迭代区间运算的不可达判定和搜索树剪枝
基于区间运算迭代向下的特点,采用迭代的区间运算策略。迭代达到稳定即是到达了两次区间运算之间的不动点。同时,迭代的区间运算策略可以在算法执行前进行路径可达性的预判,对于不可达路径可以避免后续花费在测试用例生成上的无用功。
4、基于变量级别的自由变量排序决策机制
当不同的变量具有相同的区间大小时,利用区间大小排序的决策机制会失效,则采用一种补充策略来打破这种僵局,即同区间大小的变量再通过级别排序。级别是依据区间运算所提供的启发式信息确定,即:距离程序入口越近的变量对整条路径区间运算的结果影响越大。通过快速排序得到根据区间大小排序的结果后,对于相同区间大小的变量会从入口开始沿着整个路径根据级别进行排序。一旦得出结果则随时退出,因为只要得到序列的第一个元素即可。
5、变量启发式初值选取方法
为了兼顾测试用例的多样性和算法的效率,在通过启发式规则判定初始值选取范围后随机选取初始值。通过符号分析和区间运算技术,可以提取和每个变量相关的表达式,从而对变量在这些表达式中的性质进行分析。从满足约束的角度来说,对于每个表达式,将变量分为三类:正变量、负变量和中性变量。而对于整条路径上的约束,变量也分为三类:正变量、负变量和中性变量。路径上的变量性质是对每个表达式上变量性质进行统计计算的结果。在确定了路径上的变量性质之后,可以有针对性地对每个变量的初始区间进行削减,从而减小搜索范围。
6、爬山法回退策略
爬山法作为一种局部搜索算法,具有快速收敛和实现简单的特点,但是容易陷入局部极值。考虑到测试用例生成并没有最优解的需求,引入爬山法进行局部求解,合理地定义了目标函数来引导局部搜索过程,在有解的情况下快速收敛,在无解的情况下快速退出,在分支限界的框架下充分发挥了它的优势。
实验论证本文提出的分支限界约束求解框架和各个搜索加速策略对于常见benchmark和实际工程程序所生成的测试用例都可以达到很高覆盖率。对于线性程序,可以做到基本无回溯的搜索。文中提出的爬山法,在求解严格的约束比如等式时也有非常好的效果。