(2) 对测试用例进行优化设计;
背景知识
结构性测试是知道产品内部工作过程,检测产品内部动作是否按照规格说明书的规定正常进行。结构性测试允许测试人员利用程序内部的逻辑结构及有关信息,设计或选择测试用例,对程序所有逻辑路径进行测试。通过在不同点检查程序的状态,确定实际的状态是否与预期的状态一致。
一、 逻辑覆盖
结构性测试力求提高测试覆盖率。逻辑覆盖是对一系列测试过程的总称,它是在使用白盒测试法时,选用测试用例执行程序逻辑路径的方法。
逻辑覆盖按覆盖程度由低到高大致分为以下几类:
(1) 语句覆盖:设计若干测试用例,使程序中每一可执行语句至少执行一次; (2) 判断覆盖:设计用例,使程序中的每个逻辑判断的取真取假分支至少经历一
次;
(3) 条件覆盖:设计用例,使判断中的每个条件的可能取值至少满足一次; (4) 判断/条件覆盖:设计用例,使得判断中的每个条件的所有可能结果至少出现
一次,而且判断本身所有可能结果也至少出现一次;
(5) 条件组合覆盖。设计用例,使得每个判断表达式中条件的各种可能组合都至
少出现一次;显然,满足⑤的测试用例也一定是满足②、③、④的测试用例。
(6) 路径覆盖。设计足够的测试用例,使程序的每条可能路径都至少执行一次。 如果把路径覆盖和条件组合覆盖结合起来,可以设计出检错能力更强的测试数据用例。
二、 基本路径测试
如果把覆盖的路径数压缩到一定限度内,例如,程序中的循环体只执行零次和一次,就成为基本路径测试。它是在程序控制流图的基础上,通过分析控制构造的环路复杂性,
导出基本可执行路径集合,从而设计测试用例的方法。
设计出的测试用例要保证在测试中,程序的每一个可执行语句至少要执行一次。 ① 程序的控制流图
控制流图是描述程序控制流的一种图示方法。基本控制构造的图形符号如图所示。符号○称为控制流图的一个结点,一组顺序处理框可以映射为一个单一的结点。控制流图中的箭头称为边,它表示了控制流的方向,在选择或多分支结构中分支的汇聚处,即使没有执行语句也应该有一个汇聚结点。边和结点圈定的区域叫做区域,当对区域计数时,图形外的区域也应记为一个区域。
图3-.1 控制流图的各种图形符号
如果判定中的条件表达式是复合条件时,即条件表达式是由一个或多个逻辑运算符(OR,AND,NAND,NOR)连接的逻辑表达式,则需要改复合条件的判定为一系列只有单个条件的嵌套的判定。例如对应图3-2. (a) 的复合条件的判定,应该画成如图3-2. (b) 所示的控制流图。 条件语句 if a OR b 中条件a和条件b各有一个只有单个条件的判定结点。
图3-2 复合逻辑下的控制流图
② 计算程序环路复杂性
进行程序的基本路径测试时,程序的环路复杂性给出了程序基本路径集合中的独立路径条数,这是确保程序中每个可执行语句至少执行一次所必需的测试用例数目的上界。
所谓独立路径,是指包括一组以前没有处理的语句或条件的一条路径。如在图3-3(b)所示的控制流图中,一组独立的路径是:
path1:1 - 11
path2:1 - 2 - 3 - 4 - 5 - 10 - 1 - 11 path3:1 - 2 - 3 - 6 - 8 - 9 - 10 - 1 - 11 path4:1 - 2 - 3 - 6 - 7 - 9 - 10 - 1 - 11
路径path1,path2,path3,path4组成了图3-3 (b) 所示控制流图的一个基本路径集。只要设计出的测试用例能够确保这些基本路径的执行,就可以使得程序中的每个可执行语句至少执行一次,每个条件的取真分支和取假分支也能得到测试。基本路径集不是唯一的,对于给定的控制流图,可以得到不同的基本路径集。
(a) 程序流程图 (b) 控制流图
图3-3 程序流程图与对应的控制流图
通常环路复杂性可用以下三种方法求得。 ? 将环路复杂性定义为控制流图中的区域数。
? 设E为控制流图的边数,N为图的结点数,则定义环路复杂性为 V(G)=E-N+2。
? 若设P为控制流图中的判定结点数,则有 V(G)=P+1。
因为图5.14(b)所示控制流图有4个区域。其环路复杂性为4。 它是构成基本路径集的独立路径数的上界。可以据此得到应该设计的测试用例的数目。
③ 导出测试用例
利用逻辑覆盖方法生成测试用例,确保基本路径集中每条路径的执行。
3.2.1 实验设备
主流PC机一套,要求安装windows操作系统、Visual C++开发工具和OFFICE工具;
3.2.2 实验内容
题目一:使用逻辑覆盖测试方法测试以下程序段
void DoWork (int x,int y,int z) { 1 2 3
int k=0, j=0; if ( (x>3)&&(z<10) ) {
4 k=x*y-1; 5 j=sqrt(k); 6 }
7 if((x==4)||(y>5)) 8 j=x*y+10; 9 j=j%3; 10 }
说明:程序段中每行开头的数字(1~10)是对每条语句的编号。 (1)画出程序的控制流图(用题中给出的语句编号表示)。
(2)分别以语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、组合覆盖和路径覆盖方法设计测试用例,并写出每个测试用例的执行路径(用题中给出的语句编号表示)。
题目二:三角形问题
在三角形计算中,要求输入三角型的三个边长:A、B 和C。当三边不可能构成三角形时提示错误,可构成三角形时计算三角形周长。若是等腰三角形打印“等腰三角形”,若是等边三角形,则提示“等边三角形”。画出程序流程图、控制流程图、计算圈复杂度V(g),找出基本测试路径。
题目三:计算生日是星期几
已知公元1年1月1日是星期一。编写一个程序,只要输入年月日,就能回答那天是星期几。应用逻辑覆盖方法和基路径测试方法为上面的问题设计测试用例。
题目四:选择排序
下面是选择排序的程序,其中datalist是数据表,它有两个数据成员:一是元素类型为Element的数组V,另一个是数组大小n。算法中用到两个操作,一是取某数组元素V[i]的关键码操作getKey ( ),一是交换两数组元素内容的操作Swap( ):: 象
for ( int j = i+1; j < list.n; j++)
if ( list.V[j].getKey ( ) < list.V[k].getKey ( ) ) k = j;//当前具最小关键码的对象 if ( k != i ) Swap ( list.V[i], list.V[k] );
//交换
void SelectSort ( datalist & list ) {
/对表list.V[0]到list.V[n-1]进行排序, n是表当前长度。 for ( int i = 0; i < list.n-1; i++ ) {
int k = i;
//在list.V[i].key到list.V[n-1].key中找具有最小关键码的对
} }
(1) 试计算此程序段的McCabe复杂性;