软件测试培训

随着信息技术的飞速发展,软件产品已经应用到社会的各个领域,软件产品的质量自然成为人们共同关注的焦点。

不论软件的生产者还是软件的使用者,均生存在竞争的环境中:

软件开发商为了占有市场,必须把产品质量作为企业的重要目标之一,以免在激烈的竞争中被淘汰出局。

用户为了保证自己业务的顺利完成,当然希望选用优质的软件。

软件带来错误的原因很多,具体地说,主要有如下几点:
交流不够、交流上有误解或者根本不进行交流

软件复杂性

程序设计错误

需求变化

时间压力

代码文档贫乏

软件开发工具

什么是软件测试
软件测试就是在软件投入运行前,对软件需求分析、设计规格说明和编码的最终复审,是软件质量保证的关键步骤。

软件测试定义:
软件测试是为了发现错误而执行程序的过程。或者说,软件测试是根据软件开发各阶段的规格说明和程序的内部结构而精心设计一批测试用例(即输入数据及其预期的输出结果),并利用这些测试用例去运行程序,以发现程序错误的过程。

软件测试的目的
基于不同的立场,存在着两种完全不同的测试目的。

从用户的角度出发,普遍希望通过软件测试暴露软件中隐藏的错误和缺陷,以考虑是否可接受该产品。

从软件开发者的角度出发,则希望测试成为表明软件产品中不存在错误的过程,验证该软件已正确地实现了用户的要求,确立人们对软件质量的信心。

Myers软件测试目的
(1)测试是程序的执行过程,目的在于发现错误;

(2)一个好的测试用例在于能发现至今未发现的错误;

(3)一个成功的测试是发现了至今未发现的错误的测试。

换言之,测试的目的是
想以最少的时间和人力,系统地找出软件中潜在的各种错误和缺陷。如果我们成功地实施了测试,我们就能够发现软件中的错误。

测试的附带收获是,它能够证明软件的功能和性能与需求说明相符合。

实施测试收集到的测试结果数据为可靠性分析提供了依据。

测试不能表明软件中不存在错误,它只能说明软件中存在错误。

软件测试的原则
1.应当把“尽早地和不断地进行软件测试”作为软件开发者的座右铭。

2.测试用例应由测试输入数据和对应的预期输出结果这两部分组成。

3.程序员应避免检查自己的程序。

4.在设计测试用例时,应包括合理的输入条件和不合理的输入条件。

5.充分注意测试中的群集现象。经验表明,测试后程序中残存的错误数目与该程序中已发现的错误数目成正比。

6.严格执行测试计划,排除测试的随意性。

7.应当对每一个测试结果做全面检查。

8.妥善保存测试计划,测试用例,出错统计和最终分析报告,为维护提供方便。

测试信息流
软件配置:软件需求规格说明、软件设计规格说明、源代码等;

测试配置:测试计划、测试用例、测试程序等;

测试工具:测试数据自动生成程序、静态分析程序、动态分析程序、测试结果分析程序、以及驱动测试的测试数据库等等。

测试结果分析:比较实测结果与预期结果,评价错误是否发生。
排错(调试):对已经发现的错误进行错误定位和确定出错性质,并改正这些错误,同时修改相关的文档。

修正后的文档再测试:直到通过测试为止。

通过收集和分析测试结果数据,对软件建立可靠性模型

利用可靠性分析,评价软件质量:

软件的质量和可靠性达到可以接受的程度;

所做的测试不足以发现严重的错误;

如果测试发现不了错误,可以肯定,测试配置考虑得不够细致充分,错误仍然潜伏在软件中。

V模型
每个开发活动都有右边的测试活动相对应。

软件开发过程是一个自顶向下,逐步细化的过程.

测试过程是依相反顺序安排的自底向上,逐步集成的过程。

W模型
软件测试并不等于程序测试。软件测试应贯穿于软件定义与开发的整个期间。

需求分析、概要设计、详细设计以及程序编码等各阶段所得到的文档,包括需求规格说明、概要设计规格说明、详细设计规格说明以及源程序,都应成为软件测试的对象。

开发生命周期

测试生命周期

测试计划(testplan)

定义测试项目的过程,以便测试项目能被正确的度量和控制。

包括测试需求,测试策略,测试资源和测试计划。

确定测试需求

评估风险

制定测试策略

确定资源

创建时间表

生成测试计划

确定测试需求

确定测试需求是测试计划活动的开始。测试需求确定测试对象以及测试工作的范围和作用。测试需求还用来确定整个测试工作(如安排时间表、测试设计等)并作为测试覆盖的基础。

被确定的测试需求项必须是可核实的。即,它们必须有一个可观察、可评测的结果。无法核实的需求不是测试需求。

评估风险
确定并验证风险因子

确定并验证实施概要因子

确定并验证测试优先级因子

制定测试策略
要使用的测试技术和工具;

测试完成标准;

影响资源分配的特殊考虑;如测试与外部接口或者模拟物理损坏、安全性威胁。

确定测试资源
人力资源

测试经理

测试工程师—设计与开发

测试工程师—执行

测试系统管理者

系统资源
硬件和软件环境

数据库服务器

测试设计

