JQuery变异算子的冗余检测

2019-05-05 06:57李晨章高建华
小型微型计算机系统 2019年4期
关键词:测试用例等价算子

李晨章,高建华

(上海师范大学 计算机科学与技术系,上海 200234)

1 引 言

JavaScript是一种解释型的脚本语言,它基于对象和事件驱动,具有相对安全性等特点[1].JavaScript运行在客户端,它不与某一单独的浏览器绑定但可以嵌入到任何的Web页面中,节省了Web服务器的请求时间和带宽,运行的结果和处理相对比较快.然而在实际编写JavaScript代码的过程中,一个细微的错误有可能导致一个HTML页面的无法正常显示乃至整个Web应用的瘫痪.

JQuery作为一个继Prototype后快速、简洁的JavaScript框架[2].设计之初就按照Write Less,Do More的思想,通过编写更少的代码实现更多功能.JQuery封装了JavaScript常用的功能代码,升级优化了Html处理事件、交互等方面.

由于jQuery是一种动态语言并且有着强大的拓展性,致使它更容易出错.同时又因jQuery对页面元素或者样式的操作是被封装的,导致在自动化测试过程中很难判断执行结果,所以现阶段jQuery没有办法被很好的测试.

Y.Jia和M.Haram[3]提出一种变异测试的方法,并广泛应用在各个语言的软件上.虽然变异测试已经被证明了在提高测试用例的质量上是有效的,但是测试成本也随之增加,这取决于生成的变异体的数量和产生等价变异体的百分比.

为了降低变异测试的成本,国际上许多学者提出了几种可行的方法.A.J.Offutt和R.H.Untch[4]把这些方法分为了三类,即减少变异、更好的算法以及更快生成和运行.将这三类办法应用在变异测试分析中,可以大幅降低变异测试的成本,剔除测试过程中的不必要的开销.

A.P.Mathur[5]提出了selective mutation 的方法.A.J.Offutt[6]等人又基于此方法提出了N-Selective方法,接着又通过10个程序作为测试数据进行了大量的实验,对结果进行分析后得出可以通过选择性地应用有效的变异算子来减少变异体的数量,并将多余的变异体排除在测试的过程之外.

S.Mirshokraie[7]等人提出了一种被称为FunctionRank的算法,即在JavaScript变异测试中选择更有效的分支和变量进行变异,同时提出了针对jQuery的三类变异算子,但是这三类变异算子并不能完全覆盖jQuery中所有问题.

U.Praphamontripong和A.J.Offutt[8]提出了Web应用中特定的变异算子,并在这些变异算子中寻找冗余算子,却未细化到针对jQuery的变异算子.

J Zhang[9]等人将机器学习运用在变异测试中来预测执行结果,但由于所需样本数量巨大、正确率不到70%和未普及到jQuery中,使该方法暂时不适用于jQuery变异测试.

本文基于变异测试技术,设计了13个针对jQuery的变异算子,并通过实验对变异算子中冗余进行了研究.在时间或计算资源有限的情况下,选择有效变的异算子将减少对jQuery变异分析时所需的成本.

第2节给出了相关的一些术语,第3节描述了变异测试的基本流程,第4节列出了针对于JQuery的特定的变异算子,第5节展示了通过实验获得的数据,并且讨论了结果.

2 相关术语

变异测试的概念最早由R.A.DeMillo等人[10]与R.G.Hamlet[11]提出,且变异测试已应用到了各种语言和软件测试的各个层次上,例如C语言、Java语言、Android软件[12]等.

变异是一种变更程序的行为.用P表示被测原始程序,M表示变更后得到的程序,那么M称为P的变异体.变异一个程序意味对该程序进行变更以达到测试评价的目的,是一种用于评价一个测试集针对特定程序优良程度的手段.

变异算子一般在语法条件允许情况下,仅对被测程序作细微改动.设计变异算子主要目的在于模拟程序员可能犯的简单错误.通常为了提高代码覆盖率和域覆盖率,测试人员需要设计更有效算子.表1展示了一个典型变异算子.

表1 一个典型的变异算子
Table 1 A typical mutation operator

原程序P变异体M……if ( a+b>c )if ( a-b>c ) return true; return true;……

定义1.等价变异体:给定程序P生成的变异体M,若对于所有可能的测试输入t,P(t)=M(t)都成立,就认为变异体M等价于原程序P,也称变异体M是等价变异体,因为它虽然在语法上存在着差异但是与原程序P的功能保持一致.表2给出了一个典型的等价变异体.

表2 一个典型的等价变异体
Table 2 A typical equivalent mutant

