背景技术
随着现代软件系统日益复杂庞大,软件质量问题已经严重制约了计算机技术的发展。软件测试是保证软件质量和可靠性的主要手段,也是软件工程实施过程中必要的步骤之一。测试数据的生成是软件测试的重要内容,程序在测试数据上执行以发现软件中存在的错误缺陷,是软件测试领域的基本方法。
由于不可能穷举软件系统的所有程序路径,传统的完全测试(thorough testing)技术在实际上往往是不可行的。因此,结构化的测试技术逐渐被人们所提出,结构测试是一种按照程序内部逻辑结构和编码结构设计测试数据的测试方法。覆盖率分析技术就是一种结构化的测试技术,目前已经成为了一种非常重要的软件质量评估方法。常用的两种覆盖率分析技术为语句覆盖和分支覆盖。
目前,测试人员普遍采用手工方法设计测试数据,但是,手工生成测试数据的效率极其低下,并且容易出错。尤其是为某些条件要求苛刻的路径生成测试数据是很困难的,这使得测试成本昂贵,很难保证软件质量。测试数据自动生成技术能够自动生成对被测程序进行测试时所需的数据,这样不但减轻了测试人员所必须付出的大量劳动,同时降低了由手工测试而产生的高额成本,有效地大幅提高了测试过程的可信赖程度。
对于包含有复杂逻辑的安全攸关软件来说,结构化的测试技术只是考虑了程序的结构,往往是不够充分的。因此,许多更加复杂的逻辑覆盖准则被提出,包括条件覆盖准则(Condition Coverage,CC)、判定覆盖准则(Decision Coverage,DC)、条件/判定覆盖准则(Condition/Decision Coverage,C/DC)和多重条件覆盖准则(Multiple ConditionCoverage,MCC)。然而,在目前的软件测试中,对于一些嵌入了复杂逻辑语句的程序,CC、DC、C/DC也是不够充分的,而MCC生成的测试数据数目会根据逻辑条件的数目呈现指数型增长,使得测试数据数量异常庞大。
为了权衡测试的精确性与测试数据数目,J.J.Chilenski和S.P.Miller于1994年提出了修订的条件/判定覆盖(Modified Condition/Decision Coverage,MC/DC)准则,旨在能够在生成测试数据时覆盖到程序中每一个独立的判定条件,MC/DC准则要求程序中的每个入口点和出口点至少唤醒一次,每个条件的所有可能结果至少出现一次,每个判定本身的所有结果也至少出现一次,并且判定中的每一个条件能够独立地影响判定的结果,即在其它条件不变的前提下仅改变这个条件的值就能使判定结果改变。MC/DC准则是一种实用的软件结构覆盖率测试准则,已被广泛地应用于软件验证和测试过程中。它是在C/DC的基础上发展起来的,但是它与C/DC存在着许多不同之处,具有更多的优点。例如,MC/DC测试用例的数量是线性增加的。我们更倾向于使用少量的测试数据满足覆盖准则,MC/DC准则显然是首选。另外,最近的实验结果显示,MC/DC准则有更好的检错能力,并且比其他覆盖准则更加高效。
近几年来,动态符号执行(Dynamic Symbolic Execution,DSE)方法在测试数据生成方面被广泛应用。MC/DC对于每一个判定条件都需要特定的组合值,但并不总是使被测程序能够执行一个新的分支。因此,现有的基于DSE的测试数据生成方法不能够达到MC/DC覆盖。为了解决这个问题,研究者提出了一种方法,将待测程序代码进行转换,以优化现有的基于语句覆盖和分支覆盖的软件测试数据生成方法,从而达到MC/DC覆盖。但是,他们并没有给出严格的转换规则,并且这些方法并不能够保证当测试数据集合对于转换后的程序的分支覆盖率达到100%时,测试数据对于待测程序的MC/DC覆盖率也达到100%。因此,本发明提出了一系列代码转换准则,来弥补先前方法中的缺陷。
发明内容
本发明的目的在于克服现有技术中存在的问题,提供一种基于代码转换的MC/DC覆盖准则的软件测试数据生成方法。该方法通过制定一系列代码转换规则,对待测程序的代码进行代码转换,将转换后的程序作为符号执行工具的输入程序,使得当测试数据集合对于待测程序的分支覆盖率达到100%时,测试数据对于待测程序的MC/DC覆盖率也能达到100%。
为了实现本发明的目的,采用的技术方案概述如下:
一种基于代码转换的MC/DC覆盖准则的软件测试数据生成方法,其输入为一段待测程序(软件),输出为满足MC/DC覆盖准则的软件测试数据集合,其特征在于包括以下步骤:
(1)定义待测程序的语句的类型;
(2)定义待测程序的语句的转换规则;
(3)根据步骤(1)中定义的语句类型,识别待测程序中每条语句的类型;
(4)根据步骤(3)中确定的待测程序中语句的类型,对每种类型的语句按照步骤(2)中定义的语句转换规则进行代码转换;
(5)将步骤(4)中得到的代码转换后的程序作为基于分支覆盖的软件测试数据生成工具的输入,得到测试数据集合。使得当测试数据集合对于代码转换后的程序T(S)的分支覆盖率达到100%时,测试数据集合对于待测程序S的MC/DC覆盖率为100%,从而达到MC/DC覆盖(Modified Condition/Decision Coverage,MC/DC,修订的条件/判定覆盖)。
所述步骤(1),具体包括以下步骤:
(1-1)定义待测程序的语句S的类型,语句S由如下语法规则构成,不包括函数调用;
语句S为变量声明Type id;
或赋值表达式x=a;
或空语句skip;
或顺序语句S1;S2;
或分支语句如果判断b为真(T),那么语句S1;
或分支语句如果判断b为真(T),那么语句S1;否则语句S2。
其中,a为算术表达式,b为判断,x为变量。
所述步骤(2),具体包括以下步骤:
(2-1)定义待测程序的语句S的转换规则如下;
其中,S表示待测程序中的语句,T(S)表示转换后的程序中相应的语句。a为算术表达式,x为变量。算术表达式a1是将算术表达式a中的变量x替换为变量x1得到的;算术表达式a2是将算术表达式a中的变量x替换为变量x2得到的;判断b1是将判断b中的变量x替换为变量x1得到的;判断b2是将判断b中的变量x替换为变量x2得到的;语句S11、S12表示将语句S1和S2中的变量y替换为变量y1,语句S21、S22表示将语句S1和S2中的变量y替换为变量y2;条件c1i是将条件ci中的变量x替换为变量x1得到的;条件c2i是将条件ci中的变量x替换为变量x2得到的;
转换规则1:
S为变量声明Type id;
T(S)为变量声明Type id1;Type id2;
转换规则2:
S为赋值表达式x=a;
T(S)为赋值表达式x1=a1;x2=a2;
转换规则3:
S为空语句skip;
T(S)为空语句skip;
转换规则4:
S为顺序语句S1;S2;
T(S)为顺序语句T(S1);T(S2);
转换规则5:
S为分支语句:
如果判断b为真(T)
语句S1;
T(S)为:
语句G(b);
如果判断b1为真(T)
如果判断b2为真(T)
转换语句S1到语句T(S1);
否则
语句S11;
否则
如果判断b2为真(T)
语句S21;
其中,语句G(b)为:
如果替换判断b中的条件c11为真(T)获得的判断不等于(!=)替换判断b中的条件c11为假(F)获得的判断为真(T)
如果条件c11不等于(!=)条件c21逻辑与(AND)条件c12等于(==)条件c22逻辑与(AND)…逻辑与(AND)条件c1n等于(==)条件c2n为真(T)
空语句skip;
如果替换判断b中的条件c1n为真(T)获得的判断不等于(!=)替换判断b中的条件c1n为假(F)获得的判断为真(T)
如果条件c11等于(==)条件c21逻辑与(AND)…逻辑与(AND)条件c1(n-1)等于(==)条件c2(n-1)逻辑与(AND)条件c1n不等于(!=)条件c2n为真(T)
空语句skip;
转换规则6:
S为分支语句:
如果判断b为真(T)
语句S1;
否则
语句S2;
T(S)为:
语句G(b);
如果判断b1为真(T)
如果判断b2为真(T)
转换语句S1到语句T(S1);
否则
S11S22;
否则
如果判断b2为真(T)
S21S12;
否则
转换语句S2到语句T(S2);
其中,语句G(b)为:
如果替换判断b中的条件c11为真(T)获得的判断不等于(!=)替换判断b中的条件c11为假(F)获得的判断为真(T)
如果条件c11不等于(!=)条件c21逻辑与(AND)条件c12等于(==)条件c22逻辑与(AND)…逻辑与(AND)条件c1n等于(==)条件c2n为真(T)
空语句skip;
如果替换判断b中的条件c1n为真(T)获得的判断不等于(!=)替换判断b中的条件c1n为假(F)获得的判断为真(T)
如果条件c11等于(==)条件c21逻辑与(AND)…逻辑与(AND)条件c1(n-1)等于(==)条件c2(n-1)逻辑与(AND)条件c1n不等于(!=)条件c2n为真(T)
空语句skip;
所述步骤(4),具体包括以下步骤:
(4-1)根据待测程序的语句的类型,找到符合转换规则1和转换规则2和转换规则3的所有语句,按照相对应的规则对这些语句进行代码转换,即将每条语句复制一份;
(4-2)根据待测程序的语句的类型,找到符合转换规则4和转换规则5和转换规则6的所有语句,标记所有的分支语句;
(4-3)如果当前语句不为分支语句,则按照转换规则4对待测程序进行代码转换;如果当前语句为分支语句,则分析此分支语句的嵌套逻辑关系,对于没有嵌套关系的分支语句,则按照转换规则5和转换规则6对待测程序进行代码转换。对于每一条分支语句,确定其判断逻辑表达式,明确其判断与条件,然后运用逐一替换该判断条件参数布尔值,并在分支语句的必要处添加分支的方法,对分支语句进行代码转换。对于有嵌套关系的分支语句,按照从内到外的顺序,处理每一个分支语句;
(4-4)重复步骤(4-3),直到处理完在步骤(4-2)中所有的语句为止;
与现有技术相比,本发明具有以下优点:
(1)本发明给出了严格的转换规则,使得代码转换方法更加明确。现有技术只是通过添加一系列的分支,试图覆盖判断中的每一个条件,但是却没有给出明确的转换规则来达到这一目的。
(2)本发明提出的基于代码转换的MC/DC覆盖准则的软件测试数据生成方法,能够保证当测试数据集合对于代码转换后的程序的分支覆盖率达到100%时,测试数据对于待测程序的MC/DC覆盖率也达到100%。现有的软件测试数据生成技术对于不同的测试输入,生成的测试数据是不同的,但是待测程序与代码转换后的程序在分支覆盖上达到MC/DC是不完全等价的,即代码转换后的程序的代码覆盖了所有分支,但是同等的测试数据不能够覆盖待测程序中代码的所有分支。
具体实施方式
下面介绍本说明书中用到的主要术语和符号:
(1)条件&判断
不含有逻辑操作符的布尔表达式,仅仅由关系操作符(小于<、大于>、等于==等)构成的表达式属于条件。
由条件及零个或多个逻辑操作符(逻辑与AND、逻辑或OR、逻辑非NOT、逻辑异或XOR等)组成的逻辑表达式属于判断。
(2)布尔值框架
逻辑表达式的布尔值框架是指一组纯布尔表达式,不包括算数操作和关系操作,是通过在该逻辑表达式中,用一个明确的布尔值分别替换每个关系表达式得到的。
(3)测试向量
程序在测试数据的基础上,评估每一个判断的所有条件的布尔取值,包括真(T)和假(F)。每一组布尔值对于每一个判断分别组成一组测试向量。
(4)MC/DC覆盖
令D(C1,C2,…,Cn)表示一个判断,其中Ci(1≤i≤n)表示条件。令BS(c1,c2,…,cn)为判断D的一组布尔值框架,其中ci(1≤i≤n)表示布尔值。令tv1=(v11,…,v1n)和tv2=(v21,…,v2n)表示判断D的两个测试向量,其中,值v11,…,v1n,v21,…,v2n为T或F。本发明定义方法fi(tv1,tv2),fi的值域为{T,F}。如果值
v1j⊙v2j=T(1≤j≤n且j≠i)
v1j⊕v2j=T(j=i)
同时成立,那么,方法fi(tv1,tv2)=T,否则,fi(tv1,tv2)=F。方法fi的实际意义是两个测试向量是否在第i个逻辑条件下取值不同。
两个测试向量tv1和tv2MC/DC覆盖条件Ci(1≤i≤n),当且仅当方法fi(tv1,tv2)和布尔值框架BS(v11,v12,…,v1n)⊕BS(v21,v22,…,v2n)同时成立。另外,本发明称这两个测试向量为条件Ci的一个MC/DC对。
因此,对每一个条件Ci,需找到一些测试数据,使得测试向量对于条件Ci组成一个MC/DC对,从而达到MC/DC覆盖准则。
本发明提出的一种基于代码转换的MC/DC覆盖准则的软件测试数据生成方法,能够将待测程序进行代码转换,使得转换后的程序分支覆盖率达到100%时,待测程序的MC/DC覆盖率也达到100%。
下面结合具体实施例对本发明提供的基于代码转换的MC/DC覆盖准则的软件测试数据生成方法进行详细描述。以一段简单的代码作为待测程序为例,说明本发明的工作流程,如下:
其中,example表示函数声明;bool和int表示类型;x,y,z,w表示变量;if和else表示分支语句的关键字;return表示返回语句的关键字。
变量声明:bool x,y,z;
函数声明:int example()
变量声明:int w;
分支语句:如果判断(x逻辑与(AND)(y逻辑或(OR)z))为真(T)
赋值表达式:w=0;
否则
赋值表达式:w=1;
C语言代码描述如下:
本发明的基于代码转换的MC/DC覆盖准则的软件测试数据生成方法的具体实施过程如下,如图1所示:
a)定义待测程序的语句的类型;
b)定义待测程序的语句的转换规则;
c)根据步骤a)中定义的语句类型,识别待测程序中每条语句的类型(依次为变量声明、变量声明、分支语句);
d)根据步骤c)中确定的待测程序中语句的类型,对每种类型的语句按照步骤b)中定义的语句转换规则进行代码转换;
e)将步骤d)中得到的代码转换后的程序作为基于分支覆盖的软件测试数据生成工具的输入,得到测试数据集合。使得当测试数据集合对于代码转换后的程序T(S)的分支覆盖率达到100%时,测试数据集合对于待测程序S的MC/DC覆盖率为100%,从而达到MC/DC覆盖;
其中,所述步骤d)具体实施过程如下,如图2所示:
d1)根据待测程序的语句的类型,找到符合转换规则1和转换规则2和转换规则3的所有语句,按照相对应的规则对这些语句进行代码转换,即将每条语句复制一份;
变量声明:bool x,y,z;转换为bool x1,y1,z1;bool x2,y2,z2;
变量声明:int w;转换为int w1;int w2;
赋值表达式:w=0;转换为w1=0;w2=0;
赋值表达式:w=1;转换为w1=1;w2=1;
d2)根据待测程序的语句的类型,找到符合转换规则4和转换规则5和转换规则6的所有语句,标记所有的分支语句;
顺序语句:变量声明:bool x,y,z;变量声明int w;
分支语句:如果判断(x逻辑与(AND)(y逻辑或(OR)z))为真(T)
赋值表达式:w=0;
否则
赋值表达式:w=1;
d3)当前语句不为分支语句,则按照转换规则4对待测程序进行代码转换;
顺序语句:变量声明:bool x,y,z;变量声明int w;
转换为顺序语句:
变量声明:bool x1,y1,z1;bool x2,y2,z2;
变量声明int w1;int w2;
d4)当前语句为分支语句,则分析此分支语句的嵌套逻辑关系,当前分支语句没有嵌套关系,则按照转换规则6对待测程序进行代码转换。对此分支语句,确定其判断逻辑表达式(x逻辑与(AND)(y逻辑或(OR)z)),明确其判断(x逻辑与(AND)(y逻辑或(OR)z))与条件(x,y,z),然后运用逐一替换该判断条件参数布尔值,并在分支语句的必要处添加分支的方法,对分支语句进行代码转换。如下:
分支语句:如果判断(x逻辑与(AND)(y逻辑或(OR)z))为真(T)
赋值表达式:w=0;
否则
赋值表达式:w=1;
转换为分支语句:
如果替换判断(x逻辑与(AND)(y逻辑或(OR)z))中的条件x为真(T)获得的判断不等于(!=)替换判断(x逻辑与(AND)(y逻辑或(OR)z))中的条件x为假(F)获得的判断为真(T)
如果条件x1不等于(!=)条件x2逻辑与(AND)条件y1等于(==)条件y2逻辑与(AND)条件z1等于(==)条件z2为真(T)
空语句skip
……
如果判断(x1逻辑与(AND)(y1逻辑或(OR)z1))为真(T)
如果判断(x2逻辑与(AND)(y2逻辑或(OR)z2))为真(T)
语句w1=0;w2=0;
否则
语句w1=0;w2=1;
否则
如果判断(x2逻辑与(AND)(y2逻辑或(OR)z2))为真(T)
语句w1=1;w2=0;
否则
语句w1=1;w2=1;
按照本发明的转换规则,将待测程序的代码转换后如下:
变量声明:bool x1,y1,z1;bool x2,y2,z2;
函数声明:int example()
变量声明:int w1;int w2;
分支语句:
如果判断(真(T)逻辑与(AND)(y1逻辑或(OR)z1))不等于(!=)判断(假(F)逻辑与(AND)(y1逻辑或(OR)z1))为真(T)
如果条件x1不等于(!=)条件x2逻辑与(AND)条件y1等于(==)条件y2逻辑与(AND)条件z1等于(==)条件z2为真(T)
空语句skip
……
如果判断(x1逻辑与(AND)(y1逻辑或(OR)z1))为真(T)
如果判断(x2逻辑与(AND)(y2逻辑或(OR)z2))为真(T)
赋值表达式:w1=0;w2=0;
否则
赋值表达式:w1=0;w2=1;
否则
如果判断(x2逻辑与(AND)(y2逻辑或(OR)z2))为真(T)
赋值表达式:w1=1;w2=0;
否则
赋值表达式:w1=1;w2=1;
C语言代码描述如下:
综上,本发明通过提出一种基于代码转换的MC/DC覆盖准则的软件测试数据生成的方法,能够将待测程序进行代码转换,使得转换后的程序的分支覆盖率达到100%时,待测程序的MC/DC覆盖率也达到100%。
上述仅以优选实施例对本发明进行说明,非因此即局限本发明的权利范围,因此,在不脱离本发明思想的情况下,凡运用本发明说明书及附图内容所为的等效变化,均理同包含于本发明的权利要求范围内。