JUTA一个Java自动化单元测试工具严俊.docx

上传人:b****3 文档编号:3938454 上传时间:2022-11-26 格式:DOCX 页数:14 大小:32.34KB
下载 相关 举报
JUTA一个Java自动化单元测试工具严俊.docx_第1页
第1页 / 共14页
JUTA一个Java自动化单元测试工具严俊.docx_第2页
第2页 / 共14页
JUTA一个Java自动化单元测试工具严俊.docx_第3页
第3页 / 共14页
JUTA一个Java自动化单元测试工具严俊.docx_第4页
第4页 / 共14页
JUTA一个Java自动化单元测试工具严俊.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

JUTA一个Java自动化单元测试工具严俊.docx

《JUTA一个Java自动化单元测试工具严俊.docx》由会员分享,可在线阅读,更多相关《JUTA一个Java自动化单元测试工具严俊.docx(14页珍藏版)》请在冰豆网上搜索。

JUTA一个Java自动化单元测试工具严俊.docx

JUTA一个Java自动化单元测试工具严俊

JUTA:

—个Java自动化单元测试工具

严俊1郭涛2阮

玄跻峰3

(中国科学院软件研究所

北京

100190)

仲国信息安全测评中心

北京

100085)

(大连理工大学数学科学学院

辽宁大连116024)

 

(junyan@acm.or^)

JUTA:

AnAutomatedUnitTestingFrameworkforJava

YanJun1.GuoTao2,RuanHuil.andXuanJifeng3

1(InstituteofSoftware.ChineseAcademyofSciences,Beijing100190)

2(ChinaInformationTechnologySecurityEvaluationCenter.Beijing100085)

3(SchoolofMathematicalSciences,DalianUniversityofTechnology.Dalian.Liaoningl16024)AbstractTestingisveryimportantandtimeconsuminginthedevelopmentofhigh-qualitysoftware

systems.ThispaperproposesanautomatictestingtoolJUTAforunittestingofJavaprograms.Theapproachisbasedonsharpanalysisoftheprograms.JUTAfirstlyemploystheJavaoptimizationframeworkSoottoparseasingleJavamethodintobytecodeandtranslatesitintoacontrolflowgraph

(CFG).Itthenperformsdepth-firstorbreadth-firstsearchontheCFGtoextractpathsfromit.Some

techniquessuchaspathlengthrestrictionareusedtopreventpathnumberexplosion.FinallyJUTAanalyzesthepathsbasedonthecombinationofsymbolicexecutionandconstraintsolving.Thegoalof

pathanalysisliesintwofolds.ltcangenerateasetoftestcasessatisfyingthetestcriterionsuchasstatementcoverage.Thetestsettypicallyhassmallnumberoftestcasesthatareallexecutable.Inadditiontotestgenerationfordynamictesting.itcanalsobeusedinstatictesting.JUTAcanrevealcertainkindsoferrorsfromthesourcecodeautomaticallyiftheuserprovidesproperassertionstodescribetheerrors.Thcexperimentalresultsshowthatthistoolisefficientforbothdynamicandstatictesting.

KeywordsJavaunittesting;dynamictesting;statictesting:

programanalysisisymbolicexecution摘要描述了一个Java自动化的单元测试工具JUTA.JUTA首先调用工具Soot解析单个Java方法的源码,并将源码解析成一个控制流图•在此基础上採用符号执行的方法分析控制流图上的路径.工具

能够自动地产生满足覆盖率标准的程序的测试用例•这种方法产生的所有测试用例都是可执行的,并且

一般来说具有较小的测试用例数•如果用户能够合理地给岀描述程序错误的断言,框架JUTA能够自

动地检查源码中部分特赵类型的错误•实验结果表明工具对Java单元代码的动态测试和静态测试均能

在可接受的时间内给岀有效的结果.

关键词Java单元测试;动态测试;静态测试;程序分析;符号执行

中图法分类号TP311

的控制转移都得到了覆盖)•由于在控制流图模型中,语句与节点相对应,语句覆盖意味着测试路径覆盖所有的节点•同样地,分支覆盖就是所有的测试路径覆盖了控制流图中所有的边.

1.2基于路径的程序测试