为每个工作版本确定可验证的测试用例集。

确定如何实现测试用例的测试过程。

确定并说明测试用例

确立并结构化测试过程

复审并评估测试覆盖

测试开发
创建可以重用的测试过程和测试用例

维护测试过程、测试用例与相关测试需求的一一对应

设立开发环境
建立测试过程和测试用例

建立外部数据集合

测试执行

运行与被测试应用的软件构造相对应的测试过程集,并记录结果日志,包括缺陷报告和测试日志。

执行测试过程

评估测试的执行情况

核实测试结果

恢复暂停的测试

测试评估

分析测试结果,确定是否测试标准被覆盖的过程.

分析测试结果并提交变更请求

评估基于需求的测试覆盖

评估基于代码的测试覆盖

分析缺陷

确定是否达到了测试的完成标准和成功标准

生成测试评估摘要

为把握软件开发各个环节的正确性,需要进行各种确认和验证工作。
验证(Verification),是保证软件正确地实现了某一功能的一系列活动。
确认(Validation),指的是保证软件的实现满足了用户需求的一系列活动.
验证:“我们是否正确地完成了产品?”
确认:“我们是否完成了正确的产品?”

软件测试方法
两种常用的测试方法

黑盒测试

白盒测试

黑盒测试
这种方法是把测试对象看做一个黑盒子,测试人员完全不考虑程序内部的逻辑结构和内部特性,只依据程序的需求规格说明书,检查程序的功能是否符合它的功能说明。

黑盒测试又叫做功能测试或数据驱动测试。

黑盒测试方法是在程序接口上进行测试,主要是为了发现以下错误:
是否有不正确或遗漏了的功能?

在接口上,输入能否正确地接受?能否输出正确的结果?

是否有数据结构错误或外部信息(例如数据文件)访问错误?

性能上是否能够满足要求?

是否有初始化或终止性错误?

用黑盒测试发现程序中的错误,必须在所有可能的输入条件和输出条件中确定测试数据,来检查程序是否都能产生正确的输出。

但这是不可能的。

假设一个程序P有输入量X和Y及输出量Z。在字长为32位的计算机上运行。若X、Y取整数,按黑盒方法进行穷举测试:
可能采用的
测试数据组:
232×232
=264

如果测试一组数据需要1毫秒,一年工作365×24小时,完成所有测试需5亿年。

白盒测试
此方法把测试对象看做一个透明的盒子,它允许测试人员利用程序内部的逻辑结构及有关信息,设计或选择测试用例,对程序所有逻辑路径进行测试。

通过在不同点检查程序的状态,确定实际的状态是否与预期的状态一致。因此白盒测试又称为结构测试或逻辑驱动测试。

软件人员使用白盒测试方法,主要想对程序模块进行如下的检查:

对程序模块的所有独立的执行路径至少测试一次;

对所有的逻辑判定,取“真”与取“假”的两种情况都至少测试一次;

在循环的边界和运行界限内执行循环体;

测试内部数据结构的有效性,等。

对一个具有多重选择和循环嵌套的程序,不同的路径数目可能是天文数字。给出一个小程序的流程图,它包括了一个执行20次的循环。

包含的不同执行路径数达520条,对每一条路径进行测试需要1毫秒,假定一年工作365×24小时,要想把所有路径测试完,需3170年。

语句覆盖
语句覆盖就是设计若干个测试用例,运行被测程序,使得每一可执行语句至少执行一次。

在图例中,正好所有的可执行语句都在路径L1上,所以选择路径L1设计测试用例,就可以覆盖所有的可执行语句。

测试用例的设计格式如下
【输入的(A,B,X),输出的(A,B,X)】
为图例设计满足语句覆盖的测试用例是:
【(2,0,4),(2,0,3)】

覆盖ace【L1】

判定覆盖
判定覆就是设计若干个测试用例,运行被测程序,使得程序中每个判断的取真分支和取假分支至少经历一次。

判定覆盖又称为分支覆盖。

对于图例,如果选择路径L1和L2,就可得满足要求的测试用例:

【(2,0,4),(2,0,3)】覆盖ace【L1】
【(1,1,1),(1,1,1)】覆盖abd【L2】

如果选择路径L3和L4,还可得另一组可用的测试用例:
【(2,1,1),(2,1,2)】覆盖abe【L3】【(3,0,3),(3,1,1)】覆盖acd【L4】

条件覆盖
条件覆盖就是设计若干个测试用例,运行被测程序,使得程序中每个判断的每个条件的可能取值至少执行一次。

在图例中,我们事先可对所有条件的取值加以标记。例如,

对于第一个判断:

条件A>1取真为,取假为
条件B=0取真为,取假为

对于第二个判断:
条件A=2取真为,取假为
条件X>1取真为,取假为

测试用例覆盖分支条件取值
【(2,0,4),(2,0,3)】L1(c,e)
【(1,0,1),(1,0,1)】L2(b,d)
【(2,1,1),(2,1,2)】L3(b,e)

测试用例覆盖分支条件取值
【(1,0,3),(1,0,4)】L3(b,e)
【(2,1,1),(2,1,2)】L3(b,e)

