【腾讯 TQM】遗传算法在测试中的应用初探

925 阅读9分钟
原文链接: tmq.qq.com

导读

alphago和master在围棋领域的成绩掀起一股人工智能的热潮之后,人工智能在各个领域的应用成为了大家讨论的焦点。其实机器学习在测试领域的应用也已经有很长时间并且取得了一定的效果。 遗传算法作为机器学习的经典算法就在单元测试领域起着重要的作用,今天我们简单讨论一下遗传算法在单元测试中的应用

1.遗传算法

遗传算法是由美国的J.Holland教授于1975年在他的专著《自然界和人工系统的适应性》中首先提出的,模拟自然选择和自然遗传机制的随机化搜索算法。遗传算法在人工智能领域中用于解决最优化解的问题,是进化算法的一种。对于一个最优化问题,一定数量的候选解(称为个体)的抽象表示(称为染色体)的种群向更好的解进化。传统上,解用二进制表示。进化从完全随机个体的种群开始,之后一代一代发生。在每一代中,整个种群的适应度被评价,从当前种群中随机选择多个个体,通过自然选择和突变产生新的种群,该种群在算法的下一次迭代中成为当前种群。定义比较抽象,下面用一个例子来解释。

遗传算法的具体示例

例:求解多项式函数的最小值:

Min F(X) = X­­2-19X+20,其中X=1,2,…64之间的整数(此题的精确解为X=9或10)

如何用遗传算法求解?

遗传算法是来自于生物遗传学,遗传算法中的一些概念同样也来自于生物学中的概念,具体的对应解释如下:

用遗传算法求解过程: Step1:首先生成初始种群,这里是随机选择4个解组成的解集 Step2:对初始种群进行繁衍,也就是进行交叉/变异等操作生成新的解集 Step3:计算解集中每个个体的适应度F(X) Step4:选择F(X)最小的4个个体组成新的解集,继续Step2,进行第二代繁衍Step5:当繁衍的代数达到目标要求(例如10代之后)选择F(X)最小的个体为最佳解

2.遗传算法的设计

Begin /*遗传算法*/

t ←0;/*进化的种群代数*/

生成初始种群P(t)

计算初始种群P(t)中每个个体的适应值;

White(不满足终止条件) do

/*利用下述操作生成新个体,并选择更优个体组成新种群*/

通过复制、交叉或变异操作重组种群P(t)中的个体,产生新个体,行成候选种群C(t);/*注意此处C(t)并未包含P(t)中的个体*/

计算C(t)中每个个体的适应值;

根据适应值从C(t)和P(t)中选择更优的个体组成新种群P(t+1);

End while

选择P(t)中最优的个体为所求的解;

End begin

由遗传算法的设计思想可以看到遗传算法中重要的组成部分包括:初始种群的编码、适应度函数、遗传算子(交叉、编译和选择)。

种群中个体的编码一般采用二进制编码的形式。适应度函数是种群选择的标准,因此适应度函数根据求解的具体问题来确定;适应度函数的设置会影响遗传算法获得最优解的质量。遗传算子用来对个体进行选择运算,选择可以采用随机的方式也可以采用其他算法进行选择。

3.单元测试中的应用

遗传算法在单元测试中的应用

在参数化的单元测试中,已知输入的参数的范围,求解哪些参数的组合能够达到最大的代码覆盖率(也有些研究是能达到最大的路径覆盖/分支覆盖)。因此,遗传算法可以用于选择最优的单元测试用例,也就是单元测试的最优输入集。

采用基于路径的人工智能算法自动生成测试用例时,待测程序被当做函数y=f(x)。函数的输入变量是程序的输入参数x,取值范围是程序的输入空间D;函数的输出变量y是程序的输出,包括返回值和参数赋值结果。程序结构用控制流图表示为G=(V,E,s,e)。其中:V表示语句节点;E表示语句间可能存在的控制流向;s和e分别表示程序的开始语句和结束语句。若存在有序序列(V0,…Vi,…Vn),其中,Vi∈V,并且Vi+1节点可以在Vi节点后立即执行,则该序组成程序G的一条路径。

基于路径的测试用例生成过程首先获取G中的一条典型路径PT作为目标路径,然后使用遗传算法求取X∈D,使得G以X为输入时得到路径PE。当PE与PT重合时,X即为最优测试用例。

遗传算法求解最优测试用例的方法如下:

 

 