程序中的一次完整的执行过程对应控制流图中的一条完整路径•但是,并不是所有的完整路径都代表程序中的一次运行过程•这是因为可能不存在输入数据使得程序按照该路径执行•这样的完整路径称为不可行路径(infeasiblepath),否则称为可行的(fcasiblc)[2].例如,在例1中,路径pl执行的语句如图2所示(符号后的表达式表示程序执行该逻辑判断为真的分支)•易知,程序执行到第2个判断语句时,表达式(i+2Xj<5)不可能满足,程序控制流图中的分支S3-S4不可能被执行到.那么,路径pl是一条不可行的路径.

good=TRUE;

@((i>2)&&(j>3));

J=j-U

@(i+2Xj<5);

good=FALSE;

Fig.2Pathpl.

图2路径pl

由于控制流测试准则都是基于控制流图中的测试路径来立义,很自然地,我们可以采用如下方法来生成测试用例:

首先从控制流图中找到一组路径满足覆盖准则,然后从每条路径中找岀各变量的一组初始值使得程序能够按照路径执行,这些初值就构成了测试用例集合•一般来说,一个自动测试用例生^(automatedtestcasegeneration)系统主要可以

分成3个部分⑶:

1.程序分析器(programanalyzer),其主要工作是把程序转化成容易处理的中间模型(一般就是我们前而提到过的控制流图);

2.路径选择器(pathselector),如何选择路径满足我们的测试需求(比如覆希准则);

3.测试数据生成器(testdatagenerator),如何从测试路径中得到我们需要的测试数据.在实际开发中,程序分析器也被称为前端(frontend),B两部分合起来被称为后端(backend).这样的自动测试生成的系统主要用于程序的动态测试,即采用测试用例测试被测程序.与动态测试对应的静态测试方法,其框架与测试生成大体相同.主要的不同指出在于其输出并不是测试用例,而是直接报告程序是否包含某类错误,或者给出能检岀某类错误的具体的测试数据.

由于程序测试的需求众多,实际的测试系统尤其是商用系统,可能还包括一些其他的辅助模块,比如测试脚本的自动生成器等.

13路径分析方法

不可行路径给自动化测试带来了一个难题,我们不可能简单地通过从程序控制流图的信息中抽取路径来选择测试用例,在测试用例选择时必须分析数据流的信息•为了精确地分析控制流图中一条完整的路径,我们可以采用符号执行(symbolicexecution)[4]的方法•所谓符号执行,相对于普通的程序执行来说,就是程序并不真正用数值来替换程序的变量,而是用一组关于初始值的表达是来表示程序中岀现的项•用符号执行加约朿求解进行程序分析的基本思想是:

采用Hoare逻辑可以将程序路径表示成{P}Q{R},其中P是程序的前宜条件(pre-condition.执行程序前需要满足的条件,或者称为前断言),R是程序的后置条件(post-condition,程序执行后需要满足的条件,或者称为后断言)•假立在程序的符号执行过程中由{P)Q可以推导出约束条件clAc2A…Acn,则应该有clAc2A…•在一般的测试中,如果后断言永真,那么可以对约束条件clAc2A-Acn求解,可以得到变量的初值,从而得到测试用例.另一方面,我们可以对约束clAc2A…AcnAJ^R求解,如果有一组解满足这一约束,说明存在一组输入使运行程序的结果和规范不符•如果程序的规范正确,则程序中必定包含错渓.

对于不包含函数调用代码来说,程序的语句可以分成3类:

1)动作(action),也就是赋值语句;

2)判断语句(predicate),也就是一个逻借表达式;

3)其他不影响变量的表达式,如控制台打印语句System.out.println.我们用一个具体的例子说明符号执行的原理•考虑图2的路径pl,如果i和j的初值为iO和jO.我们可以自顶向下依次执行这段程序,用程序的赋值语句替换判断语句,最后得到一个只含有判断语句的约束集合{iO+2X(jO-l)<5;(i0>2)&&(j0>3)}•这个集合就是程序初值的

约朿•由于这个约朿集是不可满足的,所以路径pl是不可行的.关于符号执行的具体细肖请参考文献[2,5-6].