判定-条件覆盖
判定-条件覆盖就是设计足够的测试用例,使得判断中每个条件的所有可能取值至少执行一次,每个判断中的每个条件的可能取值至少执行一次。

测试用例覆盖分支条件取值
【(2,0,4),(2,0,3)】L1(c,e)
【(1,1,1),(1,1,1)】L2(b,d)

条件组合覆盖
条件组合覆盖就是设计足够的测试用例,运行被测程序,使得每个判断的所有可能的条件取值组合至少执行一次。
记①A>1,B=0作
②A>1,B≠0作
③A≯1,B=0作
④A≯1,B≠0作

⑤A=2,X>1作
⑥A=2,X≯1作
⑦A≠2,X>1作
⑧A≠2,X≯1作

测试用例覆盖条件覆盖组合
【(2,0,4),(2,0,3)】(L1)①,⑤
【(2,1,1),(2,1,2)】(L3)②,⑥
【(1,0,3),(1,0,4)】(L3)③,⑦
【(1,1,1),(1,1,1)】(L2)④,⑧

路径测试
路径测试就是设计足够的测试用例,覆盖程序中所有可能的路径。

测试用例通过路径覆盖条件
【(2,0,4),(2,0,3)】ace(L1)
【(1,1,1),(1,1,1)】abd(L2)
【(1,1,2),(1,1,3)】abe(L3)
【(3,0,3),(3,0,1)】acd(L4)

条件测试路径选择

当程序中判定多于一个时,形成的分支结构可以分为两类:嵌套型分支结构和连锁型分支结构。

对于嵌套型分支结构,若有n个判定语句,需要n+1个测试用例;

对于连锁型分支结构,若有n个判定语句,需要有2n个测试用例,覆盖它的2n条路径。

循环测试路径选择
循环分为4种不同类型:简单循环、连锁循环、嵌套循环和非结构循环。

(1)简单循环
①零次循环:从循环入口到出口

②一次循环:检查循环初始值

③二次循环:检查多次循环

④m次循环:检查在多次循环

⑤最大次数循环、比最大次数多一次、少一次的循环。

例:求最小值
k=i;
for(j=i+1;j<=n;j++)
if(A[j]<A[k])k=j;

测试用例选择
①对最内层循环做简单循环的全部测试。所有其它层的循环变量置为最小值;

②逐步外推,对其外面一层循环进行测试。测试时保持所有外层循环的循环变量取最小值,所有其它嵌套内层循环的循环变量取“典型”值。

③反复进行,直到所有各层循环测试完毕。

④对全部各层循环同时取最小循环次数,或者同时取最大循环次数

(3)连锁循环
如果各个循环互相独立,则可以用与简单循环相同的方法进行测试。但如果几个循环不是互相独立的,则需要使用测试嵌套循环的办法来处理。

(4)非结构循环
这一类循环应该使用结构化程序设计方法重新设计测试用例。

基本路径测试
基本路径测试方法把覆盖的路径数压缩到一定限度内,程序中的循环体最多只执行一次。

它是在程序控制流图的基础上,分析控制构造的环路复杂性,导出基本可执行路径集合,设计测试用例的方法。设计出的测试用例要保证在测试中,程序的每一个可执行语句至少要执行一次。

1.程序的控制流图
符号○为控制流图的一个结点,表示一个或多个无分支的PDL语句或源程序语句。箭头为边,表示控制流的方向。

在选择或多分支结构中,分支的汇聚处应有一个汇聚结点。

边和结点圈定的区域叫做区域,当对区域计数时,图形外的区域也应记为一个区域。

如果判断中的条件表达式是由一个或多个逻辑运算符(OR,AND,…)连接的复合条件表达式,则需改为一系列只有单个条件的嵌套的判断。

2.程序环路复杂性
程序的环路复杂性给出了程序基本路径集中的独立路径条数,这是确保程序中每个可执行语句至少执行一次所必需的测试用例数目的上界。

从控制流图来看,一条独立路径是至少包含有一条在其它独立路径中从未有过的边的路径。

例如,在图示的控制流图中,一组独立的路径是

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.导出测试用例
导出测试用例,确保基本路径集中的每一条路径的执行。

根据判断结点给出的条件,选择适当的数据以保证某一条路径可以被测试到—用逻辑覆盖方法。

每个测试用例执行之后,与预期结果进行比较。如果所有测试用例都执行完毕,则可以确信程序中所有的可执行语句至少被执行了一次。

必须注意,一些独立的路径(如例中的路径1),往往不是完全孤立的,有时它是程序正常的控制流的一部分,这时,这些路径的测试可以是另一条路径测试的一部分。

黑盒测试的测试用例设计

等价类划分

边界值分析

错误推测法

因果图

等价类划分

等价类划分是一种典型的黑盒测试方法,使用这一方法时,完全不考虑程序的内部结构,只依据程序的规格说明来设计测试用例。

等价类划分方法把所有可能的输入数据,即程序的输入域划分成若干部分,然后从每一部分中选取少数有代表性的数据做为测试用例。

使用这一方法设计测试用例要经历划分等价类(列出等价类表)和选取测试用例两步。

划分等价类

