基于UML状态图测试用例生成的策略研究∗

2020-05-15 05:19栾家伟
计算机与数字工程 2020年2期
关键词:测试用例软件测试对象

栾家伟 吴 陈

(江苏科技大学 镇江 212003)

1 引言

随着软件行业的蓬勃发展,软件的逐渐规范化以及软件规模的日益递增,不仅仅表面上繁重软件开发工作,规模递增的软件也意味着有着大量的软件测试工作,甚至往往软件测试工作占据一半以上的软件开发周期。所以面对巨大的软件测试工作量必须提高测试效率,减少开发周期降低开发成本,并且能够同时完成测试目标提高软件质量。

面向对象的统一建模语言UML主要由图形、模型元素、视图以及通用机制组成。主要用于描述软件规格、可视化研究、软件系统的建模与分析。UML可以针对不同的软件开发方法,贯穿软件生命周期的各个阶段。UML通常用来描述对象、子系统、系统的状态迁移关系。描述面向对象类的某一对象整个生存周期的具体行为。直观地给出了特定对象可能进入的所有状态,以及该对象的状态如何影响该对象的事件。

本文选取UML图形中的状态图用以研究如何基于UML实现测试用例的自动生成。状态图主要是由状态和变迁组成的图,包括事件、状态、变迁三个部分。UML状态图是UML中对系统的动态行为进行建模的表示方法,它包括对反应型对象的行为建模。UML状态图能够直观地给出了特定对象可能进入的所有状态和触发状态转移的条件,以及对象的动作行为,通常表现为状态所经历的状态序列,也包含引起状态转移的事件,以及状态转移伴随的动作,它可以对一个对象的生命周期建模[1]。UML状态图其实就是代表一个状态机,刻画描述对象状态变迁。

J.Offutt等曾经提出关于UML状态图主要有四个测试覆盖准则:状态覆盖准则、状态变迁覆盖准则、状态变迁对覆盖准则、全序列覆盖准则。并开发了一个验证性的测试用例生成工具UMLTest实现了对Rational Rose模型文件的解析,从而读出状态图模型,然后利用相应的测试准则来产生测试用例[2]。

2 基于深度优先算法的路径覆盖策略

基于UML模型生成软件测试主要是对软件系统进行UML建模,根据需求规格说明所建立的UML模型的状态图,提取对应信息将其转化为有向图,用深度优先算法对有向图进行遍历得到相应的测试用例。

路径覆盖:在白盒测试中,路径覆盖能够满足设计出足够多的测试用例,覆盖程序中所有可能的路径以达到覆盖度最高。但是当程序过于复杂,判断和循环过多时,实现路径的完全覆盖却几乎是不可能的。程序中的路径数(复杂度)通过公式V(G)=e-n+2得到(e为边数,n为节点数)。

深度优先算法思想从图的顶点V出发,访问V的未被访问邻接点V',再从V'出发,继续访问未被访问的邻接点,直至一个不存在未被访问邻接点的某节点,此时返回上一个存在未被访问邻接点的节点,当所有节点的邻接点都处于已被访问状态,结束遍历。路径覆盖策略实现过程如图1。

图1 路径覆盖策略

利用深度优先算法对有向图进行遍历从而实现路径覆盖的目的。从图的开始节点进行遍历,一直到路径的结尾,遇到分支即进行拷贝,用二维数组event[rows][0]存储事件集合,path[rows][1]存储路径集合,当path是完整路径时结束遍历循环。

不过在开始路径寻找之前,首先判断是否有分支