符号执行的好处是能够精确地分析程序的行为,但它的缺点也是显而易见的.由于符号执行方法过于依赖源代码,并且需要消耗较大的汁算资源,因1842计算机研究与发展2010.47(10)而无法精确分析带有很多模块调用(特别是当这些子模块代码不可见的时候)的程序.同时,程序需要能够用约朿精确模拟复杂程序结构•比如指针和数组的执行,这是一件很困难的事情•最后,为了保证分析的精确性,符号执行需要有一个能力非常强的完备解法器(completesolver,就是说,只要约朿有解,解法器必然能够给出一组解).针对不同的程序,这个解法器可能需要处理位操作等复杂的约束•这一点也限制了符号执行方法的使用•工具JUTA中采用较为简单的方式在工具的处理能力和精确度之前作了一个平衡我们将程序中的表达式限制为布尔逻辑和线性数值约束两种类型,并且将程序的外部调用抽象成简单的赋值语•句和后置断言.具体内容见本文第2节.

2工具JUTA的设计与实现

本节将详细介绍JUTA工具的流程以及工具的模块组成,同时对每一个模块给出英功能以及简要的描述,主要目的是为工具提供一个整体的框架描述.

2.1工具流程为了便于理解源程序需要对程序的源代码进行一圮的处理.首先要做的就是编译分析,包括语法语义错误的检查、建立中间表示(intermediaterepresentation,IR)并生成控制流图等.同时为了以后的分析,我们还需要识别出源代码中的循环,并对循环进行处理,建立一棵循环控制树•这部分通常成为前端处理.有了前端处理的程序结构和数据信息,我们就可以通过算法遍历控制流图,得到一系列的路径,并通过符号执行和约朿求解来分析这些路径,对其可行性进行判断,对于可行的路径为其生成测试数据,最后收集这些测试数据就得到了满足某些性质的目标测试数拯集•因而,从整体上工具分为两个部分:

前端处理和后端分析,英整体结构如图3所示:

Fig.3FrameworkofJUTA.图3JUTA的框架

目前,工具JUTA实现了两方面的功能:

静态测试与动态测试•本文1.2节曾指出,这两种测试方法可以公用相同的前端,主要区别在于工具的后端.接下来我们将按照功能分别介绍工具的各模块.2.2工具输入工具输入包含两部分.首先是被测的Java源码.源码中包含被测Java代码的单个方法•由于工具JUTA的主要功能是完成单元测试,所以,工具将丢弃方法中的外部凋用•用户在测试时,需要手工将重要的外部调用替换成赋值语句或者约束表达式.例如,对于语句y=foo(x),假泄外部调用foo将y的值改变为foox,并且这个值的范由是[lb.ub]•那么可以将这行代码替换为:

y=foox;

assert(Ib<=foox&&foox<=ub);

另一部分的输入是一些描述性质的断言以及断言的插入位置.具体请参见本文2.4.2节.

2.3前端处理前端分析整体上相当于一个编译器的前端,功能上相当于一个不产生目标代码的编译器•在这一部分我们借用的是Java分析优化工具框架Soot[7]的编译分析功能.

Soot是一个功能很强大的分析框架,融合了编译前端以及分析器的各种功能.工具JUTA的前端在Soot框架下扩展苴功能,产生后端分析所需要的中间结果.在JUTA中,我们主要使用了Soot的语法语义检查、中间表示、循环控制分析以及控制流图1843严俊等:

JUTA:

-个Java自动化单元测试工具生成等模块•接下来简要介绍这几个模块的功能.2.3.1语法语义检查模块该模块主要完成源代码语法语义的检查,确保给定的输入程序是没有语法语义错误的,同时建立一棵等价于源程序的抽象语法树.

2.3.2中间代码生成模块这部分通过遍历抽象语法树,对各种语句进行处理,产生中间表示,便于以后的分析和处理.Sool提供了4种中间表示形式:

BafJimplc.Shimplc和Grimp.I具JUTA使用了Soot的Jimple中间表示.Jimple是一种简单的带类型的3地址表示形式.例如图4为Java源码与对应的Jimple代码.图4(a)所示的一段简单的Java代码,经过Soot翻译后得到图4(b)所示:

publicstaticintfunc(intx){

inty=-I;

if(x>0)

y=i;

else

y=2;

returny;

}