等价类是指某个输入域的子集合。在该子集合中,各个输入数据对于揭露程序中的错误都是等效的。测试某等价类的代表值就等价于对这一类其它值的测试。

等价类的划分有两种不同的情况:
①有效等价类:是指对于程序的规格说明来说,是合理的,有意义的输入数据构成的集合。
②无效等价类:是指对于程序的规格说明来说,是不合理的,无意义的输入数据构成的集合。

在设计测试用例时,要同时考虑有效等价类和无效等价类的设计。

划分等价类等价类的原则。
(1)如果输入条件规定了取值范围,或值的个数,则可以确立一个有效等价类和两个无效等价类。

例如,在程序的规格说明中,对输入条件有一句话:
“……项数可以从1到999……”
则有效等价类是“1≤项数≤999”
两个无效等价类是“项数<1”或“项
数>999”。在数轴上表示成:

(2)如果输入条件规定了输入值的集合,或者是规定了“必须如何”的条件,这时可确立一个有效等价类和一个无效等价类。
例如,在Pascal语言中对变量标识符规定为“以字母打头的……串”。那么所有以字母打头的构成有效等价类,而不在此集合内(不以字母打头)的归于无效等价类。

(3)如果输入条件是一个布尔量,则可以确定一个有效等价类和一个无效等价类。

(4)如果规定了输入数据的一组值,而且程序要对每个输入值分别进行处理。这时可为每一个输入值确立一个有效等价类,此外针对这组值确立一个无效等价类,它是所有不允许的输入值的集合。
例如,在教师上岗方案中规定对教授、副教授、讲师和助教分别计算分数,做相应的处理。因此可以确定4个有效等价类为教授、副教授、讲师和助教,一个无效等价类,它是所有不符合以上身分的人员的输入值的集合。

(5)如果规定了输入数据必须遵守的规则,则可以确立一个有效等价类(符合规则)和若干个无效等价类(从不同角度违反规则)。
例如,Pascal语言规定“一个语句必须以分号‘;’结束”。这时,可以确定一个有效等价类“以‘;’结束”,若干个无效等价类“以‘:’结束”、“以‘,’结束”、“以‘’结束”、“以LF结束”等。

确立测试用例
在确立了等价类之后,建立等价类表,列出所有划分出的等价类。

再从划分出的等价类中按以下原则选择测试用例:
(1)为每一个等价类规定一个唯一编号;

(2)设计一个新的测试用例,使其尽可能多地覆盖尚未被覆盖的有效等价类,重复这一步,直到所有的有效等价类都被覆盖为止;

(3)设计一个新的测试用例,使其仅覆盖一个尚未被覆盖的无效等价类,重复这一步,直到所有的无效等价类都被覆盖为止。

用等价类划分法设计测试用例的实例
在某一PASCAL语言版本中规定:“标识符是由字母开头,后跟字母或数字的任意组合构成。有效字符数为8个,最大字符数为80个。”

并且规定:“标识符必须先说明,再使用。”“在同一说明语句中,标识符至少必须有一个。”

用等价类划分方法,建立输入等价类表:

下面选取了9个测试用例,它们覆盖了所有的等价类。
①VARx,T1234567:REAL;
BEGINx:=3.414;
T1234567:=2.732;
……
(1),(2),(4),(8),(9),(12),(14)

②VAR:REAL;(3)

③VARx,:REAL;(5)

④VART12345678:REAL;(6)

⑤VART12345…:REAL;(7)
多于80个字符

⑥VART$:CHAR;(10)

⑦VARGOTO:INTEGER;(11)

⑧VAR2T:REAL;(13)

⑨VARPAR:REAL;(15)
BEGIN…
PAP:=SIN(3.14*0.8)/6;

边界值分析
边界值分析也是一种黑盒测试方法,是对等价类划分方法的补充。

人们从长期的测试工作经验得知,大量的错误是发生在输入或输出范围的边界上,而不是在输入范围的内部。因此针对各种边界情况设计测试用例,可以查出更多的错误。

比如,在做三角形计算时,要输入三角形的三个边长:A、B和C。我们应注意到这三个数值应当满足
A>0、B>0、C>0、

A+B>C、A+C>B、B+C>A,才能构成三角形。但如果把六个不等式中的任何一个大于号“>”错写成大于等于号“≥”,那就不能构成三角形。问题恰出现在容易被疏忽的边界附近。

这里所说的边界是指,相当于输入等价类和输出等价类而言,稍高于其边界值及稍低于其边界值的一些特定情况。

使用边界值分析方法设计测试用例,首先应确定边界情况。应当选取正好等于,刚刚大于,或刚刚小于边界的值做为测试数据,而不是选取等价类中的典型值或任意值做为测试数据。

错误推测法
人们也可以靠经验和直觉推测程序中可能存在的各种错误,从而有针对性地编写检查这些错误的例子。这就是错误推测法。

错误推测法的基本想法是:列举出程序中所有可能有的错误和容易发生错误的特殊情况,根据它们选择测试用例。

因果图

因果图的适用范围

如果在测试时必须考虑输入条件的各种组合,可使用一种适合于描述对于多种条件的组合,相应产生多个动作的形式来设计测试用例,这就需要利用因果图。

因果图方法最终生成的就是判定表。它适合于检查程序输入条件的各种组合情况。

