第 章 白盒测试 学习目的与要求 本章介绍白盒测试的基本概念和类型,白盒测试主要分 为控制流测试和数据流测试。其中较常用到的是控制流测试 中的相关覆盖准则。通过本章的学习,能够对白盒测试有深 入的理解和体会。本章要求重点掌握相关覆盖准则的具体 应用。 本章主要内容 ● 白盒测试的概念。 ● 控制流测试、数据流测试。 ● 测试覆盖率。 ● 语句覆盖。 ● 判定覆盖。 ● 条件覆盖 。 判定/条件覆盖 。 ● ● 条件组合覆盖。 ● 路径覆盖。 ● 白盒测试工具。 5.白盒测试的概念 1 白盒测试作为测试人员常用的一种测试方法,越来越受 到测试工程师的重视。白盒测试并不是简单地按照代码设计 用例进行测试,而是需要根据不同的测试需求,结合不同的测 试对象,使用适合的方法进行测试。因为对于不同复杂度的 代码逻辑,可以衍生出许多种执行路径,只有适当的测试方 法,才能帮助我们从代码的迷雾森林中找到正确的方向。 白盒测试也称为结构化测试、基于代码的测试,是一种测 试用例设计方法。白盒测试从程序的控制结构导出测试用 第 5 章白盒测试 例,是针对被测单元内部如何进行工作的测试。它根据程序的控制结构设计测试用例,主要用 于软件或程序验证。 白盒测试与程序内部结构相关,需要利用程序结构的实现细节等知识,才能有效进行测试 用例的设计工作。白盒测试方法有程序控制流测试、数据流测试、逻辑驱动测试、域测试、符号 测试、路径测试、程序插桩及程序变异等,本章重点介绍前两 种白盒测试方法。 白盒测试把测试对象看作一个透明的盒子,如图5-1所 示,所以又称玻璃盒测试。它允许测试人员利用程序内部的 逻辑结构及有关信息,设计或选择测试用例,对程序所有逻 辑路径进行测试,通过在不同点检查程序的状态,确定实际 的状态是否与预期的状态一致。 白盒测试检查程序内部逻辑结构,对所有逻辑路径进行图5-1 白盒测试示意图 测试,是一种穷举路径的测试方法。但即使每条路径都测试 过了,仍然可能存在错误。这是因为:①穷举路径测试无法检查出程序本身是否违反了设计 规范,即程序是否是一个错误的程序;②穷举路径测试不可能查出程序因为遗漏路径而出现 的错误;③穷举路径测试发现不了一些与数据相关的错误。 ( 采用白盒测试方法必须遵循以下几条原则,才能达到测试的目的 。 1)保证一个模块中的所有独立路径至少被测试一次 。 tua两种情况 。 (2)所有逻辑值均需测试真(re)和假(flse) (3)检查程序的内部数据结构,保证其结构的有效性。 (4)在上下边界及可操作范围内运行所有循环。 5.1 控制流测试 1. 由于非结构化程序会给测试带来许多不必要的困难,所以业界要求写出的程序具有良好 的结构。自20 世纪70 年代以来,结构化程序的概念逐渐被人们接受。体现这一要求对某些 语言并不困难,例如Pascal、C语言,因为它们都具有反映基本控制结构的控制语句。但对于 有些开发语言要做到这一点并不容易,程序人员需要注意程序结构化的要求,例如汇编语言, 若使用汇编语言编写程序,开发人员尤其要注意程序的结构化要求。 1. 控制流的基本概念 在进一步介绍控制流测试方法之前,先来回顾图论的相关概念术语 。 1( 定义5.图) 图(又称线性图)是一种由两个集合定义的抽象数学结构,即一个节点集合 和一个构成节点之间连接的边集合。图G= 由节点的有限(并且非空)集合V和节 点无序对偶集合E组成,即由V={n1,n2,…,n}和E={e1,e2,…,ep}组成。其中,每条边 ek={ni,nj},ni,nj∈V 。{ni,nj}是一个无序对偶,有(m) 时记作(ni,nj)。 如图5-2所示图例,节点集合为V={n1,n2,n3,n4,n5,n6,n7}, 边集合为E={e1,e2,e3, e4,e5}={(n1,n2),(n1,n4),(n3,n4),(n2,n5),(n4,n)}。 可以把节点看作程序语句,边表示控制流或定义/(6) 使用关系。 定义5.节点的度) 节点的度是以该节点作为端点的边的条数。节点n的度记作 g(n)。 2( de 可以说,节点的度表示它在图中的“流行程度”。如果图中的节点表示对象,边表示消息, 软件测试技术与项目案例教程 则节点(对象)的度表示适合该对象的集成测试范围。 图5-2中节点的度:deg(n1)=2,deg(n2)=2,deg(n3)=1,deg(n4)=3,deg(n5)=1, deg(n6)=1,deg(n7)=0。 定义5.关联矩阵) 拥有m个节点和n条边的图 3( G= 的关联矩阵是一种m×n 矩阵,其中第i 行 第j列的元素是1,当且仅当节点i是边j的一个端点, 否 则元素是0 。 关联矩阵是对称的,行的和即该节点的度 。 定义5.相邻矩阵) 拥有m个节点和n条边的 图 4( G= 的相邻矩阵是一种m×m 矩阵,其中第i 行 第j列的元素是1,当且仅当节点i和节点j之间存在一 条 边,否则元素是0 。 相邻矩阵是对称的,行的和即该节点的度。 图5-2 图例示意图 定义5.路径) 对于序列中的 5( 路径是一系列的边 , 任何相邻边对偶ei,ej,边都拥有相同的(节点)端点。图5-2中的一些路径如下 。 路径节点序列边序列 n1 和n5 n1,n2,n5 e1,e4 n6 和n5 n6,n4,n1,n2,n5 e5,e2,e1,e4 定义5.6(连接性) 节点ni和nj是被连接的,当且仅当它们都在同一条路径上。 “连接性”是一种图的节点集合上的等价关系。 (1)连接性是自反的。 (2)连接性是对称的。 (3)连接性是传递的。 图的组件是相连节点的最大集合。例如,图5-2中有两个组件:{n1,n2,n3,n4,n5,n6} 和{n7}。 定义5.7(圈数) 图G的圈数由V(G)=e-n+p给出。其中,e是G中的边数,n是G中 的节点数,p是G中的组件数,V(G)是图中不同区域的个数。 定义5.8(有向图) 有向图(又称框图)D=(V,E)包 含:一个节点的有限集合V={n1,n2,…,nm}, 一个边的 集合E={e1,e2,…,ep}, 其中每条ek=是节点 ∈V 的一个有序对偶。 对于有向图,边有了方向含义,在符号上,无序对偶 (ni,nj)变成有序对偶,我们说有向边从节点ni 到nj,而不是在节点之间。 有向图如图5-3所示,节点集合为V={n1,n2,n3, n4,n5,n6,n7}, 边集合为E={e1,e2,e3,e4,e5}={,,,,}。 图5-3 有向图示意图 定义5.9(内度与外度) 有向图中节点的内度,是将 第5章 白盒测试 该节点作为终止节点的不同边的条数,记为indeg(n); 有向图中节点的外度,是将该节点作为 开始节点的不同边的条数,记为outdeg(n)。 -ndeg(n1)=outdeg(n1)=indeg(n2)= 如在图53中节点具有以下内度和外度:i0,2;1, outdeg(n2)=1。 一般图和有向图存在某种联系,例如有deg(n)=indeg(n)+outdeg(n)。 定义5.节点的类型:①内度为0的节点是源节点;②外度为0的节点是吸收节点; 10 ③内度不为0且外度不为0的节点是传递节点。 源节点和吸收节点构成图的外部边界。既是源节点又是吸收节点的节点是孤立节点。 在图5-3中,n1、n3 和n7 是源节点,n5、n6 和n7 是吸收节点,n2 和n4 是传递节点,n7 是孤 立节点。 11( 定义5.有向图的相邻矩阵) 有m个节点和n条边的图D= 的相邻矩阵是 一种m×m 矩阵,A=(aij), 其中aij=1,当且仅当从节点i到节点j之间有一条边,否则该元素 是0。 图5-3所示的有向图的相邻矩阵如下所示。 n1 n2 n3 n4 n5 n6 n7 n1 0 1 0 1 0 0 0 n2 0 0 0 0 1 0 0 n3 0 0 0 1 0 0 0 n4 0 0 0 0 0 1 0 n5 0 0 0 0 0 0 0 n6 0 0 0 0 0 0 0 n7 0 0 0 0 0 0 0 定义5.12(路径与半路径)( 有向) 路径是一系列边,使得第一条边的终止节点是第二条 边的初始节点。 环路是一个在同一个节点上开始和结束的有向路径。 半路径是一系列边,使得对于该序列中至少有一对相邻边对偶来说,第一条边的 初始节点是第二条边的初始节点,或第一条边的终止节点是第二条边的终止节点。 在图5-3中,从n1 到n6 存在一条路径,n1 和n3 之间有一条半路径。 定义5.13(n-连接性) 有向图中的两个节点ni和nj是: 0连接,当且仅当ni和nj之间没有路径。 1连接,当且仅当ni和nj之间有一条半路径,但是没有路径。 2连接,当且仅当ni和n之间有一条路径。 3连接,当且仅当ni和nj 之间有一条路径,并且n和ni之间有一条路径。 jj 定义5.可到达性矩阵) 有m个节点和n条边的图D= 的相邻矩阵是一种 14( m×m 矩阵,R=(rj), 其中ri1,当且仅当从节点i到节点j之间有一条路径,否则该元素 ij= 是0。 定义5.环形复杂度,也称为圈复杂度,是一种为程序逻辑复杂度提供定量尺度的软件 15 度量。 软件测试技术与项目案例教程 可以将环形复杂度用于基本路径方法,它可以提供程序基本集的独立路径数量,确保所有 语句至少执行一次测试数量的上界。 独立路径是指程序中至少引入了一个新的处理语句集合或一个新条件的程序通路。采用 流图的术语,独立路径必须至少包含一条在本次定义路径之前不曾用过的边。 测试可以被设计成基本路径集的执行过程,但基本路径集通常并不唯一。 环形复杂度以图论为基础,为我们提供了非常有用的软件度量。可用如下方法来计算环 形复杂度。 (1)控制流图中区域的数量对应于环形复杂度。 (2)给定控制流图G的环形复杂度V(G)定义为V(G)=E-N+2 。其中,E是控制流图 中边的数量,N是控制流图中的节点数量。 (3)给定控制流图G的环形复杂度V(G)也可定义为V(G)=P+1 。其中,P是控制流图 G中判定节点的数量。 定义5.16(图矩阵) 图矩阵是控制流图的矩阵表示形式。 图矩阵是一个方形矩阵,其维数等于控制流图的节点数。矩阵中的每列和每行都对应于 标识的节点,矩阵元素对应于节点间的边。 通常,控制流图中的节点用数字标识,边则用字母标识。如果在控制流图中从第i个节点 到第j个节点有一个标识为x的边相连接,则在对应图矩阵的第i行第j列有一个非空的元 素x。 2. 程序的控制流图 程序流程图又称框图,是人们最熟悉也最容易理解的一种程序控制结构的图形表示。常 见结构的控制流图如图5-4所示。在这种图上的框里面常常标明了处理要求或条件,但是,这 些标注在进行路径分析时是不重要的。为了更加突出控制流的结构,需要对程序流程图做一 些简化。图5-5给出了简化的例子。其中图5-5(a)是一个含有两个出口判断和循环的程序流 程图,我们把它简化成图5-5(b)的形式,这种简化了的程序流程图称为控制流图。其中,包含 条件的节点称为判定节点(又称谓词节点), 由判定节点发出的边必须终止于某一个节点,由边 和节点所限定的范围称为区域。 图5-4 常见结构的控制流图 可以观察到,在控制流图中只有节点和控制线(弧)两种图形符号。 (1)节点:以标有编号的圆圈表示。它代表了程序流程图中矩形框表示的处理、菱形表 示的两个到多个出口判断,以及两条到多条流线相交的汇合点。 (2)控制流线(弧): 以箭头表示。它与程序流程图中的流线是一致的,表明了控制的顺 序。为了方便讨论,线通常标有名字,如a、b、c等。 为了使控制流图在机器上表示,可以把它表示成矩阵的形式,称为控制流图矩阵。图5-6 第 5 章 白盒测试 99 表示了图5-5的控制流图矩阵,这个矩阵有5行5列,是由该控制图中5个节点决定的。矩阵 中6个元素a、b、c、d、e和f的位置决定了它们所连接节点的号码。例如,弧d在矩阵中处于 第3行第4列,那是因为它在控制流图中连接了节点3至节点4。这里必须注意方向,图中节 点4到节点3没有弧,所以矩阵中第4行第3列也就没有元素。 图5-5 程序流程图和控制流图 图5-6 控制流图矩阵 图5-7 三角形伪代码映射 成的控制流图 除了程序流程图可以转换成控制流图以外,还可以把伪代码表示的处理过程转换成控制 流图。根据程序建构控制流图很容易,如图5-7所示,把三角形伪代码实现过程转换成了控制 流图。对于不可执行语句我们不把它映射成节点,比如变量和类型说明语句。 (1) //Program triangle2 version of simple (2) int a,b,c; (3) boolean IsATriangle; (4) cout<<"Enter 3 integers which are sides of a triangle"; (5) cin>>a>>b>>c; (6) cout<<"Side A is"<0 and b>0) c=c/a; if(a>1 or c>1) c=c+1; c=b+c 上面程序的流程如图5-11所示。 图5-11 例5-1 的程序流程图和模板 由图5-11(b)可以看出,该程序模块有4条不同的路径:①P1:(1-2-4);②P2:(1-2-5); ③P3:(1-3-4);④P4:(1-3-5)。 将里面的判定条件和过程记录为:条件M={a>0andb>0};条件N={a>1orc>1}。 这样,程序的4条不同路径可以表示为:①P1:(1-2-4)=MandN;②P2:(1-2-5)=~M andN;③P3:(1-3-4)=Mand~N;④P4:(1-3-5)=~Mand~N。 语句覆盖的基本思想:设计若干测试用例,运行被测程序,使程序中每个可执行语句至少 执行一次。 看到上面的例题,P1包含了所有可执行语句,按照语句覆盖的测试用例设计原则,可以使 用P1来设计测试用例,例如: 令a=2,b=1,c=6,此时满足条件M{a>0andb>0}和条件N={a>1orc>1}(注:此 时c=c/a=3),这样,测试用例的输入{a=2,b=1,c=6}和对应的输出{a=2,b=1,c=5}覆盖 路径P1。 语句覆盖的优点:可以很直观地从源代码得到测试用例,无须细分每条判定表达式。 语句覆盖的缺点:由于这种测试方法仅仅针对程序逻辑中显式存在的语句,但对于隐藏 的条件和可能到达的隐式逻辑分支是无法测试的。例如,在Do-While结构中,语句覆盖执行 其中某一个条件分支。显然,语句覆盖对于多分支的逻辑运算也是无法全面反映的,它只运行 一次,而不考虑其他情况。