原程序P变异体M…… for (int i=0;i<10;i++) {for(int i=0;i!=10;i++){ sum + = a[i]; sum + = a[i];}}……

定义2.可杀死变异体:给定程序P生成的变异体M,若存在测试用例t(t∈T),M上的执行结果不同于原程序P,则称变异体M相对于测试用例集T是可被杀死变异体,也就是说该变异体是可以被检测的.

定义3.可存活变异体:若不存在任何测试用例t(t∈T),在变异体M上的执行结果不同于原程序P,则称变异体M相对于测试用例集T是可存活变异体.可存活变异体中由一部分可通过设计新的测试用例来转化为可杀死变异体,其余的可存活变异体则很可能是等价变异体.

3 变异测试基本流程

变异测试的一般生成与测试方法是:

1)将变异算子O应用在程序P的源代码上以生成变异体M;

2)排除等价变异体;

3)在剩余的非等价变异体上执行测试用例集,判断是否检测出所有的变异体.

变异测试基本流程如图1所示.

图1 变异测试基本流程Fig.1 Basic process of mutation testing analysis

变异测试分析通过变异得分MS(Mutation Score)来评估整个测试用例集T的缺陷检测能力,变异得分MS(T)可通过公式(1)计算获得:

(1)

其中|D|是可被测试用例集T杀死的变异体的数量,|E|是生成等价变异体的数量,|M|是生成变异体的总数量.MS(T)的取值范围介于0到1之间.MS(T)的取值越高,代表测试用例集的实际缺陷检测能力越强.变异测试分析的最终目标是希望MS(T)的取值达到或者更接近于1,也就是测试用例集可以检测出所有的非等价变异体.

使用变异得分进行测试用例评估的过程中存在对测试用例的充分性没有任何贡献的冗余变异体,它们会导致变异得分变得不那么准确.例如,一些变异体几乎能被任何其他的测试用例杀死,如果不考虑这些变异体,并不会影响如何选择测试用例,但是会导致不同的变异得分.总之,冗余变异体不仅会影响整个变异测试的计算和分析开销外,也会影响变异得分.所以如果找到这些生成冗余变异体的变异算子,在变异算子应用于原程序前就将冗余变异算子排除在变异算子集合外,能大幅提高效率.

计算变异体冗余的公式如下:

(2)

公式(2)中mj是第j个变异算子被其它变异算子对应的测试用例集杀死的数量,Mj是第j个变异算子总共生成的变异体的数量.

4 JQuery变异算子设计

本节针对JavaScript中的JQuery代码进行了变异测试分析.变异测试的有效性主要取决于产生变异体的变异算子,在设计变异算子时应深入了解jQuery中潜在的问题,总结一些常见的错误.

4.1 JQuery变异算子

S.Mirshokraie等人[7]首次提出了针对JQuery的三类变异算子.这三类变异算子具体如下:

1)交换选择器中的{#}和{.}符号

{#}在JQuery选择器中表示指定id的元素.id引用HTML元素id属性,id属性在HTML中必须是唯一的.若在同一页面中出现多个id名称相同的元素,会导致选择器失效,不能选中对应元素.在默认浏览器中,如果使用数字开头的id名称可能会导致问题的发生.

{.}在JQuery选择器中表示指定class的元素.class引用HTML元素class属性.与id选择器不同,由于存在拥有同一class属性的元素,class选择器通常可以选择多个元素.

将{#}选择器和{.}选择器互换会使选择域发生变化,导致选择器无法选中目标或选择器失效.

2)移除jQuery对象前的{$}符号

通常jQuery对象用var开头定义,{$}符号是jQuery对象的标识.在生成或者选择已有的元素时,jQuery对象会返回一个类似数组形式的元素的集合.

由于jQuery对象实例和DOM对象实例拥有不同的方法和属性,它们是两种完全不同的对象.若将{$}符号移除或替换可能会导致web应用报错或选择器错误.

3)改变属性/类/元素的名字

addClass方法可以向被选中的jQuery对象的每一个元素上添加指定的css类名,可以是一个或多个.

removeClass方法用来移除被选中的 jQuery对象的一个元素上指定的css类名,可以是一个或多个.

removeAttr方法用来移除被选中的jQuery对象的每一个元素上指定的属性名.

remove方法在不存在参数时会删除所选元素及其子元素,在存在参数时会根据参数所涉及的范围进行相对应删除.

detach方法和remove方法类似,但detach方法会保留对象中的匹配元素,可以在将来再使用这些被保留的元素.

prop方法用于设置或者返回当前jQuery对象所匹配到的元素的属性值.

css方法用于设置或者返回被选元素的一个或者多个样式属性.

其中第1类和第2类变异算子用于分析选择器错误,第3类变异算子主要针对jQuery对象的方法和属性错误.

4.2 新的变异算子

上述三类jQuery变异测试中的变异算子在实际使用中并不能很好的覆盖一些真实的错误类型,例如parent方法和parents方法的错误使用、text方法和html方法的错误使用等.如果用上述的三类变异算子,并不会对所有语句进行变异操作分析,因此无法模拟这类语句上的错误.

本文在已提出的jQuery的错误基础上,对第3类原有变异算子的基础上进行了补充,提出了三类新的变异算子,即第4、5和6类变异算子.在第3类的基础上补充添加了以下几个方法:parent,parents,children,find,text,html,append,after,prepend,before,empty.parent方法用来查找并返回被选元素的直接父元素.

表3 13个变异算子
Table 3 Thirteen mutation operators

变异算子原始代码变异后代码Selector Sign Problem(SIP) 选择器符号错误交换选择器中的{#}和{.}符号O1O2$(′#id′)$(′.class′)$(′.id′)$(′#class′)移除符号{.}或者符号{#} O3O4$(′#id′)$(′.class′)$(′id′)$(′class′)移除jQuery对象前的{$}符号O5var $me = $(′#id′);var me = $(′#id′);this替换 {$()}中的内容 O6$(′#id′) or $(′.class′)$(this)String Joint Problem (SJP) 字符串拼接错误改变jQuery对象拼接字符串中{′}和{″} O7$(′#id′+value+ ′num′).val();$(″#id′+value+ ″num′).val();Conception Confusable Problem (CCP) 概念易混错误 O8O9parent()parents()parents()parent()O10O11remove()detach()detach()remove()O12O13text()html()html()text()

parents方法用来查找并返回被选元素的祖先元素的集合(不包括根元素).

children方法和find方法类似于parent方法和parents方法,区别在于查找返回的是直接子元素和后代元素.

text方法用来设置或者返回被选元素的文本内容.

html方法是用来设置或者返回被选元素的内容.

append方法是用来在被选元素结尾处插入内容.

after方法是用来在被选元素之后插入内容

prepend方法和before方法类似,区别在于在被选元素开头和之前插入内容.

4)this替换{$()}中的内容

this在选择器中是指已经绑定了当前操作的标签,$(this)则表示为当前对象.

将{$()}中的内容用this替换后会引用错误的对象,可能会引起选择器的失效.

5)改变jQuery对象拼接字符串中{′}和{″}

jQuery对象拼接字符串中的{′}和{″}进行交换,如果{′}{″}不成对出现或是交错嵌套使用,均会导致web应用报错或选择器错误.