(1)分析软件规格说明描述中,哪些是原因(即输入条件或输入条件的等价类),哪些是结果(即输出条件),并给每个原因和结果赋予一个标识符。

(2)分析软件规格说明描述中的语义,找出原因与结果之间,原因与原因之间对应的是什么关系?根据这些关系,画出因果图。

(3)由于语法或环境限制,有些原因与原因之间,原因与结果之间的组合情况不可能出现。为表明这些特殊情况,在因果图上用一些记号标明约束或限制条件。

(4)把因果图转换成判定表。

(5)把判定表的每一列拿出来作为依据,设计测试用例。

在因果图中出现的基本符号
通常在因果图中用Ci表示原因,用Ei表示结果,各结点表示状态,可取值“0”或“1”。“0”表示某状态不出现,“1”表示某状态出现。

主要的原因和结果之间的关系有:

表示约束条件的符号
为了表示原因与原因之间,结果与结果之间可能存在的约束条件,在因果图中可以附加一些表示约束条件的符号。

例如,有一个处理单价为5角钱的饮料的自动售货机软件测试用例的设计。其规格说明如下:

若投入5角钱或1元钱的硬币,押下〖橙汁〗或〖啤酒〗的按钮,则相应的饮料就送出来。若售货机没有零钱找,则一个显示〖零钱找完〗的红灯亮,这时在投入1元硬币并押下按钮后,饮料不送出来而且1元硬币也退出来;若有零钱找,则显示〖零钱找完〗的红灯灭,在送出饮料的同时退还5角硬币。”

(1)分析这一段说明,列出原因和结果
原因:1.售货机有零钱找
2.投入1元硬币
3.投入5角硬币
4.押下橙汁按钮
5.押下啤酒按钮

建立中间结点,表示处理中间状态
11.投入1元硬币且押下饮料按钮
12.押下〖橙汁〗或〖啤酒〗的按钮
13.应当找5角零钱并且售货机有零钱找
14.钱已付清

结果:21.售货机〖零钱找完〗灯亮
22.退还1元硬币
23.退还5角硬币
24.送出橙汁饮料
25.送出啤酒饮料

(2)画出因果图。所有原因结点列在左边,所有结果结点列在右边。

(3)由于2与3,4与5不能同时发生,

分别加上约束条件E。

(4)因果图

(5)转换成判定表

软件测试步骤
测试过程按4个步骤进行,即单元测试、集成测试、确认测试和系统测试及发版测试。

开始是单元测试,集中对用源代码实现的每一个程序单元进行测试,检查各个程序模块是否正确地实现了规定的功能。

集成测试把已测试过的模块组装起来,主要对与设计相关的软件体系结构的构造进行测试。

确认测试则是要检查已实现的软件是否满足了需求规格说明中确定了的各种需求,以及软件配置是否完全、正确。

系统测试把已经经过确认的软件纳入实际运行环境中,与其它系统成份组合在一起进行测试。

单元测试(UnitTesting)

单元测试又称模块测试,是针对软件设计的最小单位─程序模块,进行正确性检验的测试工作。其目的在于发现各模块内部可能存在的各种差错。

单元测试需要从程序的内部结构出发设计测试用例。多个模块可以平行地独立进行单元测试。

1.单元测试的内容
在单元测试时,测试者需要依据详细设计说明书和源程序清单,了解该模块的I/O条件和模块的逻辑结构,主要采用白盒测试的测试用例,辅之以黑盒测试的测试用例,使之对任何合理的输入和不合理的输入,都能鉴别和响应。

(1)模块接口测试
在单元测试的开始,应对通过被测模块的数据流进行测试。测试项目包括:

调用本模块的输入参数是否正确;

本模块调用子模块时输入给子模块的参数是否正确;

全局量的定义在各模块中是否一致;

在做内外存交换时要考虑:

文件属性是否正确;

OPEN与CLOSE语句是否正确;

缓冲区容量与记录长度是否匹配;

在进行读写操作之前是否打开了文件;

在结束文件处理时是否关闭了文件;

正文书写/输入错误,

I/O错误是否检查并做了处理。

(2)局部数据结构测试
不正确或不一致的数据类型说明

使用尚未赋值或尚未初始化的变量

错误的初始值或错误的缺省值

变量名拼写错或书写错

不一致的数据类型

全局数据对模块的影响

(3)路径测试
选择适当的测试用例,对模块中重要的执行路径进行测试。

应当设计测试用例查找由于错误的计算、不正确的比较或不正常的控制流而导致的错误。

对基本执行路径和循环进行测试可以发现大量的路径错误。

(4)错误处理测试
出错的描述是否难以理解

出错的描述是否能够对错误定位

显示的错误与实际的错误是否相符

对错误条件的处理正确与否

在对错误进行处理之前,错误条件是否已经引起系统的干预等

(5)边界测试
注意数据流、控制流中刚好等于、大于或小于确定的比较值时出错的可能性。对这些地方要仔细地选择测试用例,认真加以测试。

如果对模块运行时间有要求的话,还要专门进行关键路径测试,以确定最坏情况下和平均意义下影响模块运行时间的因素。

