一.简介
任何工程产品都可以使用白盒测试和黑盒测试两种方法进行测试
1.黑盒测试
黑盒测试:已知产品的功能设计规格和用户手册,可以进行测试证明每个功能是否实现,每个实现了的功能是否符合要求,以及产品的性能是否满足用户的要求。
软件的黑盒测试意味着测试要在软件的接口处进行,测试人员完全不考虑程序内部的逻辑结构和内部特性,指依据程序的需求规格说明书和用户手册,检测程序的功能是否符合它的功能说明,以及性能是否满足用户的要求。因此黑盒测试又叫功能测试或者数据驱动测试。
(1)是否有不正确或遗漏的功能?
(2)在接口上,输入是否能正确的接收?能否输出正确的结果?
(3)是否有数据结构错误或外部信息(例如数据文件)访问错误?
(4)性能上是否能够满足要求?
(5)是否有初始化或终止性错误?
2.白盒测试
白盒测试:已知产品的内部工作过程,可以通过测试证明每种内部操作是否符合设计规格要求,所有内部成分是否已经检查过。
软件的白盒测试是对软件的过程性细节做细致的检查,它允许测试人员利用内部的逻辑结构及有关信息,设计或选择测试用例,对程序所有逻辑路径进行测试,通过在不同点检查程序状态,确定实际状态是否与预期的状态一致。因此白盒测试又称结构测试或逻辑驱动测试。
(1)保证一个模块中的所有独立路径至少使用一次;
(2)对所有逻辑值均测试true或false;
(3)在循环的边界和运行的界限内执行循环体;
(4)检查内部数据结构以确定其有效性。
二.测试技术详解
1.白盒测试技术
白盒测试对象基本上是源程序,是以程序的内部逻辑为基础的一种测试方法。
白盒测试方法又可分为静态测试和动态测试
静态测试是一种不通过执行程序而进行测试的技术,其关键功能是检查软件的表示和描述是否一致,没有冲突或者没有歧义。它瞄准的是纠正系统在描述,表示和规格上的错误,是任何进一步测试的前提。
动态测试需要软件的执行,当软件系统在模拟的或真实的环境中执行之前,之中和之后。对软件系统行为的分析是动态测试的主要特点,它显示了一个系统在检查状态下是正确还是不正确。
1.1静态测试
最常见的静态测试是找出源代码的语法错误,这类测试可由编译器来完成,因为编译器可以逐行分析检验程序的语法,找出错误并报告。除此之外,测试人员须采用人工方法来检验程序,有些地方存在非语法方面多的错误,只能通过人工检测的方式来判断。
人工检测的方法主要有代码检查法,静态结构分析法等。
<1>代码检查法
代码检查法 主要是通过桌面检查,代码审查和走查方式,对以下内容进行检查。
1.检查代码和设计的一致性;
2.代码的可读性以及对软件设计标准的遵循情况;
3.代码逻辑表达的正确性;
4.代码结构的合理性;
5.程序中不安全,不明确和模糊的部分;
6.编程风格方面的问题等。
桌面检查:桌面检查是一种传统的检查方法,由程序员检查自己编写的程序。程序员在程序通过编译之后对源程序进行分析,检测,并补充相关的文档,目的是发现程序中的错误。
代码审查:代码审查是由一组人通过阅读,讨论和争议对程序进行静态分析的过程,以小组会的方式进行。
代码走查:代码走查就是针对代码,在假想的输入情况下,逐行的浏览代码,走查代码找那个发现潜在的缺陷并记录结果的过程。
<2>静态结构分析法
在静态结构分析中,测试人员通常通过使用测试工具分析程序源码代码的系统结构,数据结构,数据接口,内部控制逻辑等内部 结构,生成函数调用关系图,模块控制流程图,内部文件调用关系图等各种图形,图表,清晰地标识整个软件的组织结构。
通过生成各种图表,来帮助对源程序的静态分析。
静态错误分析
常用的各种引用表主要有(5个):
- 标号交叉引用表:列出在各模块中出现的全部标号,并标出标号属性。
- 变量交叉引用表:变量定义与引用表。
- 子程序(宏,函数)引用表:列出各个子程序,宏和函数属性,参数表。
- 等价表:列出在等价语句或等值中出现的全局变量和标号。
- 常数表:列出全部数字常数和字符常数,并指出它们在哪些语句中首先被定义、
常用的各种关系图,控制流程主要有:
- 函数调用关系图:列出所有函数,用连线表示调用关系,通过每个应用程序各函数之间的调用关系展示系统结构。
- 模块控制流程图:由许多结点和连接结点的边组成的图形,其中每个结点代表一条或多条语句,边表示控制流向。可以直观地反应一个函数的内部结构。
静态错误分析主要用于确定在源程序中是否有某错误或者““危险””结构。
- 类型和单位分析(发现数据类型错误和单位的不一致。)
- 引用分析(变量在赋值前被引用,在赋值后未被引用,都是引用异常,需要检查程序的每条路径,采用深度优先遍历方法。)
- 表达式分析(表达式中错误,如不正确的使用括号,数组下标越界,除数为0,对负数开平方等。)
- 接口分析(模块间接口的一致性和模块与外部数据库的接口的一致性。)
1.2 程序插桩技术
程序插桩方法是借助往被测程序中插入操作,来实现测试目的的方法,即向源程序中添加一些语句,实现对程序语句的执行、变量的变化等情况进行检查。
想要了解一个程序在某次运行中所有可执行语句被覆盖的情况,或是每个语句的实际执行次数,最好的办法是利用插桩技术。
下面是一个插桩实例:
上图计算整数X和整数Y的最大公约数的程序流程图,其中虚线的部分就是插桩的地方。
设计插桩程序时需要考虑的问题(4个):
- 探测哪些信息;
- 在程序的什么部位设置探测点;
(1)程序块的第一个可执行语句之前
(2)for,do while等循环语句处
(3)if,else if等条件语句各分支处
(4)输入输出语句之后
(5)函数、过程、子程序调用语句之后
(6)return语句之后
(7)goto语句之后
3.需要设置多少个探测点;(一般情况下,在没有分支的程序段中只需一个计数语句,但如果程序中出现了多种控制结构,则要设计最少的计数语句完成相应的测试要求。)
4.程序中特定部位插入某些用以判断变量特性的语句。(这些判断变量特性的语句称为断言语句,通过断言语句的执行,使得程序的运行特性得到证实。)
1.3 逻辑覆盖
逻辑覆盖是以程序内部的逻辑结构为基础的测试技术,是通过对程序逻辑结构的遍历实现程序的覆盖,这一方法要求测试人员对程序的逻辑结构有清楚的了解。
从覆盖源程序语句的详细程度分析,逻辑覆盖标准有语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、条件组合覆盖。
示例程序一:
其流程图为:
实程程序二:
其流程图为:
<1>语句覆盖
语句覆盖使程序中每个语句至少都能被执行一次。
例如:
在程序1中,为使程序中每个语句至少执行一次,只需设计一个能通过路径a-c-e的数据就可以了,例如选择输入数据为:A=2,B=0,X=3就可达到“语句覆盖”标准。
在程序2中,如测试用例输入为:x=4、y=5、z=5 程序执行的路径是:a-b-d。
<2>判定覆盖
比语句覆盖稍强的覆盖标准是判定覆盖。按判定覆盖准则进行测试是指,设计若干测试用例,运行被测程序,使得程序中每个判断的取真分支和取假分支至少经历一次,即判断的真假值均曾被满足。判定覆盖又称为分支覆盖。
<3>条件覆盖
在设计程序中,一个判定语句是由多个条件组合而成的复合判定。
条件覆盖的含义是:构造一组测试用例,使得每一判定语句中每个逻辑条件的可能值至少满足一次。
<4>判定/条件覆盖
判定/条件覆盖的含义是:设计足够的测试用例,使得判定中每个条件的所有可能(真/假)至少出现一次,并且每个判定本身的判定结果(真/假)也至少出现一次。
<5>多条件覆盖
多条件覆盖也称为条件组合覆盖,它的含义是:设计足够的测试用例,使得每个判定中条件的各种可能组合都至少出现一次。显然满足多条件覆盖的测试用例是一定满足判定覆盖、条件覆盖和判定/条件覆盖的。
1.4基本路径测试法
前面的例子是个比较简单的程序段,只有两条路径。但在实际问题中,即使一个不太复杂的程序,其路径的组合都是一个庞大的数字。
基本路径测试法是在程序控制流图的基础上,通过分析控制构造的环路复杂性,导出基本可执行路径集合,从而设计测试用例的方法。
设计出的测试用例要保证在测试中程序的每一条可执行语句至少执行一次。
基本路径测试法的步骤:
- 画出程序控制流图
- 计算程序环路复杂性
- 确定独立路径集合
- 准备测试用例
<1>程序控制流图
控制流图是描述程序控制流的一种图示方式。其中基本的控制结构对应的图形符号如下图所示。图中的图形符号中,圆圈称为控制流图的一个结点,它表示一个或多个无分支的语句或源程序语句。
程序流程图中的一个顺序处理框序列和一个菱形判定框,可以映射成流图中的一个节点。在流图中一条边必须终止于一个节点,即使这个节点并不代表任何语句(实际上相当于一个空语句)。
边和节点围成的面积称为区域,但计算区域数时应该包括图外部未被包围的哪个区域。
下图是一个简单的流程图转换为控制流图的实例:
注意:控制流图的判定节点是左假右真。
<2>环路复杂性
进行程序的基本路径测试时,程序的环路复杂性给出了程序基本路径集合中的独立路径条数,这是确保程序中每个可执行语句至少执行一次所必须的测试用例数目的上界。
基本路径集不是惟一的,对于给定的控制流图,可以得到不同的基本路径集。
通常环路复杂性V(G)可用以下3种方法求得:
1.将环路复杂性定义为控制流图中的区域数。
2.设E为控制流图的边数,N为图的结点数,则定义环路的复杂性为V(G)=E−N+2。(最为简单)
3.若设P为控制流图中的判定结点数,则有V(G)=P+1。(最不易出错)
上图中边数为13,节点数为11。
第一种方法:4
第二种方法计算:13-11+2=4
第三种方法计算:3+1=4
1.5其他白盒测试方法
<1>域测试
域指程序的输入空间。
域错误:若程序的控制流有错误,对应某 一特定的输入可能执行的是一条错误路径,这种错误称为路径错误,也叫做域错误。
域测试主要是针对域错误进行的程序测试,是一种基于程序结构的测试方法。
缺点:
A.为进行与测试对程序提出的限制过多:
程序中不出现数组;
程序中不含与子函数或子例程;
程序中没有输入和输出错误;
程序的分支谓语是简单谓语,即不含有布尔运算符and和or;
程序分支谓语是线性的;
程序输入域是连续的而不是离散的;
相邻的两个域上计算是不相同的;
B.当程序存在很多路径时,存在的测试点也很多。
<2>符号测试
符号测试的基本思想是允许程序的输入不仅仅是具体的数值数据,而且包括符号值,这一方法也因此而得名。其测试步骤如下(5个)。
(1)利用符号执行解释器对被测程序进行符号执行;
(2)若是遇到程序不能继续执行的情况,要求用户干预,或是遍历各执行树的各分支路径;
(3)化简得到的路径条件式
(4)用解线性不等式的方法求解路径条件式,以求得满足各个限制谓语的测试数据;
(5)对程序进行测试,若上述不等式无解,则相应的路径不可执行。
遇到的测试问题:
(1)分支问题
分支条件是符号,无法确定分支的走向;
(2)二义性问题
由于符号不能代表确切旳值,经常会产生二义性问题;
(3)大程序问题
程序很复杂时,最终结果的表达式非常长,如果得不到简化,则测试时会占大量的时间和空间,或者问题解决不了。
<3>Z路径覆盖
指简化循环意义下的路径覆盖。无论循环的形式和实际执行循环体的次数是多少,只考虑循环一次或零次两种情况。