作者 | 孙海英 华东师范大学软件工程学院讲师
苏亭 华东师范大学软件工程学院教授
版块 | 鉴源论坛 · 观模
测试用例自动生成,简称测试生成(Test Generation),是指针对给定的被测对象,例如代码单元、接口、系统等,使用相关算法计算测试用例集合的方法。测试生成的本质是测试设计自动化,无需研发人员参与测试,全部由计算机替代人类完成。测试生成方法与当前在产业界中广泛应用的基于测试框架的自动化测试技术有着本质的差别。后者是测试执行的自动化,还需要依靠研发人员设计测试用例。
从对测试生成问题进行数学建模的角度看,当前主流的测试生成方法可分为基于随机的测试生成、基于符号执行的测试生成、基于搜索的测试生成和基于模型检测的测试生成。基于搜索的测试生成将测试生成问题建模为最优化问题,其核心思想是针对期望达到的测试目标,以相关目标(成本)函数为指引,使用搜索算法在输入域中寻找最优解作为测试用例。
01 概述
基于搜索的测试生成(Search-Based Software Testing, SBST)产生于1976年[1],由于当时测试生成领域关注于基于符号执行的解决方案,因此,在其提出后的十几年里,SBST并未得到重视和发展。直到1990年,研究人员Korel在其发表的论文中,提出SBST可以有效解决当时在符号执行方法中难于处理的复杂数据结构符号化运算的问题[2],SBST才被关注并得以深入研究,应用于各种测试活动中。
02 方法说明
结构测试是面向代码的测试方法之一,被广泛应用于工业实践。其中,分支覆盖是结构测试中最为知名的测试覆盖准则之一。结构测试是最早应用SBST的测试活动,也是产生SBST这一方法的源起点。因其奠基性地位,我们以Korel的SBST方法为切入点,说明SBST的核心思想。
2.1 分支函数
Korel方法以满足分支覆盖为测试生成目标。注意到,代码中产生分支的循环判断条件和选择判断条件等分支谓词可以被转换为符合其逻辑关系的一系列简单的关系表达式:
其中,E1和E2是算术表达式。我们将简单的关系表达式称为分支表达式。为了覆盖分支,可以采用最优化方法计算使得分支表示式判定结果为真时的输入数据。具体地说,结合最优化理论中成本函数的含义可知,以分支覆盖为目标的成本函数如果构造为能够衡量候选输入与期望覆盖分支之间的远近,那么,其中距离最近的输入即为分支表达式的解。基于此,Korel定义了分支函数:
不同形式的分支表达式有不同形式的分支函数,如表1所示。分支函数具有如下特性:
1)当分支函数的值为正值(0如果rel是<)时,分支表达式不成立,该分支的取值为假;
2)当分支函数的值为负值(0如果rel是<=)时,分支表达式成立,该分支的取值为真。
因此,满足分支覆盖的测试生成问题就转为找到使得分支函数值为负值的输入。
表1 Korel定义的分支函数
2.2 测试生成过程
以分支覆盖为测试目标的SBST就是在分支函数指导下,搜索距离期望分支最近的输入数据的过程,基本的搜索过程包含以下步骤:
1)生成被测代码的控制流图;
2)计算满足分支覆盖的路径集合;
3)任选一条期望覆盖的路径;
4)随机生成一组输入数据并执行,记录该输入执行时的路径信息,将路径信息与期望覆盖的路径进行比对,找到两者之间发生偏差的分支,为该分支构造分支表达式;
5)逐一改变输入变量的值进行尝试, 直至找到使得分支表达式的值为负(0如果rel是<=)时的输入,即为所需的测试输入数据;
6)重复3)-5),直到2)中所有路径都被覆盖。
为了说明SBST的主要思想,图1给出了能够覆盖示例代码中某条路径(10-11-12-13)的测试输入的搜索计算过程。需要说明的是,为了清晰简便,示例采用了最基本的直接搜索算法,不包含对搜索过程的优化方法,也不包含计算测试预期结果(Test Oracle)的方法。现代的SBST方法采用的搜索优化算法和成本函数远先进和复杂于示例中的方法。
图1 计算覆盖期望路径的测试输入数据示例
03 主流方法
搜索最优解的算法和成本函数的构造是SBST的核心技术。常用的搜索最优解的算法有爬山算法、模拟退火算法和遗传算法。爬山算法、模拟退火属于局部搜索策略,因为这两种方法每次只考虑一个答案,且只在答案的受限毗邻区附近移动,遗传算法则属于全局搜索,同时考察搜索域中多个样本点,是当前SBST的主流。图3给出了基于遗传算法的SBST的主要流程。
图2 基于遗传算法的SBST主要流程
基于遗传算法的SBST首先使用随机方法产生第一代群体,接着对该群体中的个体进行适应性评估,根据选择策略从中挑选出优质个体集合作为亲代用以产生下一代群体。随后,在对亲代进行交叉、变异和重新组合后产生了继承亲代优良基因的子代。之后,子代进入适应性评估,重复上述行为,直至找到最优解或者资源耗尽。在该过程中,用于评估候选者,引导搜索进入有前景的搜索域的适应度函数(fitness function)是关键技术。
适应度函数具有问题相关性。不同的问题需要定义不同的适应度函数。例如,在最坏执行时间测试时,适应度函数被定义为系统执行时间;在自动泊车控制系统中,适应度函数定义为泊车期间,车辆与某个碰撞点之间的最短距离。在结构测试时,适应度函数常被定义为满足期望的覆盖准则,例如分支覆盖[3]。当前被广泛使用的以满足分支覆盖为目的的适应度函数由研究人员Wegener提出[4]。该适应度函数有两个数值指标,一是接近层级(Approach Level),另一个是分支距离(Branch Distance)。接近层级是指没有被给出的输入执行路径覆盖的与目标点相关的控制节点数量。与目标点越接近,接近层级越低。分支距离用于衡量输入执行期望分支的邻近程度,采用了改进的分支函数定义[5]。最终的适应度值是将分支距离归一化并加上接近层级的结果。分支距离的归一化方法有多种,研究人员Arcuri评估和讨论了这些方法对搜索算法的影响[6]。
04 主要挑战
环境交互问题是面向代码的SBST面临的主要困难之一[3][7]。该问题涉及代码中包含与操作系统、文件系统、网络系统、数据库系统的相关交互。环境交互问题通常采用测试替身的方案[8][9]。但是,由于代码重构和使用测试替身后会存在测试代码执行了被测代码实际不可能执行的路径等情况,因而会产生误报。对于误报目前并没有彻底的解决方案,只存在缓解的方法,一是规避导致误报的原因,二是只在必要的时候使用测试替身技术[9]。
参考文献:
[1] W. Miller and D. Spooner, “Automatic generation of floatingpoint test data,” IEEE Transactions on Software Engineering, vol. 2, no. 3, pp. 223–226, 1976.
[2] B. Korel, “Automated software test data generation,” IEEE Transactions on Software Engineering, vol. 16, no. 8, pp. 870–879, 1990.
[3] Phil McMinn. Search-Based Software Testing: Past, Present and Future. Proceedings - 4th IEEE International Conference on Software Testing, Verification, and Validation Workshops, 153 – 163, 2011.
[4] J. Wegener, A. Baresel, and H. Sthamer, “Evolutionary test environment for automatic structural testing,” Information and Software Technology, vol. 43, no. 14, pp. 841–854, 2001.
[5] N. Tracey, J. Clark, K. Mander, and J. McDermid, “An automated framework for structural test-data generation,” in Proceedings of the International Conference on Automated Software Engineering. Hawaii, USA: IEEE Computer Society Press, 1998, pp. 285–288.
[6] A. Arcuri, “It does matter how you normalise the branch distance in search based software testing,” in Proceedings of the International Conference on Software Testing, Verification and Validation. IEEE, to appear, 2010.
[7] A. Panichella, "Beyond Unit-Testing in Search-Based Test Case Generation: Challenges and Opportunities," 2019 IEEE/ACM 12th International Workshop on Search-Based Software Testing (SBST), pp. 7-8, 2019.
[8] A. Arcuri, G. Fraser, and J. P. Galeotti. Automated unit test generation for classes with environment dependencies. In IEEE/ACM International Conference on Automated Software Engineering (ASE), pages 79–90, 2014.
[9] A. Arcuri, G. Fraser and R. Just, "Private API Access and Functional Mocking in Automated Unit Test Generation," 2017 IEEE International Conference on Software Testing, Verification and Validation (ICST), pp. 126-137, 2017.