2.单元测试的步骤
模块并不是一个独立的程序,在考虑测试模块时,同时要考虑它和外界的联系,用一些辅助模块去模拟与被测模块相联系的其它模块。

驱动模块(driver)

桩模块(stub)──存根模块

如果一个模块要完成多种功能,可以将这个模块看成由几个小程序组成。必须对其中的每个小程序先进行单元测试要做的工作,对关键模块还要做性能测试。

对支持某些标准规程的程序,更要着手进行互联测试。有人把这种情况特别称为模块测试,以区别单元测试。

集成测试(IntegratedTesting)

集成测试(集成测试、联合测试)

通常,在单元测试的基础上,需要将所有模块按照设计要求组装成为系统。这时需要考虑的问题是:

在把各个模块连接起来的时侯,穿越模块接口的数据是否会丢失;

一个模块的功能是否会对另一个模块的功能产生不利的影响;

各个子功能组合起来,能否达到预期要求的父功能;

全局数据结构是否有问题;

单个模块的误差累积起来,是否会放大,从而达到不能接受的程度。

在单元测试的同时可进行集成测试,

发现并排除在模块连接中可能出现

的问题,最终构成要求的软件系统。

子系统的集成测试特别称为部件测试,它所做的工作是要找出集成后的子系统与系统需求规格说明之间的不一致。

通常,把模块集成成为系统的方式有两种

一次性集成方式

增殖式集成方式

1.一次性集成方式(bigbang)
它是一种非增殖式组装方式。也叫做整体拼装。

使用这种方式,首先对每个模块分别进行模块测试,然后再把所有模块组装在一起进行测试,最终得到要求的软件系统。

2.增殖式集成方式
这种集成方式又称渐增式集成

首先对一个个模块进行模块测试,然后将这些模块逐步组装成较大的系统

在集成的过程中边连接边测试,以发现连接过程中产生的问题

通过增殖逐步组装成为要求的软件系统。

(1)自顶向下的增殖方式
这种集成方式将模块按系统程序结构,沿控制层次自顶向下进行组装。

自顶向下的增殖方式在测试过程中较早地验证了主要的控制和判断点。

选用按深度方向组装的方式,可以首先实现和验证一个完整的软件功能。

(2)自底向上的增殖方式
这种集成的方式是从程序模块结构的最底层的模块开始集成和测试。

因为模块是自底向上进行组装,对于一个给定层次的模块,它的子模块(包括子模块的所有下属模块)已经组装并测试完成,所以不再需要桩模块。在模块的测试过程中需要从子模块得到的信息可以直接运行子模块得到。

自顶向下增殖的方式和自底向上增殖的方式各有优缺点。

一般来讲,一种方式的优点是另一种方式的缺点。

(3)混合增殖式测试
衍变的自顶向下的增殖测试

首先对输入/输出模块和引入新算法模块进行测试;

再自底向上组装成为功能相当完整且相对独立的子系统;

然后由主模块开始自顶向下进行增殖测试。

自底向上-自顶向下的增殖测试

首先对含读操作的子系统自底向上直至根结点模块进行组装和测试;

然后对含写操作的子系统做自顶向下的组装与测试。

回归测试
这种方式采取自顶向下的方式测试被修改的模块及其子模块;

然后将这一部分视为子系统,再自底向上测试。

关键模块问题
在组装测试时,应当确定关键模块,对这些关键模块及早进行测试。

关键模块的特征:

①满足某些软件需求;

②在程序的模块结构中位于较高的层次(高层控制模块);

③较复杂、较易发生错误;

④有明确定义的性能要求。

确认测试(ValidationTesting)
确认测试又称有效性测试。任务是验证软件的功能和性能及其它特性是否与用户的要求一致。

对软件的功能和性能要求在软件需求规格说明书中已经明确规定。它包含的信息就是软件确认测试的基础。

1.进行有效性测试(黑盒测试)
有效性测试是在模拟的环境(可能就是开发的环境)下,运用黑盒测试的方法,验证被测软件是否满足需求规格说明书列出的需求。

首先制定测试计划,规定要做测试的种类。还需要制定一组测试步骤,描述具体的测试用例。

通过实施预定的测试计划和测试步骤,确定

软件的特性是否与需求相符;

所有的文档都是正确且便于使用;

同时,对其它软件需求,例如可移植性、兼容性、出错自动恢复、可维护性等,也都要进行测试

在全部软件测试的测试用例运行完后,所有的测试结果可以分为两类:

测试结果与预期的结果相符。这说明软件的这部分功能或性能特征与需求规格说明书相符合,从而这部分程序被接受。

测试结果与预期的结果不符。这说明软件的这部分功能或性能特征与需求规格说明不一致,因此要为它提交一份问题报告。

2.软件配置复查
软件配置复查的目的是保证

软件配置的所有成分都齐全;

各方面的质量都符合要求;

具有维护阶段所必需的细节;

而且已经编排好分类的目录。

应当严格遵守用户手册和操作手册中规定的使用步骤,以便检查这些文档资料的完整性和正确性。

验收测试(AcceptanceTesting)
在通过了系统的有效性测试及软件配置审查之后,就应开始系统的验收测试。

