|
|
|
@ -0,0 +1,572 @@
|
|
|
|
|
## 黑盒测试法概述
|
|
|
|
|
|
|
|
|
|
> 概述
|
|
|
|
|
|
|
|
|
|
黑盒测试又称为功能测试或数据驱动测试,着眼于程序外部结构,将被测试程序视为一个不能打开的黑盒子,完全不考虑程序内部逻辑结构和内部特性,主要针对软件界面、软件功能、外部数据库访问以及软件初始化等方面进行测试。
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
> 主要目的
|
|
|
|
|
|
|
|
|
|
黑盒测试的目的主要是在已知软件产品应具有的功能的基础上,发现以下类型的错误:
|
|
|
|
|
|
|
|
|
|
- 检查程序功能是否按照需求规格说明书的规定正常使用,测试每个功能是否有遗漏,检测性能等特性要求是否满足要求。
|
|
|
|
|
- 检测人机交互是否错误,检测数据结构或外部数据库访问是否错误,程序是否能够适当地接收数据而产生正确的输出结果,并保持外部信息(如数据库或文件)的完整性。
|
|
|
|
|
- 检测程序初始化和终止方面的错误。
|
|
|
|
|
|
|
|
|
|
黑盒测试属于穷举输入测试方法,只有将所有可能的输入都作为测试情况来使用,才能检查出程序中所有的错误。但穷举测试是不现实的,因此我们需要选择合适的方法使设计出来的测试用例具有完整性、代表性,并能有效地发现软件缺陷。
|
|
|
|
|
|
|
|
|
|
> 黑盒测试常用的方法和技术
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
## 边界值测试
|
|
|
|
|
|
|
|
|
|
### 边界值分析法
|
|
|
|
|
|
|
|
|
|
边界值分析法(BVA,Boundary Value Analysis )是一种很实用的黑盒测试用例设计方法,它具有很强的发现程序错误的能力。无数的测试实践表明,大量的故障往往发生在输入定义区域或输出值域的边界上,而不是在其内部,如做一个除法运算的例子,如果测试者忽略被除数为 0 的情况就会导致问题的遗漏。所以在设计测试用例 时,一定要对边界附近的处理十分重视。为检验边界附近的处理专门设计测试用例, 通常都会取得很好的效果。
|
|
|
|
|
|
|
|
|
|
> 基本思想
|
|
|
|
|
|
|
|
|
|
应用边界值分析的基本思想是:选取正好等于、刚刚大于和刚刚小于边界值的数据作为测试数据。
|
|
|
|
|
|
|
|
|
|
边界值分析法是最有效的黑盒分析法,但在边界情况复杂的情况下, 要找出适当的边界测试用例还需要针对问题的输入域、输出域边界,耐心细致地逐个进行考察。
|
|
|
|
|
|
|
|
|
|
> 边界值分析
|
|
|
|
|
|
|
|
|
|
边界值分析关注的是输入、输出空间的边界条件,以标识测试用例。实践证明,程序在处理大量中间数值时都正确,但在边界处却往往可能出现错误。例如,循环条件漏写了等于,计数器少计了一次或多计了一次,数组下标忽略了 0 的处理等等,这些都是我们平时编程容易疏忽而导致出错的地方。
|
|
|
|
|
|
|
|
|
|
刚开始时,可能意识不到一组给定数据包含了多少边界,但是仔细分析总可以找到一些不明显的、有趣的或可能产生软件故障的边界。
|
|
|
|
|
|
|
|
|
|
实际上,边界条件就是软件操作界限所在的边缘条件。 一些可能与边界有关的数据类型有:数值、速度、字符、位置、尺寸、数量等。
|
|
|
|
|
同时,针对这些数据类型可以考虑它们的下述特征:第一个/最后一个,最小/最大,开始/完成,超过/在内,空/满等。以上是一些可能出现的边界条件。
|
|
|
|
|
实际应用中,每一个软件测试问题都不完全相同,可能包含各式各样的边界条件,应视具体情况而定。
|
|
|
|
|
|
|
|
|
|
> 内部边界值分析
|
|
|
|
|
|
|
|
|
|
上面边界值分析中所讨论的边界条件比较容易发现,它们在软件规格说明中或者有定义,或者可以在使用软件的过程中确定。而有些边界却是在软件内部,用户几乎看不到,但我们在进行软件测试时仍有必要对它们进行检查,这样的边界条件称为内部边界条件或次边界条件。
|
|
|
|
|
|
|
|
|
|
寻找内部边界条件比较困难,虽然不要求软件测试人员成为程序员或者具有阅读源代码的能力,但要求软件测试人员能大体了解软件的工作方式。
|
|
|
|
|
|
|
|
|
|
例如对文本输入或 文本转换软件进行测试,在考虑数据区间包含哪些值时,最好参考一下 ASCII 表。如果测试的文本输入框只接受用户输入字符 A——Z 和 a——z,就应该在非法区间中, 检查 ASCII 表中刚好位于 A 和 a 前面,Z 和 z 后面的值——@ ,[ ,‘ 和 { 。
|
|
|
|
|
|
|
|
|
|
### 边界值分析法测试用例
|
|
|
|
|
|
|
|
|
|
> 边界分析测试的基本思想
|
|
|
|
|
|
|
|
|
|
为便于理解,假设有两个变量 x1 和 x2 的函数 F,其中函数 F 实现为一个程序, x1、x2 在下列范围内取值: a≤x1≤bc≤x2≤d 区间[a,b]和[c,d]是 x1、x2 的值域,程序 F 的输入定义域如下图所示,即带阴影矩 形中的任何点都是程序 F 的有效输入。
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
采用边界值分析测试的基本原理是:故障往往出现在输入变量的边界值附近。
|
|
|
|
|
例如,当一个循环条件为“≤”时,却错写成“<”,计时器发生少计数一次。
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
边界值分析测试的基本思想是使用在最小值(min)、略高于最小值(min+)、正常值(nom)、略低于最大值(max-)和最大值(max)处取输入变量值。同时,对于有多个输入变量的情况我们通常是基于可靠性理论中称为“单故障”的假设,这种假设认为有两个或两个以上故障同时出现而导致软件失效的情况很少,也就是说,软件失效基本上是由单故障引起的。因此,边界值分析测试用例的获得,是通过使一个变量取极值,剩下所有变量取正常值。
|
|
|
|
|
|
|
|
|
|
因此,边界值分析测试用例的获得,是通过使一个变量 取极值,剩下所有变量取正常值。前面有两个输入变量的程序 F 的边界值分析测试用例(如图 3.2 所示)是:
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
{ < x1nom ,x2min >, < x1nom ,x2min+ >, < x1nom , x2nom >, < x1nom , x2max- >, < x1nom , x2max >,< x1min , x2nom >,< x1min+ , x2nom >, < x1max- , x2nom >, < x1max , x2nom > }
|
|
|
|
|
对于一个含有 n 个变量的程序,保留其中一个变量,让其余的变量取正常值,被 保留的变量依次取 min、 min+、nom、max-、max 值,对每个变量都重复进行。这样, 对于一个有 n 个变量的程序,边界值分析测试程序会产生 4n+1 个测试用例。如果没有显式的给出边界,如三角形问题,则必须创建一种人工边界,可以先设定下限值(边长应大于等于 1),并规定上限值,如 100,或取默认的最大可表示的整数值。
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
> 健壮性测试
|
|
|
|
|
|
|
|
|
|
健壮性测试是边界分析测试的一种简单扩展,除了取 5 个边界值分析取值外,还需要考虑采用一个略超过最大值(max+)以及略小于最小值(min-)的取值,检查超过极限值时系统的表现会是什么。健壮性测试最有意义的部分不是输入,而是预期的 输出。它要观察例外情况如何处理,比如某个部分的负载能力超过其最大值可能出现的情形。健壮性测试如图 3.3 所示。
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
### 边界值分析法测试实例
|
|
|
|
|
|
|
|
|
|
> 三角形问题
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
问题描述:
|
|
|
|
|
三角形问题接受三个整数 a、b 和 c 作为输入,用做三角形的边。
|
|
|
|
|
程序的输出是由这三条边确定的三角形类型:等边三角形、等腰三角形、不等边三角形或非三角形。
|
|
|
|
|
|
|
|
|
|
通过提供更多细节可以改进这个定义。于是这个问题变成以下的形式。
|
|
|
|
|
三角形问题接受三个整数 a、b 和 c 作为输入,用做三角形的边。整数 a、b 和 c 必须满足以下条件:
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
程序的输出是由这三条边确定的三角形类型:等边三角形、等腰三角形、不等边三角形或非三角形。如果输入值没有满足 c1、c2 和 c3 这些条件中的任何一个,则程序会通过输出消息来进行通知,例如,“b 的取值不在允许取值的范围内。”如果 a、b 和 c 取值满足 c1、c2 和 c3,则给出以下四种相互排斥输出中的一个:
|
|
|
|
|
|
|
|
|
|
- 如果三条边相等,则程序的输出是等边三角形。
|
|
|
|
|
- 如果恰好有两条边相等,则程序的输出是等腰三角形。
|
|
|
|
|
- 如果没有两条边相等,则程序输出的是不等边三角形。
|
|
|
|
|
- 如果 c4、c5 和 c6 中有一个条件不满足,则程序输出的是非三角形。
|
|
|
|
|
|
|
|
|
|
在三角形问题描述中,除了要求边长是整数外,没有给出其它的限制条件。边界下限为 1,上限为 100。表 3.1 给出了边界值分析测试用例。
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
>NextDate 函数
|
|
|
|
|
|
|
|
|
|
问题描述:
|
|
|
|
|
NextDate 是一个有三个变量(月份、日期和年)的函数。函数返回输入日期后面的那个日期。变量月份、日期和年都具有整数值,且满足以下条件:
|
|
|
|
|
|
|
|
|
|
- c1.1≤月份≤12
|
|
|
|
|
- c2.1≤日期≤31
|
|
|
|
|
- c3.1912≤年≤2050
|
|
|
|
|
|
|
|
|
|
在NextDate 函数中,规定了变量 month、day、year 相应的取值范围,即 1 ≤ month ≤ 12,1 ≤ day ≤31,1912 ≤ year ≤ 2050,表 3.2 给出了其健壮性测试用例。
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
边界值分析局限性:
|
|
|
|
|
|
|
|
|
|
如果被测程序是多个独立变量的函数,这些变量受物理量的限制,则很适合采用边界值分析。这里的关键是“独立”和“物理量”。
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
简单地看一下表 3.2 中 NextDate 函数的边界分析测试用例,就会发现其实这些测试用例是不充分的。
|
|
|
|
|
|
|
|
|
|
例如,没强调 2 月和闰年。这里的真正问题是,月份、日期和年 变量之间存在依赖关系,而边界值分析假设变量是完全独立的。不过即便如此,边界值分析也能够捕获月末和年末缺陷。
|
|
|
|
|
|
|
|
|
|
边界值分析测试用例通过引用物理量的边界独立导出变量极值,不考虑函数的性质,也不考虑变量的语义含义。因此我们把边界值分析测试用例看作是初步的,这些测试用例的获得基本没有利用理解和想象。
|
|
|
|
|
|
|
|
|
|
物理量准则也很重要。如果变量引用某个物理量,例如温度、压力、空气速度、 负载等,则物理边界极为重要。举一个这方面的例子:
|
|
|
|
|
|
|
|
|
|
菲尼克斯的航空港国际机场 1992 年 6 月 26 日被迫关闭,原因是当天的空气温度达到 122 ℉导致飞行员在起飞之前不能设置某一特定设备,因为该设备能够接受的最大空气温度是 120 ℉。
|
|
|
|
|
|
|
|
|
|
边界值分析对布尔变量和逻辑变量没有多大意义。例如布尔变量的极值是 TRUE 和 FALSE,但是其余三个值不明确。
|
|
|
|
|
我们在后面章节可以看到,布尔变量可以采用基于决策表的测试。
|
|
|
|
|
|
|
|
|
|
## 等价类测试
|
|
|
|
|
|
|
|
|
|
使用等价类作为功能性能测试的基础有两个动机:我们希望进行完备的测试,同时又希望避免冗余。
|
|
|
|
|
边界值测试不能实现这两种希望中的任意一个:研究那些测试用例表,很容易看出存在大量冗余,再进一步仔细研究,还会发现严重漏洞。
|
|
|
|
|
等价类测试重复边界值测试的两个决定因素:健壮性和单/多缺陷假设。本节我们给出了4种形式的等价类测试,在弱/强等价类测试之分的基础之上针对是否进行无效数据的处理产生健壮与一般等价类测试之分。
|
|
|
|
|
|
|
|
|
|
### 等价类
|
|
|
|
|
|
|
|
|
|
等价类的重要特征是对它们构成集合的一个划分,其中,划分是指互不相交的一组子集,并且这些子集的并是整个集合。
|
|
|
|
|
这对于测试有两点非常重要的意义:表示整个集合这个事实提供了一种形式的完备性,而互不相交可保证一种形式的无冗余性。由于子集是由等价关系决定的,因此子集的元素都有一些共同点。
|
|
|
|
|
等价类测试的思想是通过每个等价类中的一个元素标识测试用例。
|
|
|
|
|
|
|
|
|
|
如果广泛选择等价类,则可以大大降低测试用例之间的冗余。
|
|
|
|
|
|
|
|
|
|
例如,在三角形问题中,我们当然要有一个等边三角形的测试用例,我们可能选择三元组(10,10,10)作为测试用例的输入。
|
|
|
|
|
如果这样做了, 则可以预期不会从诸如(3,3,3)和(100,100,100)这样的测试用例中得到多少新东西。直觉告诉我们,这些测试用例会以与第一个测试用例一样的方式进行“相同处理”,因此,这些测试用例是冗余。
|
|
|
|
|
当我们在考虑结构性测试时,将会看到“相同处理”映射到“遍历相同的执行路径。”
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
等价类测试的关键就是选择确定类的等价关系。通常我们通过预测可能的实现, 考虑在现实中必须提供的功能操作来做出这种选择。我们将用一系列例子说明这一 点,但是首先必须区分弱和强等价类测试。
|
|
|
|
|
|
|
|
|
|
为了便于理解,我们还是讨论与有两个变量 x1 和 x2 的函数 F 联系起来。如果 F 实现为一个程序,则输入变量 x1 和 x2 将拥有以下边界,以及边界内的区间:
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
其中方括号和圆括号分别表示闭区间和开区间的端点。x1 和 x2 的无效值是:x1<a,x1>d 以及 x2<e,x2>g。
|
|
|
|
|
|
|
|
|
|
- **弱一般等价类测试**
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
弱一般等价类测试通过使用测试用例的每个等价类(区间)的一个变量实现(单缺陷 假设的作用)。对于上面给出的例子,可得到如图 3.4 所示的弱等价类测试用例。
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
这三个测试用例使用每个等价类中的一个值。事实上,永远都有等量的弱等价类测试用例,因为划分中的类对应最大子集数。
|
|
|
|
|
|
|
|
|
|
- **强一般等价类测试**
|
|
|
|
|
|
|
|
|
|
强一般等价类测试基于多缺陷假设,它需要等价类笛卡儿积的每个元素对应的测试用 例(如图 3.5 所示)。笛卡儿积可保证两种意义上的“完备性”:一是覆盖所有的等价类, 二是覆盖所有可能的输入组合中的每一个。
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
“好的”等价类测试的关键是等价关系的选择,要注意被“相同处理”的输入。在大多数情况下,等价类测试定义输入定义域的等价类。不过,其实也没有理由不能根据被测程序函数的输出值域定义等价关系。事实上,这对于三角形问题是最简单的方法。
|
|
|
|
|
|
|
|
|
|
- **弱健壮等价类测试**
|
|
|
|
|
|
|
|
|
|
这种测试的名称显然与直觉矛盾,怎么能够既弱又健壮呢?其实这是因为它是基于两个不同的角度而命名的。说它弱是因为它基于单缺陷假设,说它健壮是因为这种测试考虑了无效值
|
|
|
|
|
|
|
|
|
|
(1)对于有效输入,弱健壮等价类测试使用每个有效类的一个值,就像我们在弱一般等价类测试中所做的一样。请注意,这些测试用例中的所有输入都是有效的。
|
|
|
|
|
(2)对于无效输入,弱健壮等价类测试的测试用例将拥有一个无效值,并保持其余的值都是有效的。此时,“单缺陷”会造成测试用例失败。
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
对于健壮等价类测试通常有两个问题。
|
|
|
|
|
第一是:规格说明常常并没有定义无效测试用例所预期的输出是什么。因此,测试人员需要花大量时间定义这些测试用例的输出。
|
|
|
|
|
第二是:强类型语言没有必要考虑无效输入。
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
- **强健壮等价类测试**
|
|
|
|
|
|
|
|
|
|
强健壮等价类测试,“强”是指该类测试用例的获得是基于多缺陷假设,“健壮” 则和前面的定义一样,是指考虑了无效值。如图 3.7 所示,强健壮等价类测试从所有等价类笛卡尔积的每个元素中获得测试用例
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
### 等价类测试实例
|
|
|
|
|
|
|
|
|
|
> 三角形问题
|
|
|
|
|
|
|
|
|
|
在描述问题时,我们曾经提到有四种可能出现的输出:非三角形、不等边三角形、 等腰三角形和等边三角形。可以使用这些输出,标识如下所示的输出(值域)等价类:
|
|
|
|
|
|
|
|
|
|
- R1={:有三条边 a、b 和 c 的等边三角形}
|
|
|
|
|
- R2={:有三条边 a、b 和 c 的等腰三角形}
|
|
|
|
|
- R3={:有三条边 a、b 和 c 的不等边三角形}
|
|
|
|
|
- R4={:有三条边 a、b 和 c 的非三角形}
|
|
|
|
|
|
|
|
|
|
四个弱一般等价类测试用例是:
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
由于变量 a、b 和 c 没有有效区间划分,则强一般等价类测试用例与弱一般等价类测试用例相同。
|
|
|
|
|
|
|
|
|
|
考虑 a、b 和 c 的无效值产生的以下额外弱健壮等价类测试用例:
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
以下是额外强健壮等价类测试用例三维立方的一个“角”:
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
请注意,预期输出如何完备地描述无效输入值。
|
|
|
|
|
|
|
|
|
|
等价类测试显然对于用来定义的等价关系很敏感。如果在输入定义域上定义等价类,则可以得到更丰富的测试用例集合。三个整数 a、b 和 c 有些什么可能的取值呢? 这些整数相等(有三种相等方式),或都不相等。
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
作为一个单独的问题,我们可以通过三角形的性质来判断三条边是否构成一个三角形(例如,三元组有一对相等的边,但是这些边不构成一个三角形)
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
如果我们要彻底一些,可以将“小于或等于”分解为两种不同的情况,这样D6就变成:
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
同样对于 D7 和 D8 也有类似的情况。
|
|
|
|
|
|
|
|
|
|
> NextDate 函数
|
|
|
|
|
|
|
|
|
|
NextDate 函数可以很好地说明选择内部等价关系的工艺。前面已经介绍过,NextDate 是一个三变量函数,即月份、日期和年,这些变量的有效值区间定义如下:
|
|
|
|
|
|
|
|
|
|
- M1={月份:1≤月份≤12}
|
|
|
|
|
- D1={日期:1≤月份≤31}
|
|
|
|
|
- Y1={年:1812≤月份≤2012}
|
|
|
|
|
|
|
|
|
|
无效等价类是:
|
|
|
|
|
|
|
|
|
|
- M2={月份:月份12}
|
|
|
|
|
- D2={日期:日期31}
|
|
|
|
|
- Y2={年:年2012}
|
|
|
|
|
|
|
|
|
|
由于每个独立变量的有效区间均为 1 个,因此只有弱一般等价类测试用例出现, 并且与强一般等价类测试用例相同:
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
以下是弱健壮测试用例的完整集合:
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
与三角形问题一样,以下是额外强健壮性等价类测试用例三维立方的一个“角”:
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
划分等价关系的重点是等价类中的元素要被“同样处理”。上述方法所得测试用例集其实是不足的,因为它只注意到在单个变量处理的有效/无效层次上进行,而没有进一步分析具体处理的过程与特征。对该函数如果更仔细地选择等价关系,所得到的等价类和测试用例集将会更有用。
|
|
|
|
|
|
|
|
|
|
例如在 NextDate 函数中,注意到必须对输入日期做怎样的处理?
|
|
|
|
|
|
|
|
|
|
如果它不是某个月的最后一天,则 NextDate 函数会直接对日期加 1。到了月末,下一个日期是 1,月份加 1。到了年末,日期和月份会复位到 1,年加 1。最后,闰年问题要确定有关的月份的最后一天。
|
|
|
|
|
|
|
|
|
|
经过这些分析之后,可以假设有以下等价类:
|
|
|
|
|
|
|
|
|
|
- M1={月份:每月有 30 天}
|
|
|
|
|
- M2={月份:每月有 31 天}
|
|
|
|
|
- M1={月份:此月是 2 月}
|
|
|
|
|
- D1={日期:1≤日期≤28}
|
|
|
|
|
- D2={日期:日期=29}
|
|
|
|
|
- D3={日期:日期=30}
|
|
|
|
|
- D4={日期:日期=31}
|
|
|
|
|
- Y1={年:年=2000}
|
|
|
|
|
- Y2={年:年是闰年}
|
|
|
|
|
- Y3={年:年是平年}
|
|
|
|
|
|
|
|
|
|
通过选择有 30 天的月份和有 31 天的月份的独立类,可以简化月份最后一天问题。 通过把 2 月分成独立的类,可以对闰年问题给予更多关注。我们还要特别关注日期的值:D1中的日(差不多)总是加 1,D4 中的日只对 M2 中的月才有意义。最后,年有三个类,包括 2000 年这个特例、闰年和非闰年类。这并不是完美的等价类集合, 但是通过这种等价类集合可以发现很多潜在错误。
|
|
|
|
|
|
|
|
|
|
这些类产生以下弱等价类测试用例。与前面一样,机械地从对应类的取值范围中选择输入:
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
机械选择输入值不考虑领域知识,因此没有考虑两种不可能出现的日期。“自动” 测试用例生成永远都会有这种问题,因为领域知识不是通过等价类选择获得的。
|
|
|
|
|
|
|
|
|
|
经过改进的强一般等价类测试用例是:
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
从弱一般测试转向强一般测试会产生一些边界值测试中也出现的冗余问题。从弱到强的转换,不管是一般类还是健壮类,都是以等价类的叉积表示。3 个月份类乘以 4 个日期类乘以 3 个年类,产生 36 个强一般等价类测试用例。对每个变量加上 2 个无效类,得到 150 个强健壮等价类测试用例。
|
|
|
|
|
|
|
|
|
|
通过更仔细地研究年类,还可以精简测试用例集合。通过合并 Y1 和 Y3,把结果 称做平年,则 36 个测试用例就会降低到 24 个。这种变化不再特别关注 2000 年,并 58 会增加判断闰年的难度。需要在难度和能够从当前用例中了解到的内容之间做平衡综合考虑。
|
|
|
|
|
|
|
|
|
|
> 佣金问题
|
|
|
|
|
|
|
|
|
|
问题描述:前亚利桑那州境内的一位步枪销售商销售密苏里州制造商制造的步枪机(lock)、枪托(stock)和枪管(barrel)。枪机卖 45 美元,枪托卖 30 美元,枪管卖 25 美元。销售商每月至少要售出一支完整的步枪,且生产限额是大多数销售商在一个 月内可销售 70 个枪机、80 个枪托和 90 个枪管。每访问一个镇子之后,销售商都给密 苏里州步枪制造商发出电报,说明在那个镇子中售出的枪机、枪托和枪管数量。到了 月末,销售商要发出一封很短的电报,通知-1 个枪机被售出。这样步枪制造商就知道当月的销售情况,并计算销售商的佣金如下:销售额不到(含)1000 美元的部分为 10%,1000(不含)~1800(含)美元的部分为 15%,超过 1800 美元的部分为 20%。 佣金程序生成月份销售报告,汇总售出的枪机、枪托和枪管总数,销售商的总销售额 以及佣金。
|
|
|
|
|
|
|
|
|
|
佣金问题的输入定义域,由于枪机、枪托和枪管的限制而被“自然地”划分。这些等价类也正是通过传统等价类测试所标识的等价类。第一个类是有效输入,其他两个类是无效输入。在佣金问题中,仅考虑输入定义域等价类产生的测试用例集合非常不能令人满意。通过进一步分析,我们能够发现对佣金函数的输出值域定义等价类可以有效改进测试用例集合。
|
|
|
|
|
|
|
|
|
|
输入变量对应的有效类是:
|
|
|
|
|
|
|
|
|
|
- L1={枪机:1≤枪机≤70}
|
|
|
|
|
- L2={枪机=-1}
|
|
|
|
|
- S1={枪托:1≤枪托≤80}
|
|
|
|
|
- B1={枪管:1≤枪托≤90}
|
|
|
|
|
|
|
|
|
|
输入变量对应的无效类是:
|
|
|
|
|
|
|
|
|
|
- L2={枪机:枪机=0 或枪机<-1}
|
|
|
|
|
- L3={枪机:枪机>70}
|
|
|
|
|
- S2={枪托:枪托<1}
|
|
|
|
|
- S3={枪管:枪管>80}
|
|
|
|
|
- B2={枪管:枪管<1}
|
|
|
|
|
- B3={枪管:枪管>90}
|
|
|
|
|
|
|
|
|
|
其中变量枪机还用做指示不再有电报的标记。当枪机等于-1 时,While 循环就会终止,总枪机、总枪托和枪管的值就会被用来计算销售额,进而计算佣金,因此对于变量枪机增加了第 2 个有效类 L2。
|
|
|
|
|
|
|
|
|
|
根据上述等价类的划分,可得如下所示佣金问题的弱一般等价类测试用例,这个 测试用例同样也等于强一般等价类测试用例。
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
七个弱健壮测试用例如下。
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
最后,额外强健壮等价类测试用例三维立方的一个“角”是:
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
请注意,对于强测试用例,不管是强一般测试用例还是强健壮测试用例,都只有一个是合理输入。如果确实担心错误案例,那么这就是很好的测试用例集合。但是这样很 难确信佣金问题的计算部分没有问题。在本例中,我们可以通过对输出值域定义等价类来进一步完善测试。前面提到过,销售额是所售出的枪机、枪托和枪管数量的函数:
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
由此得到如下的输出值域等价类测试用例:
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
这些测试用例让人感觉到正在接触问题的重要部分。与弱健壮测试用例结合在一 起,就可得到佣金问题的相当不错的测试。另外,可能还希望增加一些边界检查,只是为了保证从 1000 美元到 1800 美元的转移是正确的。
|
|
|
|
|
|
|
|
|
|
### 指导方针
|
|
|
|
|
|
|
|
|
|
我们已经介绍了三个例子,最后讨论关于等价类测试的一些观察和等价类测试指导方针。
|
|
|
|
|
|
|
|
|
|
- 显然,等价类测试的弱形式(一般或健壮)不如对应的强形式的测试全面。
|
|
|
|
|
- 如果实现语言的强类型(无效值会引起运行时错误),则没有必要使用健壮 形式的测试。
|
|
|
|
|
- 如果错误条件非常重要,则进行健壮形式的测试是合适的。
|
|
|
|
|
- 如果输入数据以离散值区间和集合定义,则等价类测试是合适的。当然也适用于如果变量值越界就会出现故障的系统。
|
|
|
|
|
- 通过结合边界值测试,等价类测试可得到加强。(我们可以“重用”定义等价类的工作成果。)
|
|
|
|
|
- 如果程序函数很复杂,则等价类测试是被指示的。在这种情况下,函数的复 杂性可以帮助标识有用的等价类,就像 NextDate 函数一样。
|
|
|
|
|
- 强等价类测试假设变量是独立的,相应的测试用例相乘会引起冗余问题。而 如果存在依赖关系,则常常会生成“错误”测试用例,就像 NextDate 函数一 样(此时最好采用决策表技术解决)。
|
|
|
|
|
- 在发现“合适”的等价关系之前,可能需要进行多次尝试,就像 NextDate 函 数例子一样。如果不能肯定存在“明显”或“自然”等价关系,最好对任何合理 的实现进行再次预测。
|
|
|
|
|
|
|
|
|
|
## 基于决策表的测试
|
|
|
|
|
|
|
|
|
|
在所有的功能性测试方法中,基于决策表的测试方法是最严格的,因为决策表具有逻辑严格性。
|
|
|
|
|
|
|
|
|
|
### 决策表介绍
|
|
|
|
|
|
|
|
|
|
自从 20 世纪 60 年代初以来,决策表一直被用来表示和分析复杂逻辑关系。决策 61 表很适合描述不同条件集合下采取行动的若干组合的情况。
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
决策表有四个部分:粗竖线左侧是桩部分;右侧是条目部分。横粗线的上面是条件部分,下面是行动部分。因此,我们可以引用条件桩、条件条目、行动桩和行动条目。条目部分中的一列是一条规则。规则只是在规则的条件部分中指示的条件环境下要采取什么行动。在表 3.3 给出的决策表中,如果 c1、c2 和 c3 都为真,则采取行动 a1 和 a2。如果 c1 和 c2 都为真而 c3 为假,则采取行动 a1 和 a3。在 c1 为真 c2 为假的 条件下采取行动 a4,此时规则中的 c3 条目叫做“不关心”条目。不关心条目有两种主 要解释:条件无关或条件不适用。
|
|
|
|
|
|
|
|
|
|
如果有二叉条件(真/假,是/否,0/1 ),则决策表的条件部分是旋转了 90 度的(命 题逻辑)真值表。这种结构能够保证我们考虑了所有可能的条件的组合。如果使用决 策表标识测试用例,那么决策表的这种完备性质能够保证一种完备的测试。所有条件都是二叉条件的决策表叫做有限条目决策表。如果条件可以有多个值,则对应的决策 表叫做扩展条目决策表。 决策表被设计为说明性的,给出的条件没有特别的顺序,而且所选择的行动发生时也没有任何特定顺序。
|
|
|
|
|
|
|
|
|
|
### 决策表表示方法
|
|
|
|
|
|
|
|
|
|
为了使用决策表标识测试用例,我们把条件解释为输入,把行动解释为输出。有时条件最终引用输入的等价类,行动引用被测软件的主要功能处理部分。这时规则就解释为测试用例。由于决策表可以机械地强制为完备的,因此可以有测试用例的完整集合。
|
|
|
|
|
|
|
|
|
|
产生决策表的方法可以有多种。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
在表 3.4 所示的决策表中,给出了不关心条目和不可能规则使用的例子。正如第 一条规则所指示,如果整数 a、b 和 c 不构成三角形,则我们根本不关心可能的相关系。在规则 3、4 和 6 中,如果两对整数相等,则根据传递性,第三对整数也一定相等,因此这些规则不可能满足。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
表 3.5 所示的决策表给出了有关表示方法的另一种考虑:条件的选择可以大大地 扩展决策表的规模。这里将老条件(c1:a、b、c 构成三角形?)扩展为三角形特性的三个不等式的详细表示。如果有一个不等式不成立,则三个整数就不能构成三角形。 我们还可以进一步扩展,因为不等式不成立有两种方式:一条边等于另外两条边的和, 或严格大于另外两条边的和。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
如果条件引用了等价类,则决策表会有一种典型的外观。如表 3.6 所示的决策表来自 NextDate 问题,引用了可能的月份变量相互排斥的可能性。由于一个月份就是一 个等价类,因此不可能有两个条目同时为真的规则。不关心条目(-)的实际含义是“必须失败”。有些决策表使用者用 F 表示这一点。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
不关心条目的使用,对完整决策表的识别方式有微妙的影响。对于有限的条目决策表,如果有 n 个条件,则必须有 2 n 条规则。如果不关心条目实际地表明条件是不相关的,则可以按以下方法统计规则数:没有不关心条目的规则统计为 1 条规则;规则中每出现一个不关心条目,该规则数乘一次 2。表 3.5 所示决策表的规则条目数统 计如表 3.7 所示。请注意,规则总数是 64(正好是应该得到的规则条数)。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
如果将这种简化算法应用于表 3.6 所示的决策表,会得到如表 3.8 所示的规则条数统计。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
应该只有八条规则,所以显然有问题。为了找出问题所在,我们扩展所有三条规则,用可能的 T 或 F 替代“-”,如图 3.9 所示。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
请注意,所有条目都是 T 的规则有三条:规则 1.1、2.1、和 3.1;条目是 T、T、 F 的规则有两条:规则 1.2 和 2.2。类似地,规则 1.3 和 3.2、2.3 和 3.3 也是一样的。 如果去掉这种重复,最后可得到七条规则,缺少的规则是所有条件都是假的规则。这 种处理的结果如表 3.10 所示,表中还给出了不可能出现的规则。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
这种识别完备决策表的能力,使我们在解决冗余性和不一致性方面处于很有利的 地位,表 3.11 给出的决策表是冗余的,因为有三个条件则应该是 2³=8 条规则,此处却有九条规则。(规则 9 和规则 1~4 中某一条相同,是冗余规则。)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
注意规则 9 的行为条目与规则 1~4 的条目相同。只要冗余规则中的行为与决策表相同的部分相同,就不会有什么大问题。如果行为条目不同,例如表 3.12 所示的情况, 则会遇到比较大的问题。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
如表 3.12 所示的决策表被用来处理事务,其中 c1 是真,c2 和 c3 都是假,则规则 4 和规则 9 都适用。我们可以观察到两点:
|
|
|
|
|
|
|
|
|
|
- 规则 4 和规则 9 是不一致的。因为它们的行为集合是不同的。
|
|
|
|
|
- 决策表是非确定的。因为此时不能确定是应该应用规则 4 还是应用规则 9。 因此测试人员在应用决策表技术时要小心使用不关心条目。
|
|
|
|
|
|
|
|
|
|
### 决策表的应用
|
|
|
|
|
|
|
|
|
|
决策表最为突出的优点是,能够将复杂的问题按照各种可能的情况全部列举出来,简明并避免遗漏。因此,利用决策表能够设计出完整的测试用例集合。运用决策表设计测试用例,可以将条件理解为输入,将动作理解为输出。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- **三角形问题的测试用例**
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
使用表 3.5 所示的决策表,可得到 11 个功能性测试用例:3 个不可能测试用例, 3 个测试用例违反三角形性质,1 个测试用例可得到等边三角形,1 个测试用例可得到 不等边三角形,3 个测试用例可得到等腰三角形(如表 3.13 所示)如果扩展决策表以 显示两种违反三角形性质的方式,可以再选三个测试用例(一条边正好等于另外两条边的和)。做到这一点需要做一定的判断,否则规则会呈指数级增长。在这种情况下,最终会再得到很多不关心条目和不可能的规则。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
使用表 3.5 所示的决策表,可得到 11 个功能性测试用例:3 个不可能测试用例, 3 个测试用例违反三角形性质,1 个测试用例可得到等边三角形,1 个测试用例可得到 不等边三角形,3 个测试用例可得到等腰三角形(如表 3.13 所示)如果扩展决策表以 显示两种违反三角形性质的方式,可以再选三个测试用例(一条边正好等于另外两条边的和)。做到这一点需要做一定的判断,否则规则会呈指数级增长。在这种情况下,最终会再得到很多不关心条目和不可能的规则。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- **NextDate 函数测试用例**
|
|
|
|
|
|
|
|
|
|
NextDate 函数可以说明定义域中的依赖性问题,决策表可以突出这种依赖关系, 因此使得它成为基于决策表测试的一个完美例子。前面介绍过 NextDate 函数的等价类 划分。等价类划分的不足之处是机械地选取输入值,可能会产生“奇怪”的测试用例, 如找 2003 年 4 月 31 日的下一天。问题产生的根源是等价类划分和边界值分析测试都 假设了变量是独立的。若变量之间在输入定义域中存在某种逻辑依赖关系,则这些依赖关系在机械地选取输入值时就可能会丢失。决策表方法通过使用“不可能动作”的概念表示条件的不可能组合,使我们能够强调这种依赖关系。
|
|
|
|
|
|
|
|
|
|
为了产生给定日期的下一个日期,NextDate 函数能够使用的操作只有 5 种:day 变量和 month 变量的加 1 和复位操作,year 变量的加 1 操作。
|
|
|
|
|
|
|
|
|
|
在以下等价类集合上建立决策表:
|
|
|
|
|
|
|
|
|
|
- M1: { month: month 有 30 天 }
|
|
|
|
|
- M2: { month: month 有 31 天,12 月除外 }
|
|
|
|
|
- M3: { month: month 是 12 月 }
|
|
|
|
|
- M4: { month: month 是 2 月 }
|
|
|
|
|
- D1: { day: 1≤day≤27 }
|
|
|
|
|
- D2: { day: day = 28 }
|
|
|
|
|
- D3: { day: day = 29 }
|
|
|
|
|
- D4: { day: day = 30 }
|
|
|
|
|
- D5: { day: day = 31 }
|
|
|
|
|
- Y1: { year: year 是闰年 }
|
|
|
|
|
- Y2: { year: year 不是闰年 }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
如表 3.14 所示是决策表,共有 22 条规则。
|
|
|
|
|
|
|
|
|
|
规则 1~5 处理有 30 天的月份,其中不可能规则也列出,如规则 5 处理在有 30 天 的月份中考虑 31 日;规则 6~10 和规则 11~15 处理有 31 天的月份,其中规则 6~10 处 理 12 月之外的月份,规则 11~15 处理 12 月;最后的 7 条规则关注 2 月和闰年问题。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
规则 1~5 处理有 30 天的月份,其中不可能规则也列出,如规则 5 处理在有 30 天 的月份中考虑 31 日;规则 6~10 和规则 11~15 处理有 31 天的月份,其中规则 6~10 处 理 12 月之外的月份,规则 11~15 处理 12 月;最后的 7 条规则关注 2 月和闰年问题。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
可进一步简化这 22 条规则。若决策表中有两条规则的动作项相同,则一定至少 68 有一个条件能够把这两条规则用不关心条件合并。例如,规则 1、2、3 都涉及有 30 天的月份 day 类 D1、D2 和 D3,并且它们的动作项都是 day 加 1,因此可以将规则 1、 2、3 合并。类似地,有 31 天的月份的 day 类 D1、D2、D3 和 D4 也可合并,2 月的 D4 和 D5 也可合并。简化后的决策表如表 3.15 所示。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
根据简化后的决策表 3.15,可设计测试用例,如表 3.16 所示。
|
|
|
|
|
|
|
|
|
|
### 决策表测试适用范围
|
|
|
|
|
|
|
|
|
|
每种测试方法都有适用的范围。基于决策表的测试可能对于某些应用程序,如 NextDate 函数十分有效,但是对于另一些应用程序(如佣金问题)就不是很有效。基 于决策表测试通常适用于要产生大量决策的情况,如三角形问题,或在输入变量之间存在重要的逻辑关系的情况,如 NextDate 函数。
|
|
|
|
|
|
|
|
|
|
一般来说,决策表测试法适用于具有以下特征的应用程序:
|
|
|
|
|
|
|
|
|
|
- if-then-else 逻辑突出;
|
|
|
|
|
- 输入变量之间存在逻辑关系;
|
|
|
|
|
- 涉及输入变量子集的计算;
|
|
|
|
|
- 输入与输出之间存在因果关系。
|
|
|
|
|
|
|
|
|
|
在建立决策表的过程中不容易一步到位,第一次标识的条件和行动往往可能不那么令人满意。与其他技术一样,这时采用迭代会有所帮助。把第一次得到的结果作为铺路石,逐渐改进,直到得到满意的决策表。
|
|
|
|
|
|
|
|
|
|
## 错误推测法
|
|
|
|
|
|
|
|
|
|
错误猜测大多基于经验,需要从边界值分析等其它技术获得帮助。这种技术猜测特定软件类型可能发生的错误类型,并且设计测试用例查出这些错误。对有经验的工程师来说,错误猜测有时是最有效的发现 bug 的测试设计方法。为了更好地利用现成的经验,可以列出一个错误类型的检查表,帮助猜测错误可能发生在程序中的位置, 提高错误猜测的有效性。
|
|
|
|
|
|
|
|
|
|
## 练习题
|
|
|
|
|
|
|
|
|
|
> 分析黑盒测试方法的特点。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
> 健壮等价类测试与标准等价类测试的主要区别是什么?
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
> 试用等价分类法测试党政管理系统中党员出生年月的输入设计是否符合要求,假设出生年月格式为 yyyymmdd。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
> 找零钱最佳组合:假设商店货品价格(R)皆不大于 100 元(且为整数),若顾客付 款在100 元内(P),求找给顾客之最少货币个(张)数?(货币面值 50 元(N50),10 元(N10),5 元(N5),1 元(N1)四种。试根据边界值法设计测试用例。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
> 试为三角形问题中的直角三角形开发一个决策表和相应的测试用例。注意,会有等腰直角三角形。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
> 现有一个学生标准化考试批阅试卷,产生成绩报告的程序。其规格说明如下:程序的输入文件由一些有 80 个字符的记录组成,所有记录分为 3 组,如图:
|
|
|
|
|
>
|
|
|
|
|
> 
|
|
|
|
|
>
|
|
|
|
|
> - 标题:该组只有一个记录,其内容是成绩报告的名字。
|
|
|
|
|
> - 各题的标准答案:每个记录均在第 80 个字符处标以数字 2。该组的记录:
|
|
|
|
|
> - 第一个记录:第 1~3 个字符为试题数(1~999)。第 10~59 个字符是 1~50 题 的标准答案(每个合法字符表示一个答案)。
|
|
|
|
|
> - 第二个记录:是第 51~100 题的标准答案。 …….
|
|
|
|
|
> - 学生的答案:每个记录均在第 80 个字符处标以数字 3。每个学生的答卷在 若干个记录中给出。
|
|
|
|
|
> - 学号:1~9 个字符
|
|
|
|
|
> - 1~50 题的答案:10~59。当大于 50 题时,在第二、三、……个记录中给出。
|
|
|
|
|
> - 学生人数不超过 200,试题数不超过 999。
|
|
|
|
|
>
|
|
|
|
|
> 程序的输出有 4 个报告: a)按学号排列的成绩单,列出每个学生的成绩、名次。 b)按学生成绩排序的成绩单。 c)平均分数及标准偏差的报告。 d)试题分析报告。按试题号排序,列出各题学生答对的百分比。 采用边界值分析方法,分析和设计测试用例。分别考虑输入条件和输出条件,以 及边界条件。采用错误推测法补充设计一些测试用例。
|