一个基于UML协作图的集成测试用例生成方法 王林章 (南京大学计算机科学与技术系,南京市汉口路22号419信箱,210093,南京)摘要: UML协作图描述了系统的一个协作中参与对象之间的结构关系和交互行为,确认它们是否被正确实现是集成测试的工作。本文提出了一个基于UML协作图生成集成测试用例的方法,将表示设计的协作图作为测试模型,并从中提取相关信息生成用于测试所描述的行为的集成测试用例。首先通过遍历每条消息的直接后继识别协作图中的表示用例实现的所有可能的场景路径,然后在遍历每条场景路径的过程中获取相应协作执行的路径条件、参数变量和预期方法调用序列,最后使用范畴-划分方法确定场景路径上的输入、输出、环境条件的合理组合作为覆盖该场景路径的测试用例,用于测试一个协作场景路径上的交互行为。该方法完全基于UML,集合了白盒方法和黑盒方法,生成了较少的测试用例覆盖所有的测试需求。本文将该方法应用于一个ATM建立会话的用例片断实现的实例,证明了其可行性和实用性,并提出了一个用UML设计的工具框架,以实现该方法的自动化,使得其可以方便地集成到使用UML的软件开发过程中。关键词:测试用例生成,集成测试,UML协作图,场景路径
中图分类号 : TP311 文献标识码 : 文章编号 : An Approach to Generate Integration Test Cases based on UML Collaboration Diagrams Linzhang Wang, Xuandong Li,Guoliang Zheng (CS Department , Nanjing University, Hankou Road 22 P.O. Box 419, 210093, Nanjing) Abstract: UML collaboration diagrams represent the structure relationship and interactive behavior of the objects involving in a collaboration of the software system, whether they are correctly implemented or not can be validated by integration testing. This paper propose an approach to generate integration test cases based on UML collaboration diagrams, take collaboration diagram as test model, from which we can extract information to generate integration test cases for testing the behavior. Firstly, the method identifies all the scenario paths in the diagram which represent use case realization by traverse the direct successors of each message. Then it selects and traverses each scenario path to get the method call sequence, path condition and parameters. Lastly, it applies category partition method to generate rational combination of input parameters, environmental conditions, as well as the corresponding output and method call sequence, to form a test case for each scenario path, thus we can test the interactive behavior of the software. This method completely base on UML, combine white-box and black-box test method to generate fewer test cases to test the gray-box behavior. In this paper, we apply this approach to an example of constructing sessions between cardholder and the bank through ATM, proving its feasibility and practicability, also propose a corresponding tool framework to facilitate its automation, thus to easily be deployed into the UML –based software development process. Keywords: test cases generation, integration testing, UML collaboration diagram, scenario path 1、引言 面向对象的技术因为能够解决传统程序设计语言的问题,自提出后,一度成为研究热点,事实上采用面向对象技术减少了不少错误的发生,对于提高软件质量起到了很大的作用,但是面向对象技术本身在任何情况下都不会排除软件测试的动机,同时面向对象语言的本质特征,如继承、封装、和多态等,也带来了新的故障风险,并给软件测试提出了新的挑战。[1,2,9] 区别于传统软件的功能分解,面向对象软件是通过合成来构造软件的,因而集成是面向对象软件开发中最重要的工作,面向对象软件构造过程中有的不同层次的集成,包括:从方法到类的集成,类通过继承集成,类通过容器集成,类到组件的集成,组件到应用系统的集成。在面向对象的迭代式增量开发过程中,通过不断的集成产生系统的可执行的版本,但每一个集成的环节都可能引入错误,导致软件中存在缺陷,为了能够发现软件集成中的问题,面向对象软件的集成测试非常重要。[4] 对于传统软件的集成测试,可以根据设计阶段形成的功能分解树,采用自顶向下或自底向上逐步测试用经过测试的单元组装成系统的过程中有无错误。[3]而面向对象软件采用的是通过组合实现系统的功能,没有一个功能分解树可用,所以传统的基于功能分解的集成测试策略不适合面向对象软件。要检验最终实现中各种集成是否与设计的集成一致,则需要对每一个集成层次进行测试,而这里的集成分为结构集成和行为集成,所以面向对象软件的集成测试包含结构集成测试和行为集成测试。结构集成测试主要测试类的继承、类的容器、类的接口、组件的接口中有无错误;行为集成测试主要是类内方法交互、类间方法交互、组件间交互是否被错误地实现。测试工作的核心主要是生成测试用例,在面向对象软件开发过程中系统的规约、设计、代码是生成测试的信息来源,是软件在其生命周期不同阶段的变体,当然规约、设计、代码在每一阶段的测试中都起相应的作用,特别地,系统规约是生成系统测试的测试用例的基础和系统测试的检验依据,软件代码是生成单元测试用例的基础和单元测试的检验依据,系统设计是生成集成测试用例和集成测试的检验依据。系统的设计信息有助于理解系统功能和结构,设计模型包含规约和程序结构的信息,同时也描述了系统的相应功能片断的行为,因此也被称为灰盒。可以结合白盒测试和黑盒测试方法,从设计信息生成集成测试用例,测试设计模型表示的软件系统的灰盒行为。 UML是面向对象系统分析、设计的标准的建模语言,自从在1997年成为建模语言事实上的标准后,就得到学术界的推崇和工业界的支持,使得UML广为使用,基于UML的方法和实用技术的研究成为将来的发展趋势。UML对面向对象软件开发全生命周期的支持也使得软件开发人员优先用它来描述系统。[8]正像集许多优点的面向对象技术不能免除软件测试一样,使用UML进行面向对象软件开发,在提高软件质量的同时,仍然需要测试来确认软件分析、设计、实现的一致性和正确性。同时基于UML开发的软件系统,软件开发的分析、设计阶段工作成果多为各种模型图,系统的可用信息都在这些模型图中,给信息的提取带来了新的问题,从而也给测试带来新的课题。对测试而言,原先的基于规约或者是基于程序的方法都不能直接使用,对基于UML模型的测试,要将问题转换到原来传统测试方法可以处理的问题空间中加以解决,转换工作主要解决信息提取问题,然后用常规测试方法生成测试。面向对象的软件中,对象通过交互来实现行为,UML的交互图[6,7]是描述一组对象间的结构关系和交互行为设计的最佳选择,主要有顺序图和协作图两种,顺序图关注全局的时序,协作图关注协作对象之间的关系,本文主要研究协作图。UML协作图描述了系统的一个协作中参与对象之间如何交互,集成测试正是要验证这些对象是否正确交互,所以我们研究基于UML协作图的集成测试用例生成方法。本文中我们使用UML协作图作为系统功能片断的高级描述,用来作为生成测试的基础,使得在系统设计阶段一开始就可以计划集成测试阶段的测试。在软件开发早期准备软件测试,在软件的系统分析、设计阶段,利用每一阶段的人工制品(artifact)生成软件测试各个阶段所需的测试用例,在代码阶段结束后便可以开始测试工作,而且对分析设计模型进行分析的同时也能发现分析、设计本身的缺陷,以便及时排除,以防缺陷随着软件开发过程的进展而被放大。由于UML在工业界的使用越来越普遍,而相应支持在分析设计阶段基于模型生成测试用例的实用方法和支持工具还不多见。我们希望能够研究出仅从UML分析、设计模型图自动生成测试用例的方法,而且不需要使用者的除UML外其他方面专业的知识,能够实现自动化而不增加用户额外的工作量,这样的测试方法容易被已经使用UML的工业界采用。[8,10] 本文研究如何通过面向对象软件设计阶段的UML协作图选择合适的集成测试用例的方法,第2部分对协作图的语法和语义作了详细的介绍,并回顾了测试模型、协作集成测试模式、协作故障模型等知识;第3部分对基于协作图生成测试用例的方法作了总体介绍,详细描述了从协作图生成测试用例的具体算法和支撑工具框架原型,第4部分是相关工作的介绍,最后是结束语和将来工作的构想。 |
2、协作图与集成测试 2.1协作图的语法和语义 UML协作图[7]就是用来表示一组通过交互来实现某些行为的对象,可以用来可视化、详细描述、构造和文档化一个特定的对象群体的动态方面,也可以用来按交互中的角色及其关系对一个用例的特定的场景或控制流的实现进行建模。协作图描述了特定行为的参与对象的静态结构,以及参与对象之间的动态交互,可以用于不同的规约抽象级别,规约级协作图表示了类元角色、关联角色和消息,表示对象之间的可能的关系,而实例级协作图表示对象、链和激励,表示特定对象之间的关系。两者都描述了协作参与者之间的结构关系。如果要表示可能事件,一般用规约级协作图,其中没有条件和循环,实例没有取值范围或有许多可能的路径。实例级协作图用于描述属性或参量有具体的值的对象和链,可变大小多重性的对象和链的具体数目,或者是执行中的分支或循环的特定选择。协作图可以用来表示用例的实现或操作的实现,描述操作和用例的执行实现所处的语境、交互中行为序列。当协作图用于表示用例的实现时,只描述外部可见的动作及其顺序,用对象之间的消息交换来描述一个用例实现的场景。当协作图用来表示一个对象的操作的实现时,提供了更详细的信息,如操作的参数及其用途、参与变量的特征、关联上的约束、操作实现过程中对象的创建和破坏等。本文主要研究用于表示用例实现的实例级协作图,下面介绍实例级协作图符号及其语义。 协作描述了在一定的语境中一组对象以及用以实现某些行为的这些对象之间的相互作用。协作由静态部分和动态部分组成,静态部分描述在协作实例中对象和链可能担任的角色,是角色集合和其间关系,这些关系定义了结构方面的内容,动态部分是一个消息集合,包括一个和多个动态交互,表示在执行计算过程中不同时间里协作中的消息流, 这些消息定义了行为方面的内容。角色表示协作中对象和链的目的,类元角色定义了参与协作执行的对象在一个协作中扮演的角色,关联角色定义了一个类元角色和其他角色之间的关系,是参与协作执行的关联的描述,关联角色是链的子集,链是两个或多个对象之间的单向连接,是关联的实例。对象必须是位于关联相应位置的类的直接或间接实例。关联是两个或多个特定描述其实例间连接的类元之间的关系,参与关联的类元在关联内有有序的位置。在运行时,对象和链与协作中的角色绑定,在不同的协作中一个对象可以绑定到一个或多个角色。 交互是由在一个实现特定目标的协作内一组对象之间通信序列组成的行为规约。每个交互包含消息的偏序集,这些消息由类元角色通过关联角色交换。消息是激励的规约,是发送者和接受者之间的通信。消息指定了发送者对象和接受者对象扮演的角色,说明发送者对象对接受者对象应用何种操作。激励是传递消息期望发生的两个对象之间的通信,激励导致一个操作被激活、发出一个信号、导致一个对象被创建或终止。 本部分介绍一个客户通过ATM上验证用户卡和PIN有效性、建立会话的用例片断[9]的实例级协作图,如图1所示。协作图上存在条件消息说明考虑到许多不同的用例场景,涉及到多个对象之间的交互,其中每一个场景都对应协作图上的一条执行路径,这正是测试所要尝试的。图2表示了在这个协作中参与对象相应的类图。 一个描述用例实现的实例级协作图上用于建模的元模型包括:类元角色名、关联角色名、对象符号、链接符号、消息符号、链上的约束等。对象框能够表示参与协作中交互的对象,链表示这些对象之间的结构关系,消息的箭头形状表示协作对象间的通信模式和对象的执行特征, 消息标签表示对一个对象的操作调用的允许顺序的实例、操作的语义。在实际的建模活动中有些元素并不在模型上反映,例如图1的协作图只表示了协作中参与的对象和对象之间的消息,这是表示对象交互的最小元素集。本文关注协作图表示的动态行为的测试,前面提到协作图上表示交互的主要元素是消息,下面详细介绍消息。 迭代过程调用 |
3、基于协作图生成集成测试用例的方法 3.1研究假定 为了有针对性地解决从协作图生成测试用例的问题,本文作出如下假定和要求: (1)假定协作图描述的协作与用例图描述的规约是一致的。模型本身的验证是通过非形式化的复审和形式化的模型检验方法进行的,已超出本文的研究范围;如果协作图上的场景路径集不能覆盖所有消息,则说明协作图本身有错误; (2)假定系统中的对象都是自行开发的,不包括第三方组件对象,文中的对象可以是不同粒度的对象(类的实例、类簇、组件、子系统、系统),也就是说我们在分析任意对象或类时,在必要的情况下都可以获取其规约和内部详细设计信息,包括功能和结构信息;对于第三方组件的集成测试,[13][17]介绍了详细的测试方法; (3)我们研究的测试是针对检错进行的,确认软件是否正确实现了设计,协作图上的结构关系是否被正确实现,[15]中已有相应的静态检验方法,所以本文只研究动态交互行为的测试; (4)本文为了明确解决问题,假定消息类型只有普通消息、条件消息、循环消息,而且只存在顺序循环,不存在嵌套循环。 3.2方法概述 基于协作图的集成测试(Collaboration diagram-based Integration Testing, CIT )方法集合了传统的白盒测试方法和黑盒测试方法,用于测试协作图中参与协作的对象之间通过消息的交互,对每个协作图处理一次,得到相应的测试用例集。首先分析协作图,提取协作图中表示的所有元素,根据消息的顺序号和消息的条件,找到每一条消息的直接后继消息,然后根据场景路径的定义,使用深度优先方法遍历消息及其直接后继直至到达无直接后继的消息从而生成场景路径,然后回溯到没有被访问的直接后继,重复上述方法找到所有的场景路径;在访问消息获取场景路径的同时,获取该路径的方法调用序列、参数和路径条件,将这些集成测试的关键因素用范畴-划分方法定义为方法序列、环境条件、系统输入、系统输出等范畴,结合该协作片断的用例规约和类图中的定义生成这些范畴的可能选择,然后结合路径约束条件在这些范畴的划分中确定选择项的合理组合,这样我们就等到了该场景路径完整的测试用例,包括外界输入、交互输入、预期方法调用序列、后条件、预期输出。对协作图中的所有场景路径都构造了测试用例,就形成了协作集成测试用例集。这样在实际执行集成测试时不但可以直接观察到系统级的输入作用下协作实现过程中的实际输出,还能够通过动态插装方法在代码中加入不影响软件功能的观察代码[15],使测试人员能够观察到实际协作执行时的方法调用序列和数据流的定义和使用,然后通过比较最终系统实际执行时输出与预期输出的一致性决定该协作实现的功能是否正确,通过比较应该发生的方法调用序列和实际执行时观察到的方法调用序列是否一致,确定协作表示的交互行为是否正确,从而从整体上对协作图描述的系统行为的实现是否与设计一致,从而完成协作的集成测试。 本方法可以以增量的方法进行,最终生成的测试用例的具体程度,与相应UML模型图的设计精化程度相关,因为协作图描述的场景的详细程度与测试用例的表达能力直接相关。 3.3 UML协作图生成测试用例的算法描述 本文的方法能够从协作图规约文档直接生成测试用例,主要描述分析协作图规约文档提取集成测试需求信息并生成消息后继表的算法UMLspecificationparser(),然后为每个消息确定其直接后继消息的findsuccessor()算法,根据消息后继表遍历所有场景路径获取测试用例规约信息的spathgenerator()算法,以及从测试用例规约使用范畴划分方法确定测试用例输入值、预期输出值、预期输出行为的算法testcasegenerator()。UMLspecificationparser()算法从协作图从获取集成测试需求信息是通过对UML协作图规约的文本文件(如Rational Rose 的MDL文件)进行分析完成的[11],在我们的工具中实现相应的功能,本文对分析算法不作详细描述。我们用邻接表定义消息后继列表,将分析结果信息按消息顺序号升序记录到messagelist的表头中,以便下一步处理。我们定义消息后继列表如下: messageitem{ mid:string;//消息顺序号 mguardcondition:string;//消息卫式条件表达式 mlabel:string;//消息标签 msender,mreciever:object;// 消息发送者对象,消息接收者对象 mmethod:method;//消息激活的方法 mtype:[flat flow, procdure call, call return];// 根据消息的箭头及线型划分的消息类型 link:pointer of msuccessor; } msuccessor{ mid:string;//后继消息顺序号 mscondition:string;//选择该后继的条件表达式 next:pointer of msuccesor } messagelist:messageitem[n]; findsuccessor()算法为消息生成直接后继列表的并记录到消息的后继链表中,描述如下: findsuccessor(messagelist){ //找到所有消息的所有可能后继和每个后继条件 //输入:消息后继表messagelist //输出:消息后继表messagelist //出口准则:所有消息都处理完 for i:=1 to n do { if i= =n 或者messagelist[i]为端口输出事件触发消息 messagelist[i].link=nil;i:=i+1; //最后消息或触发端口输出事件的消息无后继消息 else{ if messagelist[i+1]是普通消息 则messagelist[i]的直接后继为messagelist[i+1]; else{ k:=1; do while messagelist[i+k]是条件消息{ messagelist [i+k]是messagelist [i]的直接后继,且条件为messagelist [i+k]的条件取真 if messagelist [i+k]是循环或嵌套层次的第一个消息{ t:=该层次的消息数;messagelist [i+k+t]是messagelist [i]的直接后继; 条件为messagelist [i+k]的条件取假; k:=k+t;}//条件取假时循//环或嵌套内的消息都不发送 else{ messagelist [i+k+1]是messagelist [i]的直接后继; 条件为messagelist [i+1]的条件取假; k:=k+1;//不发送 }endif }enddo }endif i:=i+1; }endif }endfor; }endfindsuccessor; spathgenerator()通过访问消息后继表中消息及其直接后继生成场景路径,在遍历场景路径时同时记录路径上相应的控制流和数据流信息,执行完毕得到一个场景路径集spath相应的控制流数据流测试规约。其算法描述如下: s-pathgenerator(m:msuccessorlist){ //输入:messagelist; (消息后继表) //输出:spath;(场景路径集) spath{ sid:integer;//场景路径顺序号 pathcondition: list of gardcondition; //场景路径的实现条件 mlist:list of message;//场景路径上的消息流列表 parameters:list of variable;//场景路径上定义和使用的变量列表 userinputparameters: list of variable; //场景路径上外界输入参数列表 methodsequence:{objectname,methodname,next};场景路径上由消息激活的方法序列 }[n]; i,j:integer; i:=1; j:=1; Sid:=j;//场景路径序号 //递归访问消息及其直接后继 访问消息m,在消息标签中取出并记录返回值、参数、调用的对象方法; 记录消息条件到路径条件中; if m的后继消息为空 { 一条场景路径结束;j:=j+1;return;}//回溯到m[i]的直接前驱继续 else{ k:=1; while m.link<>nil do { //m的后继消息列表不空 successor:=m.link; spathgenerator(successor) //深度优先遍历该消息及其后继消息 m.link:=successor->next;//下一后继消息; }endwhile }endif; }endfind; testcasegenerator()选定遍历一个场景路径过程中生成的控制流和数据流,定义相关范畴,生成测试用例的规约。消息激活的方法序列正是我们要测试的对象间的交互,是软件执行时表现出来的对象之间的控制流传递行为,是对象之间通过消息交互的结果,定义为交互范畴Interaction Category;输入参数列表为测试该场景时外界的输入,定义为输入参数范畴input parameter Category;我们通过对参与协作对象的类图的分析,以及用例描述,可以获取我们所研究的交互行为定义、输入参数的定义、其他影响消息执行的变量的定义、系统环境条件的定义等,从而可以获取这些系统环境条件、输入参数、方法行为的可能选择,然后结合。 利用范畴-划分思想,用相应场景路径的路径条件和加在消息上的约束、以及系统本身的属性约束来限定这些选择,排除无意义和有冲突的值,然后通过这些不同的范畴的不同选择的可能组合作为一个场景路径的测试用例,这样每个场景路径生成一个集成测试用例。具体算法描述如下: Testcasegenerator(){ //输入:spath[n] //输出:tcsuite[n]{ envirnmentpara,input(inputpara,paravaliue),expectoutput,postcondition} i:integer; for i:=1 to n do { tcsuite[i].postcondition:=spath[i].pathcondition; tcsuite[i].environmentpara:={满足路径条件的环境条件} tcsuite[i].input.inputpara=spath[i].userinputsparamenters; 选择对本场景路径条件有影响的参数确定其可能的取值; tcsuite[i].input.paravalue={符合路径条件的输入参数可能的取值}; 取出spath[i]的方法激活序列,分析每一个方法的定义,确定其可能的行为,选择符合场景路径条件的行为,并将方法序列的执行过程的输出序列存到tcsuite[i].expectoutput中; i:=i+1; }endfor; }endtestcasegenerator; 为说明问题,我们选一条最长路径spath[5](消息序列为:1.1,1.2,2.1,2.2,2.3,4.1,4.2,4.3,5)来演示使用上述方法生成覆盖该路径的测试用例的过程。,从该路径获取相关范畴如下: Tcsuite[5] Pathcongdition:!notATMCard, !isStolen, !accountClosed, validPIN&&n=1,!declineFee Environmentcondition: ATM卡,非成员卡,卡没有被盗,帐户没有关闭 parameter category: inputPIN //影响validPIN 123456 [property validPIN][if !notAtmCard] 564821 123258 …….. deClineFee //影响deClineFee T [property declineFee][if !isMemberCard]] F interaction behavior category: session.beginSession(), 插卡事件创建session对象 cardSlot.isATMCard(), 判断是ATM卡,读取卡号,定义cardNum,notATMCard=F[if !notATMCard] 判断不是ATM卡,notATMCard=T screen.prompt(), 屏幕提示“please input PIN”,n=1[if !notATMCard][property n] 屏幕提示“please input PIN”,n=2[if !notATMCard] [property n] 屏幕提示“please input PIN”,n=3[if !notATMCard] [property n] numkeyPad.getEntry(), 输入正确的PIN inputPIN=’123456’[if n=1] 输入错误的PIN inputPIN<>’123456’[if n=1] 输入正确的PIN inputPIN=’123456’[if n=2] and [if !validPIN&&n=1] 输入错误的PIN inputPIN<>’123456’[if n=2] and [if !validPIN&&n=1] 输入正确的PIN inputPIN=’123456’[if n=3] and [if !validPIN&&n=2] 输入错误的PIN inputPIN<>’123456’[if n=3] and [if !validPIN&&n=2] bank.checkCard(), 为被盗ATM卡验证PIN ,isStolen=T[if !notATMCard] 为帐户关闭的ATM卡验证PIN,accountClosed=T [if !notATMCard] 为合法ATM卡错误输入PIN验证身份,accountClosed=F, isStolen=F ,validPIN=F[if !notATMCard&n<4] 为合法ATM卡正确输入PIN验证身份,accountClosed=F, isStolen=F ,validPIN=T[if !notATMCard&n<4] bank.getFeeAmount(), 获取非成员卡用户交易服务费金额,定义feeAmount [if !notATMCard&&ValidPIN&&n<4 and !isMemberCard] screen.prompt() 屏幕提示“Fee Payed:XXX” numkeyPad.getEntry(), 输入同意付费,declineFee=T 输入拒绝付费,declineFee=F screen.prompt() 屏幕提示“please select transaction”[if !notATMCard&ValidPIN&&n<4] and [if isMemberCard or !isMembercard&!declineFee] 这样我们符合spath[5]路径条件的相应的一个测试用例tcsuite[5]的最后结果为: Test case 5: 外部事件:插卡 environmentcondtion: ATM卡,非成员卡,卡没有被盗,帐户没有关闭 input category: inputPIN=’123456’ //输入有效PIN declineFee=F //输入同意付费 interaction behavior category: session.beginSession(), 为ATM卡合法持卡人建立会话 cardSlot.isATMCard(), 判断是ATM卡,读取卡号cardNum, notATMCard=F screen.prompt(), 屏幕提示“please input PIN”,定义n=1 numkeyPad.getEntry(), 输入正确的PIN,inputPIN=’123456’ bank.checkCard(), 为合法ATM卡正确输入PIN验证身份,定义accountClosed=F, isStolen=F ,validPIN=T,ismemberCard=F; bank.getFeeAmount(), 获取非成员卡用户交易服务费金额,定义feeAmount=xxx screen.prompt() 屏幕提示“fee Payed XXX” numkeyPad.getEntry(), 输入同意付费 定义declineFee=F screen.prompt() 屏幕提示“Please select transaction” 预期的方法调用序列:session.beginSession(),cardSlot.isATMCard() ,screen.prompt() ,numKeypad.getEntry() ,bank.checkCard() ,bank.getFeeAmount(),screen. prompt (),numKeypad.getEntry(),screen. prompt () 后条件: inputPIN=’123456’,!notATMCard, !isStolen, !accountClosed, validPIN&&n=1, !declineFee 预期输出: 屏幕提示“please input PIN” 屏幕提示“fee Payed XXX” 屏幕提示“Please select transaction” 我们可以用同样方法为属于同一个用例的其他协作图构造了测试用例,则该用例的集成测试集构造完成。然后,可以用增量方式为组件、子系统、系统构造完整的集成测试用例集,而且可以用自动的方式进行。可以用[15]中的插装方法按照每一场景路径上的方法调用顺序,对待测试实现进行插装,这样在执行时可以观察到软件用相应测试用例运行的结果,并将观察到的实际执行结果与测试用例中的预期结果进行比较,如果一致,说明相应场景的实现与设计是一致的,否则,存在错误,并且错误在协作图的相应场景路径上,可以通过实际结果与预期结果发生不一致的地方定位错误,然后调试修改。 3.3算法实现工具框架 为了支撑上述测试用例生成方法的自动化,我们设计一个基于UML设计模型图的集成测试用例的自动生成工具UMLTGF,我们仍然使用UML为UMLTGF建模,本文给出UMLTGF的类图,如图3。相应的功能描述如下: 1、UML模型分析器。能够直接读取UML协作图规约的文本文件(如MDL文件)[11],进行解析,并获取对象角色、对象的属性和方法,链、约束,消息流和消息标签,存入相应的中间表,以便测试用例生成器使用; 2、协作集成测试用例生成器。根据消息的顺序号和条件,跟踪消息流,生成每条消息的直接后继,然后通过遍历消息及其直接后继的方法生成协作图上每个用例场景对应的协作的场景路径,同时可以获取场景执行的控制流和数据流,并用范畴-划分方法生成相应场景路径对应的集成测试用例。输入为从协作图中提取的信息中间表,输出为生成的测试用例集合; 3、测试用例管理。为使得生成的测试用例集可复用、可维护、无冗余,对每个测试用例设计了增加、修改、删除操作,用来在测试用例生成过程中管理这些测试用例集。 图3 UMLTGF类图 |
4、相关工作 尽管UML在工业界和研究领域用得相当广泛,关于UML生成测试的研究相对较少。一般测试生成都是将UML模型图转换到一个现成工具能够处理的中间的形式化描述,从而可以处理UML规约。基于UML分析、设计模型获取系统的相关信息生成各个阶段的测试用例的研究近年来有不少成果,从设计阶段的模型图生成集成测试用例的研究较少,[13]提出一个新的基于UML的测试模型生成集成测试的测试用例的方法,该方法首先分析软件系统的顺序图和协作图,提取组件间的事件流,根据组件之间的消息转移将顺序图和协作图划分为一组原子系统功能(ASF)单元,以每个ASF为一个节点、消息流为边构造测试模型,使用面向对象的集成测试方法在测试模型上生成测试用例。 [12]提出基于UML设计规约生成集成测试用例的方法,用UML状态机图建立软件动态行为的模型,组件之间的交互用图上注解表示,将设计规约模型转化为与集成系统的动态行为相应的全局FSM,在FSM上基于一定的覆盖准则使用常规的等价类划分方法生成可用于单元和集成测试的测试用例。[14]提出一种不需要其他形式化知识、只在UML框架内完成测试用例生成的UIT方法,选择实现和执行每个用例图描述的功能的相应顺序图、协作图以及类图,分析图中元素的语义,识别出作为测试单元的参与交互的对象和与其相关的消息的等价类,定义测试规约,从图中找到消息顺序,使用传统的Category Partition Method分析消息顺序,生成最终的测试用例。[15]分析了UML规约级和实例级协作图中所能表示的信息,将信息进行分类,有些信息可以用于对最终程序的静态检查,有些信息可用于动态测试;并设计了一个根据协作图中信息对相应生成的程序进行插装的算法,实现对测试满足测试准则的程度的度量,但生成测试用例的方法还没有给出。[16] 提出了一个基于UML顺序图设计的面向对象的软件的自动测试的概念和相应的实现工具SeDiTeC。该方法提出一个可测试的顺序图的规则,凡是满足可测试性需求的软件系统的顺序图设计模型都可以作为测试规约,并介绍了从一个顺序图中生成测试用例的方法,在SeDiTeC中实现了完整的测试过程。 本文提出的从UML设计模型图(协作图、类图)生成集成测试用例的方法,可以对表示复杂场景的协作图进行处理,与上述方法是有一定区别,也是互补的。 5、总结和将来的工作 本文提出了一个基于UML协作图,采用协作集成测试模式生成集成测试用例的方法,用基于线程执行的方法识别协作图中的场景路径,用控制流和数据流方法遍历场景路径获取交互中的参数变量和方法调用序列,最后使用范畴-划分方法找到场景路径上的变量、方法、输入、输出、环境条件的合理组合作为覆盖该场景路径的测试用例;该方法的特点是:1、集合白盒方法和黑盒方法对协作图描述的灰盒行为进行测试;2、完全基于UML;3、生成较少的测试用例;4、便于实现自动化。 对基于UML生成测试用例的研究还存在许多不足。基于设计描述的形式化的测试准则相对还较少,基于UML模型图生成测试用例的方法也在不停的研究与发展中,目前对UML模型图作进一步精化或扩展其语义后,使用常规方法进行测试用例生成的情况较多,直接使用UML模型图提供的信息的方法较少;把单个模型图作为研究对象的较多,多个模型为同一测试用例生成提供信息的研究较少;针对测试过程中特定级别的测试(类级测试、集成测试)生成测试用例的方法较多,同一模型图为多个级别测试生成测试用例的研究较少;在具体的方法研究中,假设的前提和约束太多,还不能够达到实用的程度;对方法提供自动支持的工具大多是实验室原型,还不能应用到工业界;可应用的领域还有许多局限;缺少整体的、系统的解决方法,还没有能够把待测试系统的所有能够为测试用例生成提供信息的模型图综合利用,形成一个系统的测试用例生成方法,这也正是我们将来的研究方向。 我们将来的研究工作主要有几个目标:第一,提出一种与面向对象软件开发过程集成的测试过程,测试用例应以增量、系统的、与项目成本和进度相适应的可管理的数目的方法产生,利用业务模型生成用户验收测试的测试用例,利用UML分析模型生成系统测试的测试用例,利用UML设计模型生成集成测试的测试用例,利用实现模型生成单元测试的测试用例,能够合理计划测试资源,并能够对软件开发过程起到过程改进的作用;第二,针对UML单个模型图,研究其在为不同层次测试生成测试用例的方法,提出相应可行的测试准则和评估方法,尽量能够直接使用UML模型文档;第三,针对某一层次测试的测试用例生成时,研究综合利用待测试系统的各种模型图生成该测试层次的测试用例的方法;第四,为上述方法提供自动的工具支持,并希望能够与主流建模工具、测试工具集成。 参考文献: |