验收测试是以用户为主的测试。软件开发人员和QA(质量保证)人员也应参加。

由用户参加设计测试用例,使用生产中的实际数据进行测试。

在测试过程中,除了考虑软件的功能和性能外,还应对软件的可移植性、兼容性、可维护性、错误的恢复功能等进行确认。

确认测试应交付的文档有:
确认测试分析报告

最终的用户手册和操作手册

项目开发总结报告。

系统测试(SystemTesting)
系统测试,是将通过确认测试的软件,作为整个基于计算机系统的一个元素,与计算机硬件、外设、某些支持软件、数据和人员等其它系统元素结合在一起,在实际运行环境下,对计算机系统进行一系列的组装测试和确认测试。

系统测试的目的在于通过与系统的需求定义作比较,发现软件与系统的定义不符合或与之矛盾的地方。

α测试和β测试
在软件交付使用之后,用户将如何实际使用程序,对于开发者来说是无法预测的。

α测试是由一个用户在开发环境下进行的测试,也可以是公司内部的用户在模拟实际操作环境下进行的测试。

α测试的目的是评价软件产品的FLURPS(即功能、局域化、可使用性、可靠性、性能和支持)。尤其注重产品的界面和特色。

α测试可以从软件产品编码结束之时开始,或在模块(子系统)测试完成之后开始,也可以在确认测试过程中产品达到一定的稳定和可靠程度之后再开始。

β测试是由软件的多个用户在实际使用环境下进行的测试。这些用户返回有关错误信息给开发者。

测试时,开发者通常不在测试现场。因而,β测试是在开发者无法控制的环境下进行的软件现场应用。

在β测试中,由用户记下遇到的所有问题,包括真实的以及主观认定的,定期向开发者报告。

β测试主要衡量产品的FLURPS。着重于产品的支持性,包括文档、客户培训和支持产品生产能力。

只有当α测试达到一定的可靠程度时,才能开始β测试。它处在整个测试的最后阶段。同时,产品的所有手册文本也应该在此阶段完全定稿。

测试类型

软件测试是由一系列不同的测试组成。主要目的是对以计算机为基础的系统进行充分的测试。

功能测试

功能测试是在规定的一段时间内运行软件系统的所有功能,以验证这个软件系统有无严重错误。

强度测试
强度测试是要检查在系统运行环境不正常乃至发生故障的情况下,系统可以运行到何种程度的测试。例如:

把输入数据速率提高一个数量级,确定输入功能将如何响应。

设计需要占用最大存储量或其它资源的测试用例进行测试。

设计出在虚拟存储管理机制中引起“颠簸”的测试用例进行测试。

设计出会对磁盘常驻内存的数据过度访问的测试用例进行测试。

强度测试的一个变种就是敏感性测试。在程序有效数据界限内一个小范围内的一组数据可能引起极端的或不平稳的错误处理出现,或者导致极度的性能下降的情况发生。此测试用以发现可能引起这种不稳定性或不正常处理的某些数据组合。

性能测试
性能测试是要检查系统是否满足在需求说明书中规定的性能。特别是对于实时系统或嵌入式系统。

性能测试常常需要与强度测试结合起来进行,并常常要求同时进行硬件和软件检测。

通常,对软件性能的检测表现在以下几个方面:响应时间、吞吐量、辅助存储区,例如缓冲区,工作区的大小等、处理精度,等等。

恢复测试
恢复测试是要证实在克服硬件故障(包括掉电、硬件或网络出错等)后,系统能否正常地继续进行工作,并不对系统造成任何损害。

为此,可采用各种人工干预的手段,模拟硬件故障,故意造成软件出错。并由此检查:

错误探测功能──系统能否发现硬件失效与故障;

能否切换或启动备用的硬件;

在故障发生时能否保护正在运行的作业和系统状态;

在系统恢复后能否从最后记录下来的无错误状态开始继续执行作业,等等。

掉电测试:其目的是测试软件系统在发生电源中断时能否保护当时的状态且不毁坏数据,然后在电源恢复时从保留的断点处重新进行操作。

配置测试

这类测试是要检查计算机系统内各个设备或各种资源之间的相互联结和功能分配中的错误。

它主要包括以下几种:

配置命令测试:验证全部配置命令的可操作性(有效性);特别对最大配置和最小配置要进行测试。软件配置和硬件配置都要测试。

循环配置测试:证明对每个设备物理与逻辑的,逻辑与功能的每次循环置换配置都能正常工作。

修复测试:检查每种配置状态及哪个设备是坏的。并用自动的或手工的方式进行配置状态间的转换。

安全性测试
安全性测试是要检验在系统中已经存在的系统安全性、保密性措施是否发挥作用,有无漏洞。

力图破坏系统的保护机构以进入系统的主要方法有以下几种:

正面攻击或从侧面、背面攻击系统中易受损坏的那些部分;

以系统输入为突破口,利用输入的容错性进行正面攻击;

申请和占用过多的资源压垮系统,以破坏安全措施,从而进入系统;

故意使系统出错,利用系统恢复的过程,窃取用户口令及其它有用的信息;

通过浏览残留在计算机各种资源中的垃圾(无用信息),以获取如口令,安全码,译码关键字等信息;