6)移除符号{.}或者符号{#}

其中,第4类和第6类均属于选择器符号错误,第5类属于字符串拼接错误.

因为针对jQuery方法和属性错误的变异算子过于繁多,所以在最终选择变异算子时,基于熟练程序员假设[6],更关注那些功能类似且易于混淆的变异算子,它们更能模拟熟练程序员的实际编程问题.最终在针对jQuery方法和属性错误的变异算子中选择了6个,即parent,parents,remove,detach,text,html.

针对jQuery的冗余问题,归纳后提出了表3中的13 个jQuery特有的变异算子,并进行了变异测试和分析.其中,选择器符号错误对应第1类、第2类、第4类和第6类变异算子,字符串拼接错误对应第5类变异算子,概念易混错误对应第3类变异算子.

5 实验与结果

本文在实验过程中主要寻求以下几个问题的解答:

Q1:哪几个jQuery变异算子可能是冗余的?

Q2:是否存在质量较高的jQuery变异算子?

Q3:哪几个jQuery变异算子生成的变异体很少被其它变异体的测试用例杀死?

5.1 实验设置

由于现阶段没有适合jQuery的变异生成工具,所以本文使用Python编写代码.本文采用Python中提供的Selenium第三方包,通过使用Python和Selenium的环境,可以做到打开页面,运行测试用例,并提示错误原因.Selenium是一个用于Web应用程序测试的工具,可以按脚本代码依次完成输入、打开、点击等操作,从用户角度测试了web应用.

本文选取某品牌官方商城中jQuery代码居多的Try,Search,Cart,Confirm四个功能页面中相应的代码,对应的具体功能是申请试用、搜索商品、购物车、付款.以付款功能页面中为例,jQuery被用来操作商品数量的增减或删除、地址的选择(异步)、优惠券的使用、支付方式的选择等.四个项目(功能页面)中jQuery代码总长度共计348行.

5.2 JQuery变异体生成

首先将所有的13个变异算子都应用在每一个项目上,生成对应算子的变异体,并依次对每个变异算子所生成的变异体文件分类保存.

通过将第j个变异算子应用在第i个项目上得到的变异体称为变异体Mij.在设计测试用例方面,针对每个不同的变异算子和每个不同的项目设计了与之一一对应的测试用例,以杀死所有非等价变异体.

四个项目总共生成了179个变异体.讨论并区分了4个实验对象中的等价变异体,并且设计了129个测试用例,具体情况见表4.

表4 各项目代码及变异情况
Table 4 Project code and mutation information

项目编号项目名具体功能LOC变异体等价变异体杀死的变异体测试用例S1Try试用申请795024839S2Search搜索商品1797957453S3Cart购物车573203223S4Confirm付款331801814Total3481797172129

表5 变异体情况
Table 5 Mutants information

编号LOCO1O2O3O4O5O6O7O8O9O10O11O12O13TotalS1793939212121301248S2179513513416441223274S357353528210010232S433323214020100018Total348142914299407926346172

从表4可知,S1共获得50个变异体,S2共获得79个变异体,S3共获得32个变异体,而S4共获得了18个变异体.其中等价变异体的总数量为7个,占四个项目所生成的变异体总和的3.91%,非等价变异体的总数为172个.而等价变异体中个3个为O1类型,2个为O6类型,1个为O10类型,1个为O13类型.

在分析O1变异算子产生的2个等价变异体后发现,因为存在某些节点的id名称和class名称一致,有且只有一对的情况下导致了等价变异体的生成.这通常是程序员在编写代码时没有规范命名,使变异前通过id选取的选择器和变异后通过class选取的选择器选中的对象一致,对该选择器的行为和选中对象没有任何影响.而通过O6算子生成的2个等价变异体是因为节点选择器在方法内部且变异前选择器指向的也是该方法所选中的节点,将选择器中的内容在变异为this之后,选择器选取的对象域未发生改变.剩余的2个通过O10和O13算子所生成的变异体,在变异前后,功能上未发生改变,所以在变异后对源代码没有影响.

表5给出了依靠前文中提出的变异算子在每个项目上产生的变异体的具体数量,以及由变异算子生成的变异体的总数.因为O1算子和O3算子、O2算子和O4算子,这两对算子均通过各自相同的选择器生成,所以在没有等价变异体的情况下,数量上是相等的.

表6给出了被杀死变异体情况的数据,其中“测试用例数”所在的列记录了杀死每种算子的所有非等价变异体所需要的测试用例的数量.为了获得对于每一个项目的这些数值,对所有的变异体执行了每一个测试用例集,并且记录了对于每种算子的被杀死的变异体的数量.表6同时给出变异得分(MS)列,该得分通过公式(1)计算得出,其值越高代表该测试用例检测能力越强,但由于可能包涵了冗余变异体,这个得分就变得不那么准确.

表6 变异体被杀死情况
Table 6 Killed mutants information

测试用例集测试用例数被杀死的变异体O1O2O3O4O5O6O7O8O9O10O11O12O13TotalMST_O11114314191255000000810.47T_O22322912833340000001000.58T_O310131714211112000000790.46T_O42222611293191001000920.53T_O593423970200000300.17T_O6278168152403000000920.53T_O761313027000010180.10T_O820100000912101150.09T_O92000000032001060.03T_O1060000003006113140.08T_O1130001000105300100.06T_O1232000000200042100.06T_O1350000200103116140.08

由表6可知,需要11个测试用例来杀死所有通过O1算子产生的变异体,这个测试用例集叫做T_O1.“被杀死的变异体”所在的15列中的前13列给出了被测试用例集杀死的变异体的数量,每个测试用例集能杀死的变异体的数量总和等于最后一列数值.测试用例集T_O1同时能杀死O1算子产生的变异体和其他6个算子产生的变异体.对于某些变异算子而言,被杀死的变异体的数量远远小于所用的测试用例的数量,这是因为一部分测试用例可以杀死多个变异体,也就意味着对角线上的数值至少和左边测试用例的数值一样大,甚至大于左边测试用例数值.

5.3 冗余检测

本文考虑了每一组测试用例如何能更有效的杀死各种变异体.针对某一变异体所设计的测试用例集如果能杀死其他变异体的比例越高,那么越有可能存在冗余的变异算子.

表7 jQuery变异算子冗余
Table 7 Redundancy of jQuery mutation operators

O1O2O3O4O5O6O7O8O9O10O11O12O13T_O11.000.101.000.660.110.630.710.000.000.000.000.000.00T_O20.141.000.070.970.330.830.570.000.000.000.000.000.00T_O30.930.591.000.720.110.280.290.000.000.000.000.000.00T_O40.140.900.791.000.330.480.140.000.000.170.000.000.00T_O50.210.140.140.101.000.180.000.220.000.000.000.000.00T_O60.570.550.570.520.221.000.430.000.000.000.000.000.00T_O70.070.100.070.100.000.051.000.000.000.000.000.250.00T_O80.000.030.000.000.000.000.001.000.500.330.330.000.17T_O90.000.000.000.000.000.000.000.331.000.000.000.250.00T_O100.000.000.000.000.000.000.430.000.001.000.330.250.50T_O110.000.000.000.030.000.000.000.110.000.831.000.000.00T_O120.140.000.000.000.000.000.000.220.000.000.001.000.33T_O130.000.000.000.000.220.000.000.110.000.500.330.251.00

表7列出了每个变异算子基于公式(2)所获得的总体冗余.每个变异算子的整体冗余是基于该变异算子生成的变异体在某个测试用例集下所被杀死的变异体的数量除以该变异算子生成的变异体的总数量.

6 实验数据分析

根据实验结果,可逐一回答前文所提的Q1、Q2、Q3问题.

Q1:O1算子的测试用例集能杀死100%的O3算子生成的变异体,O2算子的测试用例集能杀死97%的O4算子生成的变异体.对于O3算子的测试用例集而言,它能杀死93%的O1算子生成的变异体同时也能杀死72%的O4算子生成的变异体.O4算子的测试用例集能杀死90%的O2算子生成的变异体,同样也能杀死79%的O3算子生成的变异体.这表明在O1、O2、O3、O4算子中存在着冗余.

为了确定哪些变异算子可以移除,本文考虑了在杀死其他算子生成的变异体方面的有效性.值得注意的是,由于O3和O4算子的测试用例集在杀死O6和O7生成的变异体的个数上明显少于O1和O2算子的测试用例集杀死O6和O7算子生成的变异体的个数.因此O1和O2算子生成的变异体更强.所以,可以将O3和O4算子排除在外.

另一个有可能会产生冗余的变异算子是O11,因为O11对应的测试用例集杀死了83%的O10算子生成的变异体.虽然从数值上来看还是相对较小,且O11的测试用例集不能有效的杀死其他变异体,但是也可能会引起冗余.

Q2:在判断是否存在质量较高的变异算子时,本文采用的方法是将可能引起冗余的变异算子排除,再根据变异得分来衡量.故在排除O3、O4后对MS进行排序,排名前三的变异算子为O1、O2和O6.其中O2和O6的MS都高于0.5,所以可以认为O2和O6是质量较高的变异算子,因为针对他们所设计的测试用例集能杀死超过50%的变异体.

Q3:由表7可明显发现,O5、O7和O9 算子生成的变异体很少被其它变异体的测试用例杀死.

7 结束语

变异分析是一种设计、评估和提高测试质量的有效方法.变异分析主要受计算成本等制约,而成本的一个主要因素是变异体生成的数量.本文对jQuery中变异算子的冗余性进行了实证研究.根据研究,从先前定义的变异算子中发现对jQuery的测试几乎没有贡献的变异算子,提出了13个针对于jQuery 的变异算子,随后在四个项目中应用这些变异算子,生成了变异体,并对所有生成的变异体进行了的测试.对每个变异算子生成的变异体进行了测试并记录相关数据.根据这些数据,计算出了之前提出的jQuery中13个变异算子的冗余.结果表明,两个变异算子生成的变异体在很大程度上是冗余的,并且可以在故障检测最小损失时去除,它们是O3算子和O4算子.实验结果同时表明,O1算子和O2算子对应的测试用例集可以有效的杀死其他几种变异算子生成的变异体,这表明了O2和O6算子生成的变异体可能特别强.本文研究后发现O11算子也存在冗余的可能性,因为这个变异算子至少创建了许多冗余.在将来,计划扩展更多的变异算子来测试jQuery下的AJAX以及扩大样本数量、采用机器学习等.

猜你喜欢
测试用例等价算子
基于相似性的CITCP强化学习奖励策略①
等价转化
有界线性算子及其函数的(R)性质
测试用例自动生成技术综述
Domestication or Foreignization:A Cultural Choice
n次自然数幂和的一个等价无穷大
QK空间上的叠加算子
将问题等价转化一下再解答
等价转化思想在高中数学中的应用
测试工时受限的测试策略研究