Isbranch(s,n,i){

If(s[i].start==s[num].start&&s[i].end!=s[num].end);

如果存在分支的话,还需要进行起始节点和分支节点的判断,如果该节点为起始节点,则进行下面的处理:

If(s[i].start==“start”){

event[rows][0]=s[i].sevent+“”;

path[rows][1]=s[i].start+“->”+s[i].end;

如果判断为该节点为分支节点,则如下处理:

event[rows][0]=event[rows][0]+s[i].sevent+“”;

path[rows][1]=path[rows][1]+“->”+s[i].end;

3 基于贪心算法和回溯法的语句覆盖策略

在采用语句覆盖策略时,先通过贪心算法对进行第一次遍历,每个节点只遍历一次。如果节点为聚合节点或者分支节点的特殊情况下,可能会出现节点遍历遗漏的情况,这种情况下基于回溯法的思想,采用双向回溯,实现回溯功能。

对节点的上下遍历过程进行检查,如果该节点存在下一个未遍历过程则返回该节点在数组中的下标,则进行如下的处理:

isnext=Istrackingnext(s,n,finals);//测试是否存在下一个

未访问过的节点

intIstrackingnext(Swant s[],int n,String finals){

for(int j=0;j<n;j++){

if(s[j].state==1&&s[j].start==finals)

return j;

}}

当只存在下节点未遍历时,对下节点进行遍历,然后将结束节点标记置为下节点的结尾,并将下结点设置为已遍历访问。

If(isnext=!-1&&ispre==-1)//当只存在下节点时操作

getnxtevent=s [isnext].DateOfConditionOrPredicateAnd⁃Condition(s[isnext].sevent);

event[rows][0]=event[rows][0]+“”+getnxtdate[1];

path[rows][1]=path[rows][1]+“->”+s[isnext].end;

finals=s[isnext].end;//将结束节点标记置为下节点的末尾

s[isnext].state=0;//下节点置已访问标记

如果该节点存在上一个未遍历的过程则进行如下处理:

ispre=Istrackingpre(s,n,begin);//测试是否存在上一个未访问过的节点

int Istrackingpre(Swant s[],int n,String begin){

for(int j=0;j<n;j++){

if(s[j].state==1&&s[j].end==begin)

return j;

}}

当存在上节点未遍历时,对上节点进行遍历,然后将开始节点标记置为上节点的开头,并将上节点设置为已遍历访问。

If(isnext==-1&&ispre!=-1)//当只存在上节点时操作

getpreevent=s [ispre].DateOfConditionOrPredicateAnd⁃Condition(s[ispre].sevent);

event[rows][0]=getpreevent[1]+“ ”+event[rows][0];

path[rows][1]=s[ispre].start+“->”+path[rows][1];

begin=s[ispre].start;//将开始节点标记置为上节点的开头

s[ispre].start=0;//上节点置已访问标记

如果上下节点都存在未访问的情况,将开始节点标记设置为上节点的开头,结束节点标记设置为下节点的末尾,并将上下节点设置为已遍历访问。

if(isnext!=-1&&ispre!=-1)//上下节点都存在时进行的操作

getpreevent=s [ispre].DateOfConditionOrPredicateAnd⁃Condition(s[ispre].sevent);

getnxtevent=s [isnext].DateOfConditionOrPredicateAnd⁃Condition(s[isnext].sevent);

event[rows][0]=getpreevent[1]+“”+event[rows][0]+“”+getnxtevent[1];

path[rows][1]=s[ispre].start+“->”+path[rows][1]+“->”+s[isnext].end;

begin=s[ispre].start;//将开始节点标记置为上节点的开头

finals=s[isnext].end;//将结束节点标记置为下节点的末尾

s[ispre].state=0;//上节点置已访问标记

s[isnext].state=0;//下节点置已访问标记}

4 结语

软件测试是为了发现软件开发的错误,测试用例的自动生成对于整个软件开发的效率和软件质量有着巨大的促进作用。UML状态图能够通过描述对象的状态变化,提供对象在整个生命周期中的详细状态信息。本文研究了基于UML状态图实现测试用例的生成,主要介绍了两种生成策略,将白盒测试技术中的路径覆盖以及语句覆盖和UML状态图相结合,以此实现测试用例的自动生成。今后可能还会尝试基于UML中其他如类图,活动图等实现测试用例的生成进行更多研究探讨。

猜你喜欢
测试用例软件测试对象
软件测试方向人才培养“1+X”融合研究
晒晒全国优秀县委书记拟推荐对象
基于LDA模型的测试用例复用方法*
航天软件测试模型构建与应用
基于路径关键状态变量的测试用例约简
攻略对象的心思好难猜
图说车事
关于 Web 应用系统的软件测试的研究
软件测试中的测试用例及复用研究
软件测试发展现状及前景的探讨