APP下载

基于Java编译器的MC/DC测试覆盖方法设计

2017-03-31周睿

软件导刊 2016年8期

周睿

摘 要:基于Java编译器的MC/DC测试覆盖方法设计,主要对Java文件中存在的条件表达式实现MC/DC测试覆盖算法,并对其条件语句进行插桩,生成插桩文件,针对后续的具体测试用例检查是否满足MC/DC测试覆盖算法以及覆盖率统计。

关键词关键词:Java编译器;MC/DC;插桩技术

DOIDOI:10.11907/rjdk.161755

中图分类号:TP312

文献标识码:A 文章编号:1672-7800(2016)008-0039-03

0 引言

测试工作日益重要,越来越多的公司使用自动化测试工具。正确选择和使用自动化测试工具,能提高测试效率和质量,降低测试成本。根据测试方法的不同,自动化测试工具分为白盒测试工具、黑盒测试工具和测试管理工具。这些工具主要是Mercury Intera ctive(MI)、Segue、IBM/Rational Compuware Empirix 等公司的产品[1]。

国内外主流的白盒测试工具中都有MC/DC测试覆盖分析,如McCabe、C++ Test、CodeCover等。与白盒测试逻辑覆盖相比,MC/DC 覆盖强度高于语句、判定和条件覆盖,覆盖范围大于条件判定组合覆盖,测试性能接近多条件覆盖,但测试用例数却只是线性增加,远小于多条件覆盖的指数级增加,符合精简高效原则。因此,很有必要在白盒测试中对程序实现MC/DC 测试覆盖算法,生成最小测试用例集,达到自动测试程序目的。

1 核心技术

1.1 插桩技术

程序插桩技术最早由J.C.Huang 教授[1]提出,它是在保证被测程序原有逻辑完整性的基础上在程序中插入一些探针,通过探针的执行并抛出程序运行的特征数据。通过对这些数据的分析,可以获得程序的控制流和数据流信息,进而得到逻辑覆盖等动态信息,从而实现测试目的。

插桩就是在代码中插入一段自定义的代码。

由于插入的代码会一起编译到可执行文件中,所以可执行文件在运行过程中必然会执行插入的自定义代码,这样就可以记录我们希望得到的信息,例如函数的调用信息、软件测试的覆盖率等。插桩难点在于要学习目标语言的语法,能够对其解析和语义理解;确定插入代码内容和位置。

程序插桩技术是在被测程序中插入探针,然后通过探针的执行获得程序的控制流和数据流信息,以此实现测试目的。可以根据探针插入的时间分为目标代码插桩和源代码插桩。

(1)目标码上插桩。在经过编译的目标码上插入记录测试覆盖率的语句,以记录各个程序分支或者语句的测试覆盖率数据。优点在于不需要源程序,只要有目标程序即可;编译时间非常短;比较容易用于处理多种计算机语言编写的软件。缺点是程序执行时的附加开销很大;在没有源码的情况下,只能告知各模块的测试覆盖率是多少,无法显示哪些语句或程序分支没有测试到,从而无法有效地改进测试覆盖率。

(2)源代码插桩。在程序编译之前直接在源代码中插入记录测试覆盖率的语句,以达到记录各程序分支或者组合条件的测试覆盖率数据。优点是程序执行时的附加开销很小;不仅能告知各模块的测试覆盖率是多少,还能显示哪些语句或者程序分支和条件组合是否测试到,能有效提高测试覆盖率。缺点是编译时间较长,处理不同计算机语言需要不同的词法语法分析器。本文采用基于源码的白盒测试技术,如果没有源程序,即使通過目标码插桩方式进行结构测试,也无法显示具体哪个语句或哪个分支被测试到,这就失去了测试价值。

1.2 MC/DC测试覆盖方法准则

MC/DC(修订的条件/判定覆盖,Modified Condition/Decision Coverage)准则[4]是一种实用的软件结构覆盖率测试准则,广泛应用于软件验证和测试过程中。

MC/DC定义为在每个判定条件都曾独立影响判定结果至少一次。 其中独立影响意思是在其它条件不变的情况下,改变一个条件。根据DO-178B,MC/DC(Modified Condition/Decision Coverage)有如下要求:判定中每个条件的所有可能结果至少出现一次,每个判定本身的所有可能结果也至少出现一次,每个入口点和出口点至少要执行一次,并且每个条件都能单独影响判定结果。这里条件是指不含任何逻辑操作符的布尔表达式,由关系操作符构成。判定是指包含逻辑操作符的布尔表达式。如果同一个布尔表达式在一个判定中出现多次,那么该表达式应算作多个条件[5-6]。

1.3 JDBC技术

JDBC技术是Java DataBase Connectivity的缩写,它是SUN公司提供的一种支持基本SQL功能的通用应用程序接口(Application Programming Interface)。它由一组用Java语言编写的类和接口组成。通过这些类和接口,程序开发人员可以在Java语言中方便地建立与数据库的链接,通过执行相应SQL语句,完成对不同数据库的访问。

JDBC能完成3件工作:①数据库建立连接;②向数据库建立连接;③处理数据库返回结果。

数据库连接处理实现如下:

//建立JDBC——ODBC

sun.jdbc.odbc.JdbcOdbcDriver;

//建立失败时的错误处理

catch(ClassNotFoundException event){}

//创建SQL查询语句,将结果保存到rs对象中

Con=建立JDBC——ODBC桥

Sql=SQL查询语句

执行查询

Rs=返回结果

//SQL出错处理

catch(SQLException e1){}

1.4 XML文档存储数据