publicstaticintfunc(int){intx,y,temp$O.tcmp$1;

x:

=@parameterO:

int;

y=-U

ifx>0gotolabelO;gotolabel1;

labclO:

nop;

temp$0=1;y=tcmp$0;

gotolabel2;labelknop;

temp$1=2:

y=temp$1;label2:

nop;

retumy;

(a)(b)

Fig.4JavasourcecodeandthecorrespondingJimplecode.(a)Javasourceand(b)Jimplecode・

图4Java源码与对应的Jimple代码.(a)Java源码;

(b)Jimple代码

2.3.3控制流图建立模块

本模块通过遍历中间表示的列表,将中间表示序列划分为基本块,控制流图即是以基本块为节点的有向图,描述了源代码中的控制流•工具JUTA使用Soot中的BriefBlockGraph,只为源代码中基本的控制流提供支持,目前无法处理异常(exception).2.3.4循环控制分析模块

这一部分主要是分析控制流中的循环,Soot中将每一个循环抽象成一个对象,每一个循环都存储自己的循环头部以及循环体.一般来说,结构化的程序中的循环分成3类,孤立循环(singleloop).嵌套循环(nestingloop)以及串联的循环(concatenatedloop)[8].我们可以建立一个抽象的循环控制森林,森林中每一个节点是一个表示循环的对象,用来描述循环之间的关系•循环A是循环B的子节点,当且仅当循环B内嵌在循环A之中.当被测程序中不包含串联循环时,循环控制森林退化为循环控制树.2.4后端分析本节将介绍工具的后端.考虑到动静态测试的不同之处.我们将分別介绍动态和静态测试的功能模块,之后对两者进行一个比较.

2.4.1动态测试后端

动态测试的目标是生成一组满足覆盖率的测试数据•所以,动态测试的后端需要分析前端处理后得到的数据信息(包括中间表示、控制流图以及循环控制树),根据路径产生策略以及覆盖准则产生满足要求的路径,并且通过分析路径的可行性得到测试数据•这一部分有以下4个模块:

路径生成、路径转换、路径分析以及路径选择.

1)路径生成模块

这一模块将分析由前端处理得到的控制流图,并抽取出一系列的路径.这些路径可以用基本块的编号序列表示•路径的产生过程是通过遍历控制流图来得到的•由于程序中可能有循环,那么,从图中可能抽取出无限条路径.为了产生有限条测试路径,我们可以限制循环次数或者限制路径的长度(路径表示中基本块的个数)•在工具JUTA中可以通过参数来选择使用的路径限制策略.

路径产生是一个遍历控制流图各顶点的过程,在图的遍历算法中有两种常见的策略:

深度优先遍历(DFS)和宽度优先遍历(BFS).当采用BFS算法时,是按照路径长度由短到长的次序生成路径,所以在队列中需要存储最多两层的中间i'j点,当路径长度限制比较大或者循环次数限制值比较大时,队列中需要存储很多的肖点•在使用DFS算法时,由于优先考虑循环的退出节点,在栈中存储的元素数目比较少,但是生成的最终路径不是按照由短到长的顺序•而且很多路径都是由几个相同的基本块所组成•由上述的比较可知,使用DFS占用较少的系统资源,但是在处理过程中,尤英是在CFG包含环时容易陷入一个分支无法跳出,无法快速达到覆盖率指标,比较适用于静态测试;使得BFS能够较快达到覆盖率,但是代价相对较髙,适用于在测试覆盖准则指导下的测试生成.工具JUTA的路径生成模块实现了这1844计算机研究与发展2010,47(10)

0引言

软件质量历来就是学术界和工业界共同关心的问题,因为软件质量问题造成巨大经济损失事件不胜枚举•当前,随着信息技术的迅速发展,特别是互联网技术的广泛应用Java技术以其通用性、平台移植性、安全性等特征,吸引了众多软件开发者,在各个重要的行业部门得到了广泛的应用•因此,如何提高软件质量,尤苴是提高应用广泛的Java程序的可靠性,长期以来一宜是一个非常重要的研究课题.软件测试是提髙软件质量的重要手段•优秀的软件开发机构把40%的工作量花在软件测试上,软件测试费用则占到了软件开发总费用的30%〜50%,而对于一些要求高可靠性、髙安全性的软件,测试费用已经抬高到了整个软件项目开发所需费用的3〜5倍.