浏览全局数据,期望从中找到进入系统的关键字;

浏览那些逻辑上不存在,但物理上还存在的各种记录和资料等。

可使用性测试

可使用性测试主要从使用的合理性和方便性等角度对软件系统进行检查,发现人为因素或使用上的问题。

要保证在足够详细的程度下,用户界面便于使用;对输入量可容错、响应时间和响应方式合理可行、输出信息有意义、正确并前后一致;出错信息能够引导用户去解决问题;软件文档全面、正规、确切。

安装测试
安装测试的目的不是找软件错误,而是找安装错误。

在安装软件系统时,会有多种选择。

要分配和装入文件与程序库

布置适用的硬件配置

进行程序的联结。

而安装测试就是要找出在这些安装过程中出现的错误。

安装测试是在系统安装之后进行测试。它要检验:

用户选择的一套任选方案是否相容;

系统的每一部分是否都齐全;

所有文件是否都已产生并确有所需要的内容;

硬件的配置是否合理,等等。

容量测试
容量测试是要检验系统的能力最高能达到什么程度。例如,

对于编译程序,让它处理特别长的源程序;

对于操作系统,让它的作业队列“满员”;

对于信息检索系统,让它使用频率达到最大。

在使系统的全部资源达到“满负荷”的情形下,测试系统的承受能力。

文档测试
这种测试是检查用户文档(如用户手册)的清晰性和精确性。

用户文档中所使用的例子必须在测试中一一试过,确保叙述正确无误。

自动测试
认识自动测试

什么时候使用自动测试

自动测试工具

好的测试工程师应具备的素质

人是测试工作中最有价值也是最重要的资源,没有一个合格的、积极的测试小组,测试就不可能实现。然而,在软件开发产业中有一种非常普遍习惯,那就是让那些经验最少的新手、没有效率的开发者或不适合干其他工作的人去做测试工作。这绝对是一种目光短浅的行为,对一个系统进行有效的测试所需要的技能绝对不比进行软件开发需要的少,事实上,测试者将获得极其广泛的经验,他们将遇到许多开发者不可能遇到的问题。

好的测试工程师应具备的素质
沟通能力
移情能力
技术能力
自信心
外交能力
幽默感
很强的记忆力
耐心

好的测试工程师应具备的素质
怀疑精神
自我督促
洞察力
沟通能力

一名理想的测试者必须能够同测试涉及到的所有人进行沟通,具有与技术(开发者)和非技术人员(客户,管理人员)的交流能力。

既要可以和用户谈得来,又能同开发人员说得上话,不幸的是这两类人没有共同语言。和用户谈话的重点必须放在系统可以正确地处理什么和不可以处理什么上。而和开发者谈相同的信息时,就必须将这些活重新组织以另一种方式表达出来,测试小组的成员必须能够同等地同用户和开发者沟通。

移情能力
和系统开发有关的所有人员都处在一种既关心又担心的状态之中。用户担心将来使用一个不符合自己要求的系统,开发者则担心由于系统要求不正确而使他不得不重新开发整个系统,管理部门则担心这个系统突然崩溃而使它的声誉受损。测试者必须和每一类人打交道,因此需要测试小组的成员对他们每个人都具有足够的理解和同情,具备了这种能力可以将测试人员与相关人员之间的冲突和对抗减少到最低程度。

技术能力
一个测试者必须既明白被测软件系统的概念又要会使用工程中的那些工具。要做到这一点需要有几年以上的编程经验,前期的开发经验可以帮助对软件开发过程有较深入的理解。

就我们部门而言,作为一个好的测试工程师,必须具备的技术能力有:LINUX、C++、VC、NT、WIN2000、测试技能及安全知识等。

自信心
作为好的测试人员必须对自己的观点有足够的自信心。

外交能力
当你告诉某人他出了错时,就必须使用一些外交方法。机智老练和外交手法有助于维护与开发人员的协作关系,测试者在告诉开发者他的软件有错误时,也同样需要一定的外交手腕。如果采取的方法过于强硬,对测试者来说,在以后和开发部门的合作方面就相当于“赢了战争却输了战役”。

幽默感
在遇到与研发人员问题上有争议的情况下,一个幽默的批评将是很有帮助的。

很强的记忆力
一个理想的测试者应该有能力将以前曾经遇到过的类似的错误从记忆深处挖掘出来,这一能力在测试过程中的价值是无法衡量的。因为许多新出现的问题和我们已经发现的问题相差无几。

耐心
一些测试工作需要难以置信的耐心。有时你需要花费惊人的时间去查找或发现一个错误。使这个错误可重现即有规律。而这个工作是那些坐不住的人无法完成的。

怀疑精神
可以预料,开发者会尽他们最大的努力将所有的错误解释过去。测式者必须听每个人的说明,但他必须保持怀疑直到他自己看过以后。

自我督促
做测试工作很容易使你变得懒散。只有那些具有自我督促能力的人才能够使自己每天正常地工作。

洞察力
一个好的测试工程师具有“测试是为了破坏”的观点,捕获用户观点的能力,强烈的质量追求,对细节的关注能力。应用的高风险区的判断能力以便将有限的测试针对重点环节。