可扩展的标识语言XML(Extensible Markup Language)是一种元标注语言,即定义特定领域有关语义的、结构化的标记语言,这些标记语言将文档分成许多部件并对这些部件加以标识[7]。

2 设计思路

2.1 技术路线

具体如下:①利用插桩技术,实现对Java文件基于源码的插桩;

②利用MC/DC 准则,设计实现算法流程,实现对Java文件中所有满足MC/DC条件语句的测试覆盖算法,并生成最小测试用例集;

③利用JDBC技术,实现将测试用例集存储到MYSQL中;

④利用XML技术实现对Java文件中的条件语句原型的相关信息存储,和存在数据库中的测试用例集形成一个相互对应的关系,以方便后续页面显示。

2.2 基于源码的条件插桩技术

插桩点识别过程中的词法、语法分析只需识别有限的程序结构即可。而对程序中所有的词法、语法进行分析,是因为从中间代码生成汇编代码时,需要以词法、语法分析作为基础,识别出所有的程序结构。插桩点识别程序的输入为预处理后的源代码文件,输出是插桩后的源代码文件,这样只对有限的程序结构进行插桩,减少了膨胀性,提高了效率,如图1所示。

插桩具体过程:①对Java文件编译,在语法分析过程中,找到需要的插桩点,记录下此位置的行号字节偏移量,并将这些信息存入设计的插桩结构对象JInstru中;②语法分析结束后,将对象JInstru 中的信息即属性值,写入字节流DataOutputStream 中,并生成.map 文件;③从DataOutputStream 读出需要插桩的信息,然后对数据进行分析,根据需要插桩的行号、偏移量、插桩点种类,插入相应的代码,完成整个Java文件的插桩,最终生成插桩后文件,如图2所示。

2.3 MC/DC测试覆盖方法

①从Java编译器语法分析过程中分析条件语句里的布尔表达式和它对应的抽象语法树;②将抽象语法树以逆波兰表达式形式送入FirstProcess,形如AB||C&&,对其进行整形和封装,最终成为一个动态的list;③从FirstProcess 接口输出的list进入SecondProcess接口,对其后序遍历,判断条件的前置条件和默认用例值并封装成对象,存储到ArrayList 里,送入下一个接口;④从SecondProcess接口输出的 ArrayList 进入 ThirdProcess 接口,通过MC/DC 的相关原则输出满足表达式的最小测试用例。MC/DC测试覆盖生成过程如图3所示。

2.4 存储结构

MC/DC 的数据存储分为两部分:①从Java编译器词法分析结束后,要将每个条件语句的原型存储起来生成一个XML文件,用这种标记语言来将复杂的条件语句之间的关系和条件语句中各条件之间的关系作清晰的存储和展现;②每个条件语句对应的最小测试用例集存入到数据库中。这样存储既能保证存储的可行性,又能保证以后界面化显示数据时,能方便调用到正确数据信息。数据分析存储过程如图4所示。

2.5 条件原型存储

XML的存储结构:

例如: if(a){

}

while(a==2 || b >5){

}

设计的Xml结构如下:

0

a

0

a == 2

1

b > 5

Xml的根節点是ConditionBox,用来存储分析Java文件中的所有条件语句的条件原型,里面包含了很多Expression节点。Expression 节点有两个属性:commit 是表达式的原型,例如 a 、 a == 2 这样的整个表达式。index是指该表达式在Java文件中第几个分析条件表达式,即为索引。而每一个Expression都有很多个Condition子节点, Condition的子节点包括 ID 和 ConditionField 分别存储在这个条件的表达式中(存入数据库中的测试用例条件就是用该标记存储的)。这样Xml里面的表达式原型和SQL里面的最小测试用例能一一对应起来。

元素内容中的字符数据不能直接使用:< & > ‘ “,因为这些符号对XML分析器而言都有特殊意义。为了解决这些问题,可以使用字符引用来表达这些字符,如要表达这个标签:

a <= 2,只能使用字符引用表达来完成存储结构,如:

a < = 2

XML预定义的实体引用如表1所示。

2.6 测试用例存储

Java文件中有多少个表达式就有多少个Table,MC/DC 算法的每一个条件表达式形成一张存储生成的测试用例表。

3 结语

全球信息化快速推动了中国软件产业的发展,极大地促进了软件测试业的发展。但目前中国在软件测试认识、软件测试技术、软件测试商业化等方面,与欧美还存在很大差距。具有高安全性要求的航空航天软件尤其需要可靠、有效的软件测试,错误一旦发生,结果往往是灾难性的。MC/DC准则是为了只经过较少的测试就能达到完备测试相同的效果。本研究基于Java编译器设计完成了MC/DC测试覆盖方法,为后期进一步实现覆盖率统计打下了坚实的基础。

参考文献:

[1] 熊继光.新一代软件工程体系与实践[M].北京:清华大学出版社,2008.

[2] [美]APPEL A W.现代编译器的Java实现[M].第2版.北京:电子工业出版社,2004.

[3] [美]阿霍.编译原理[M].北京:机械工业出版社,2003.

[4] [美]DANIEL J MOSLEY , BRUCE A POSEY.软件测试自动化[M].北京:机械工业出版社,2003.

[5] 朱少民.软件测试方法和技术[M].北京:清华大学出版社,2005.

[6] 张义德,王国庆,汤幼宁.更改的判定条件覆盖测试技术研究[J].计算机工程与设计,2003(1):123-129.

[7] 朱海燕,范辉,谢青松.测试用例排序的研究[J].计算机工程与科学,2008(5):254-259.

[8] 陈鑫,杨平.应用MC/DC准则时需考虑的问题及其改进方法[J].计算机工程与设计,2004(6):115-118.

(责任编辑:杜能钢)