单元测试是软件测试的早期阶段,这种测试方法主要测试程序的单元函数或者类中的方法,苴主要原理是对源代码中的控制结构和处理过程等进行分析,检查程序内部处理是否正确,包括语句结构、分支和循环结构等•由于单元测试需要分析源代码,所以测试的代价往往比较髙•目前,在工业界,单元测试大多仍然是靠人工完成的,如手工设计测试用例、人工审阅代码等,不但十分繁琐,而且测试质量与测试人员的主观经验紧密相关•随着计算机软硬件规模的不断发展,以人工为主的测试方法已经无法满足测试的需求.目前,采用汁算机辅助的自动化软件测试技术成为软件工程中一个活跃的研究领域.

本文介绍一个Java自动化的单元测试工具JUTA(anunittestingandanalyzingtoolforJava).与Junit等传统测试框架不同JUTA提供了一系列的精度和自动化程度较髙的技术来生成测试用例以及检查代码中的错误,以提高测试的自动化程度和效率.

1预备知识

本巧将简要介绍JUTA采用的控制流和数据流分析技术.

1.1控制流图

形式化地说,控制流图(controlflowgraph,CFG)是一个有向图G=N,E,s,f淇中N代表节点的集合.E代表边的集合,s和f分别表示控制流图的起点和终点•图中每个点nGN代表程序中的一系列顺序运算(即这些语句在程序执行过程中要么全部都执行,要么全部都不执行),或者说是一个基本块(basicblock);而每条边,e=(ni,nj)GE,代表从肖点ni到nj的一个转移•用流图作为程序结构的模型时,程序的运行过程可以用流图中的路径来刻画•控制流图中的一条执行路径p代表一个执行序列p=nl,n2,・・・,nm,其中m是路径的长度,(ni.ni+1)GE(1Wi

例1•图1为一段简单的代码及其控制流图•函数foo根据输入i和j的值计算参数good的值并返回.从控制流图上易知程序有3条从起点S到终点F的完整路径:

pl=S,S1,S2,S3,S4,F,p2=

S.S1.S2,S3,F,p3=S.Sl,F.

publicintfoo(intijntj){intgood=TRUE:

*S1*if((i>2)&&(j>3))(

*S2*j-;

*S3*if(i+2*j<5)

*S4*good=FALSE;

}

returngood;

Fig.lApieceofexamplecode.图1一段示例代码

对于基于控制流图的结构测试来说,主要的测试方法就是找到一系列的可行测试路径,这些路径的输入数据就是测试用例•例如在例1中,{i=3,j=4}就是对应于路径p2的一个测试用例.测试人员通过执行这些测试用例来检査程序的错误•显然,由于程序代码的复杂性,通过枚举所有的测试路径来测试程序是不现实的.为了减少测试的代价,人们定义了一系列的测试覆盖准则(coveragecriterion),作为测试的标准来限制测试集的大小[1].最简单的控制流覆盖准是语句覆盖(statementcoverage^卩在软件测试过程中,只有当程序中的所有语句都得到了运行,才能称该测试是充分的)和分支覆盖(branchcoverage,即要求在软件测试过程中,所有1841严俊等:

JUTA:

—个Java自动化单元测试工具两种策略,用户也可以用参数指泄所使用的遍历策略•在默认情况下使用的是深度优先.

2)路径转换模块

前面1.3节中介绍过,对于不包含函数调用代码来说,程序的语句可以分成3类.而我们主要关注其中两类语句,即赋值和判断•路径转换模块将采用基本块的编号序列表示的路径,根据基本块对应的Jimple中间表示.翻译成一些简单的赋值和判断语句,方便下一步的路径分析.

3)路径分析模块

这一部分主要是用来对产生的路径进行分析.张健等人在文献[2,5-6]中提出了基于符号执行以及约束求解的路径分析方法,并给出了一个工具EPAT用于判断C程序路径的可行性.目前,EPAT支持布尔逻辑表达式和线性数值约束表达式及苴混合,同时还支持数组和指针下标的运算.

考虑到经过断言插入和路径转换后的路径只包含两类基本的表达式:

判断和赋值,从而可以调用EPAT来分析Java程序的路径条件,判断出路径是否可行,并对可行的路径产生测试数据.

4)路径选择模块

为了采用较少的测试数据测试程序,可以在所有可行路径中选择一些有代表性的路径来测试被测代码.可行的选择标准就是覆盖准则,例如

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 能源化工

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1