Step1:初始化,设定目标路径集合,随机生成初始种群的集合;设定遗传的代数t=0 Step2:计算种群中个体的适应度,对于不同的目标路径有不同的适应度。适应度函数就是该输入对应的分支与目标分支的距离,距离越小表示越接近 Step3:判断是否适应度为0(fitness=0)或者达到了最大遗传代数。如果没有进入step4,如果满足则结束 Step4:随机选择个体,进行交叉和变异操作。再利用适应度选择新一代种群,继续step3 

适应度函数:

当执行路径PE和目标路径PT时间存在未匹配的分支节点,路径覆盖指标PC按照如下公式计算他们之间未匹配的节点数

多路径的适应度函数为:

其中,i是目标路径的索引;j是执行路径的索引;λi∈[0,1]是权重参数,根据目标路径之间的相关度计算而自适应得到。ε△c是调整参数。BC是分支覆盖指标值,分支覆盖指标值可以根据Korel提出的分支函数表计算得到(参见参考文献[5])

 

交叉算子

交叉算子采用双点交叉算法(参见参考文献[6]),其中交叉点的选择可以采用随机的方式也可以采用其他方式。交叉得到的child必须满足在输入空间内。

经过一定代数的进化之后,可以得到满足目标路径的一组输出,他们能够最大限度的对目标路径进行覆盖。进化的过程中需要不断调整适应度函数的参数以得到更好的结果。遗传算法的进化代数不是越多越好­[4],当进化到一定代数之后会出现收敛,再多的代数不会出现更好的结果。

4.测试应用中的改进

遗传算法在测试应用中的改进

由于测试用例生成是一个多项式复杂度的非确定性问题(NP),所以遗传算法也是提供近似解,因此遗传算法也存在着不足。

遗传算法最大的问题是容易陷入局部最优解。因此有些人使用遗传算法和模拟退火算法结合解决陷入局部最优解的情况。解决的思路是用退火算法优化变异操作,跳出局部最优改善收敛速度。在繁衍的过程中,进行交叉和变异等的操作也对后代的影响很大,因此业界也有结合各种其他算法对繁衍过程中的下一代选择进行更一步的优化。

 

遗传算法的初始种群生成对最终的结果的准确度也有很大的影响,原始的遗传算法初始种群采用随机生成的方式。随机生成有可能造成陷入局部最优,因此很多人利用其它的算法(如BP算法等)选取初始种群来达到更好的搜索结果。

 

遗传算法的适应度函数也是决定遗传算法好坏的重要指标,适应度函数的计算主要利用测试数据执行过程中的覆盖来计算适应值。这种适应度函数只考虑了覆盖率,没有考虑时间因素,因此业界也有利用空间和时间结合来定义适应度函数。

5.遗传算法的不足

遗传算法作为数据挖掘的经典算法在单元测试领域也能得到很好的发挥。但是遗传算法也存在不足,因此业界也将遗传算法和其他算法结合起来改进算法的效率和用例生成质量。

机器学习算法在单元测试中的应用目前较为成熟的就是选择测试用例集。最优测试用例的求解问题对于分支覆盖,路径覆盖等都有大量研究,但是目前主要是集中在单元测试领域。另外对于机器学习算法搜索到的用例集价值有多高,对整个项目的贡献有多大还缺乏一个根本的度量,因此,这些算法并没有大规模的应用在实际的项目中。

实际的单元测试中,仅仅针对某个被测对象的分支进行覆盖是远远不够的,选择被测对象,自动生成测试用例,并且根据被测对象的变更自动调整测试用例集都是用例集优化需要解决的问题,目前相关的研究也在进行中,必然有一天人工智能能够解决这类问题,扫平算法研究到实际应用之间的道路。

互动问答?

机器学习在测试领域的应用能带来什么火花?

参考文献:

[1]  胡静,赵莹.机器学习在软件测试用例集优化生成中的应用.

[2]  赵慧娟,孙文辉.基于退火遗传算法的单元测试方法.

[3]  深入浅出遗传算法blog.csdn.net/v_july_v/ar…

[4]  仲晓敏,巫晓琳,赵雪峰.基于退火遗传算法的多路径测试用例生成

[5]  KOREL B.Automated software test data generation[J].IEEE Trans onSoftware Engineering,1990,16(8):870-879

[6]  遗传算法

https://segmentfault.com/a/1190000004155021

 

版权所属,禁止转载