//读书总结
面试时常会问到:“是否做过测试?黑盒还是白盒?怎么做?有什么区别?”----应时刻提醒面试官“我不光是懂,我是真懂”。
做黑盒测试不是在那里点点鼠标键而已,而是有目的地点鼠标键!
软件测试通常分为两类:黑盒测试和白盒测试。
这里介绍黑盒测试及测试用例设计方法:
1.黑盒测试定义:
·(面试题1)什么是黑盒测试?
答:黑盒测试就是测试人员把软件产品(或阶段性产品)看做是一个黑盒。在测试过程中测试人员只需关心对这个软件黑盒进行操作会得到什么样的结果,而不必深入的去了解它的内部实现机制所进行的测试活动。 这样的操作可以是字符串的输入、图片的输入、视频流的输入,甚至可以是事件输入。而不同的输入进入相应的处理软件(即这个黑盒)进行处理之后通常能得到不同的结果。
黑盒测试示例:
黑盒测试活动:只关心输入和想要得到的输出,测试人员只按业务逻辑测试而不必考虑其内部实现。
·(面试题2)为什么要做黑盒测试?
答:验证Verify软件产品是否符合需求文档的设计 + 证实Validate软件产品符合终端用户的需求 。
说明:这也是进行软件测试活动的目的。IEEE中论述中,各项软件测试活动都是围绕以上两个目的展开的。
·(面试题3)你在软件生命周期中的哪些测试阶段用到过黑盒测试?
答:单元测试unit test、组件测试component test、集成测试integration test、系统测试system test、用户验收测试user acceptance test。
通常来说,软件生命周期中的测试阶段按时间顺序可分为单元测试、组件测试、集成测试、系统测试及用户验收测试。在各个测试阶段之间通常还会设置通过条件pass criteria和准入条件entry criteria。一般来说,黑盒测试适用于所有阶段,注意单元测试,一般认为应采用白盒测试,而其实黑盒测试也是其有效方法。因为,我们知道黑盒测试把软件产品看做黑盒,测试人员只关心对其进行的输入和获得的输出,而并不关心其内部实现机制。所以,在单元测试中,将函数看做是一个黑盒(函数黑盒)。一个组件或应用程序正是由这一个个函数黑盒组成的大黑盒。利用黑盒测试用例设计的方法对其输入值域和输出值域进行分析可极大地保证函数的质量。
函数四部分对应:函数名---函数标志;函数体---函数实现,即黑盒;形参表---黑盒的输入;返回值---黑盒的输出。
说明:一个函数除了输出返回值之外还可能有其他输出:
· 函数体有可能处理了函数域以外的全局变量,这时全局变量也成为了这个函数输入和输出的一部分。
· 函数的参数中可能有引用型形参(C:指针,C++:指针/引用,C#/Java:引用类型的引用和值类型的引用),这时被引用的对象实例有可能在函数中被修改,从而成为函数输出的一部分。
函数黑盒示例:
组件或程序是通过层层调用函数来处理用户需求的。当多个函数能够封装成类,进而被组装成一个组件时,即把一个个小的函数黑盒组装成了一个大黑盒,此时就可以对它进行一定的组件测试了。
这时的组件即使不能完成一个完整的功能,也能通过编写驱动函数或桩函数的方法来测试它。
·(面试题4)什么叫打桩,什么叫驱动?
答:(说明)驱动函数:在测试被测函数时,一般需要在一个函数中构造一些实验数据作为传入被测函数的实参,然后再在该函数中调用被测函数,之后检验结果。即调用被测函数的函数为驱动函数,一般为main函数。
桩函数:在测试被测函数时,被测函数可能要调用一个未被实现功能的函数(或一连串函数的调用),这时测试人员可以写一个临时的简单函数以模拟被调函数的部分行为,这样写的临时简单函数调用为桩函数。
驱动函数与桩函数:
我们通过组件暴露的公共接口分析它的输入值域,然后根据其输入值域编写测试数据。之后在驱动程序中调用组件的公共接口,并把测试数据作为参数(或全局变量)传给被测组件。最终获得该组测试数据经处理后所产生的输出。此后就要分析这些输出是否是期望结果以确定该组件是否有缺陷。 之后,被多个测试过的组件将被集成,成为更大的组件直到成为功能齐全的应用程序。这时系统测试就将开始了。从黑盒测试的角度看,这时的软件产品就是一个更大规模的黑盒,而且因为功能齐全,我们就可以直接通过图形用户界面、命令行或该软件产品所提供的其他方式直接对其进行黑盒测试了。 进入用户验收测试阶段,黑盒测试也是最主要的测试方法,大都是从用户的角度出发,而且生产企业大都会邀请用户直接加入到用户体验测试中,以使软件产品更符合用户的习惯。
2.黑盒测试方法
(1)输入值域和输出值域:
输入值域就是所有可能的输入值组合的集合。
输入值域=有效输入值域+无效输入值域,且二者无交集。 同理, 输出值域=有效输出值域+无效输出值域。
注意:在无效输入值域中任何一个输入组合被输入到程序中,程序都必须反馈以一个合理的信息以通知使用者这个输入对应的错误信息提示。
例:模拟学生成绩数据库录入界面,有一个输入框和一个按钮。
---我们知道,学生的成绩一定是≤100而≥0的数。如果出现半分的情况,这个数的小数点后面只能出现5而不会有其他数情况。
总结如下:
①被输入的数是一个实数,且可以没有小数部分,如果有小数点后只能为5或0,取值范围在≥0且≤100。而在计算机中这个数的有效范围为一个≥0且≤100的浮点数,可以没有小数部分,如果有小数点后只能为5或0,符合以上条件的浮点数允许输入。这样的一个有效范围就称作有效输入值域。所以,此例的有效输入值域中有201种输入组合{0,0.5,1,1.5,...,99,99.5,100}。
②取浮点数中的任意值对其进行测试。知道实数的取值范围是无穷大的且连续的,而计算机浮点数是32位的,只有2^32种取值可能。所以,在浮点数域中对此例进行测试,可以找出2^32 - 201个无效的输入组合。所有的无效输入组合就组成了在浮点数域的无效输入值域,且,在这个域中任何一个输入组合被输入到程序中,程序都必须反馈以一个合理的信息以通知使用者这个输入是超出有效范围的。
③由于输入框可以允许用户输入字符,所以,我们可以用键盘上非浮点型字符常量的组合,爆输一番。这样的组合是无穷的,所以这种情况下无效输入值域是无穷大的,且,在这个域中任何一个输入组合被输入到程序中,程序都必须反馈以一个合理的信息以通知使用者这个输入中含有无效的字符。
④可以不输入任何值而直接按按钮,这也是一个无效的输入。而对于这个输入,程序必须将输入为空的信息反馈给使用者。
所以,此例的输入值域= 有效输入值域(201) +无效输入值域(2^32-201+∞+1=∞)。
软件测试的工作不可能通过逐个枚举输入/出值域中的输入/出组合来完成,有一系列的方法来减少工作量。
如: 首先,把输入/出域划分为有效输入/出值域和无效输入/出值域。
然后,等价类划分法将有效输入/出值域和无效输入/出值域进一步划分为更小的集合,每个集合的输入/出组合是等效的。
最后,边界分析值法在每个集合选定使用哪些输入/出值组合作为代表来编写测试用例。
(2)等价类划分Equivalence Partitioning
运用的是对组件的输入值域和输出值域进行划分的模式来设计测试用例。一般可通过对组件的需求文档进行分析得到这些输入值域和输出值域。 对一个等价类中的某一个值进行测试就可以被等效认为对这个等价类中所有的值进行测试。
该设计模式应该包括对输入值域和输出值域的划分。每个被划分出来的等价类应当包含一组值的集合或一个范围之内的值。在每一个等价类中,所有的值对于这个组件来说在某种程度上都是等效的。
在这种设计模式下测试用例将执行(覆盖)各个等价类。这样的等价类包括对有效输入值域和对无效输入值域进行划分所得的等价类,测试用例该可以被设计为用来测试那些无法被推导出的无效输出值。
一个测试用例可以执行(覆盖)任意数量的等价类。
每个测试用例应当包括:对于该组件的输入;该用例所执行(覆盖)的等价类;该用例的期望输出。
等价类划分覆盖率=(已覆盖的等价类的数量/总的等价类数)×100%。 其中,已覆盖的等价类的数量是指设计的测试用例集总共覆盖的等价类数量。总的等价类数是指一个组件的输入/出值域所有可能的等价类的总和。
例:假设有一个组件,为学生的成绩定级。它在其设计文档中被描述为以下内容:
该组件将接收两个有符号整型参数---考试成绩(80分)和平时表现(20分)。该组件将把这两个参数相加。之后根据这个和对其进行定级。经过该组件的运算和判断将输出4个值:
总分大于等于80 --- ‘A’(优秀)
总分大于等于60并小于80 --- ‘B’(良好)
总分大于等于50并小于60 --- ‘C’(补考)
总分小于50 --- ‘D’(重修)
在此,所有输入的考试成绩如果超出其有效值范围,则该组件将返回一个错误消息(error message)的提示消息。
-->首先,划分等价类;然后,设计测试用例来执行(覆盖)每个等价类。
等价类将按照该组件的输入和输出域进行划分,输入/出域中所有的有效值域和无效值域都将被考虑。
①分析该组件的输入域-->两个参数的输入域
· 有效输入值域划分:
0<=平时成绩<=80 |
0<=平时表现<=20 |
· 无效输入值域划分:
考试成绩<0 | 考试成绩>80 |
平时表现<0 | 平时表现>20 |
考试成绩=带小数的浮点数 | 考试成绩=非数字的字符组合 |
平时表现=带小数的浮点数 | 平时表现=非数字的字符组合 |
②分析该组件的输出值域
· 有效输出值域划分: 其中,总分=考试成绩+平时表现
80<=总分<=100 | 将输出 ‘A’ (优秀) |
60<=总分<=80 | 将输出 ‘B’ (良好) |
50<=总分<=60 | 将输出 ‘C’ (补考) |
0<=总分<50 | 将输出 ‘D’ (重修) |
100<总分 | 将输出 ‘error message’ (错误消息) |
总分<0 | 将输出 ‘error message’ (错误消息) |
以上6种情况之外的情况就是该输出域的无效输出了。
· 无效输出很难界定,这里我们将无效输出值域划分为以下等价类:
output = ‘null’ | 等效于 输入的两个参数皆为null |
output = ‘float input’ | 等效于 输入参数至少有一个是浮点数 |
output = ‘non-numeric input’ | 等效于 输入参数至少有一个是非数字 |
③设计测试用例来覆盖以上的各个等价类,采用逐个覆盖方法。
测试用例 | 001 | 002 | 003 |
---|---|---|---|
输入参数1(考试成绩) | 50 | -3 | 85 |
输入参数2(平时表现) | 15 | 15 | 15 |
总分 | 65 | 12 | 100 |
被覆盖的划分(考试成绩相关) | 0<=考试成绩<=80 | 考试成绩<0 | 考试成绩>80 |
输出结果 | B | error message | error message |
测试用例 | 004 | 005 | 006 |
---|---|---|---|
输入参数1(考试成绩) | 70 | 70 | 70 |
输入参数2(平时表现) | 18 | -8 | 25 |
总分 | 88 | 62 | 95 |
被覆盖的划分(平时表现相关) | 0<=平时表现<=20 | 平时表现<0 | 平时表现>20 |
输出结果 | A | error message | error message |
表3 输入参数的其他无效输入值域相关等价类
测试用例 | 007 | 008 | 009 | 010 |
输入参数1(考试成绩) | 70.1 | a | 70 | 70 |
输入参数2(平时表现) | 15 | 15 | 12.5 | good |
总分 | 85.1 | n/a | 82.5 | n/a |
被覆盖的划分 | 考试成绩=带小数的浮点数 | 考试成绩=非数字的字符组合 | 平时表现=带小数的浮点数 | 平时表现=非数字的字符组合 |
输出结果 | float input* | non-numeric input* | float input* | non-numeric input* |
表4 有效输出值域的等价类
测试用例 | 011 | 012 | 013 | 014 | 015 | 016 |
---|---|---|---|---|---|---|
输入参数1(考试成绩) | -5 | 20 | 45 | 50 | 75 | 85 |
输入参数2(平时表现) | -2 | 10 | 10 | 16 | 15 | 25 |
总分 | -7 | 30 | 55 | 66 | 90 | 110 |
被覆盖的划分 | 总分<0 | 0<=总分<50 | 50<=总分<60 | 60<=总分<80 | 80<=总分<=100 | 100<总分 |
输出结果 | error message | D | C | B | A | error message |
测试用例 | 017 | 018 | 019 |
---|---|---|---|
输入参数1(考试成绩) | 12.4 | ww | null |
输入参数2(平时表现) | 16 | as | null |
总分 | 18.4 | 90 | null |
被覆盖的划分 | 输入参数中带小数的浮点数 | 输入参数中非数字的字符组合 | null |
输出结果 | float input* | non-numeric input* | null* |
(3)边界值分析Boundary Value Analysis
运用的是将被测组件的输入值域和输出值域划分为多个有序并有确定边界的集合的模式来设计测试用例。
一般通过对该组件的需求文档进行分析得到这个输入值域和输出值域。
在这个模式下,被划分出来的集合是有序的,而且包含明确的边界。每个被划分出来的集合应当包含一组值或一个取值范围。在每一个被划分出来的集合中,所有的值对于这个组件来说在某种程度上都是等价的。此外,有效值域和无效值域都应当按照这种方式来划分。
所谓边界值就是用来界定各个有序集合之间的边界点。每个被划分出来的集合一般都有一个最大值和一个最小值作为其边界值,而其他的值都在这两个边界值的范围之内。
在边界值分析法的模式下设计出来的测试用例将用于覆盖每个被划分出来的集合的边界点上的值和其相邻值(即,边界点的前一个有序值和边界点的后一个有序值)。所以,对于每一个被确定的边界都有3个值需要覆盖。这样的边界值是对有效输入值域进行划分所得的集合的边界值和对无效输入值域进行划分所得的集合的边界值。另外,测试用例还可以被设计为用来测试那些无法被推导出的无效输出值域的边界值。
每一个运用边界值分析法模式设计的测试用例都应当包括:
对于该组价的输入;该用例所执行(覆盖)的边界值;该用例的期望输出。
边界值覆盖率=(被执行的已确定边界值的数量/总的边界值数)×100%
其中,每一个边界值均对应于测试用例中所覆盖的边界值或其相邻值。
说明:边界值分析基于以下假设:
根据组件的设计文档,该组件的输入值域和输出值域可以被划分为多个集合,通常情况下会把从输入值域和输出值域划分出来的等价类作为需要收集边界点的集合。基于这个模式。设计的测试用例就是用来覆盖这些边界的,即覆盖这些集合的边界点上的边界值及其相邻值。
例:同样对上例所描述的设计文档设计边界值分析模式下的测试用例。
-->首先,划分其等价类;然后,再确定各个等价类的边界,并设计测试用例覆盖它们。
此时等价类将按照该组件的输入和输出域进行划分,输入域和输出域中所有的有效值域和无效值域都将被考虑。
①分析该组件的输入域-->两个参数的输入域
· 有效输入值域划分:
0<=考试成绩<=80 | 0<=平时表现<=20 |
· 无效输入值域划分:
考试成绩<0 | 平时表现<0 |
考试成绩>80 | 平时表现>20 |
-->确定该组件输入值域各个等价类的边界点值及其相邻值:
在边界值分析设计模式下,在每一个被划分的等价类的边界点附件取3个值:
[ 边界点的前一个有序值、边界点值、边界点的后一个有序值 ]
· 还可以划分出该组件的无效输入值域:
考试成绩=带小数的浮点数 | 平时表现=带小数的浮点数 |
考试成绩=非数字的字符组合 | 平时表现=非数字的字符组合 |
但由于无效输入值域不具备“有序”特征,而且这些等价类很难确定其边界点,所以在边界值设计模式下降不对这些等价类设计测试用例。
所以,为考试成绩和平时表现 设计测试用例如下:
测试用例 | 001 | 002 | 003 | 004 | 005 | 006 |
---|---|---|---|---|---|---|
输入参数1(考试成绩) | -1 | 0 | 1 | 79 | 80 | 81 |
输入参数2(平时表现) | 15 | 15 | 15 | 15 | 15 | 15 |
总分 | 14 | 15 | 16 | 94 | 95 | 96 |
被覆盖的边界值(考试成绩相关) | 0 | 0 | 0 | 80 | 80 | 80 |
输出结果 | error message | D | D | A | A | error message |
测试用例 | 007 | 008 | 009 | 010 | 011 | 012 |
---|---|---|---|---|---|---|
输入参数1(考试成绩) | 75 | 75 | 75 | 75 | 75 | 75 |
输入参数2(平时表现) | -1 | 0 | 1 | 19 | 20 | 21 |
总分 | 74 | 75 | 76 | 94 | 95 | 96 |
被覆盖的边界值(平时表现相关) | 0 | 0 | 0 | 20 | 20 | 20 |
输出结果 | error message | B | B | A | A | error message |
②分析该组件的输出值域
· 有效输出值域划分: 其中,总分=考试成绩+平时表现
80<=总分<=100 | 将输出 ‘A’ (优秀) |
60<=总分<=80 | 将输出 ‘B’ (良好) |
50<=总分<=60 | 将输出 ‘C’ (补考) |
0<=总分<50 | 将输出 ‘D’ (重修) |
100<总分 | 将输出 ‘error message’ (错误消息) |
总分<0 | 将输出 ‘error message’ (错误消息) |
以上6种情况之外的情况就是该输出域的无效输出了。
-->确定该组件输出值域各个等价类的边界点值及其相邻值:
[-1,0,1],[49,50,51],[59,60,61],[79,80,81],[99,100,101]
· 无效输出值域划分:
output = ‘null’ | 等效于 输入的两个参数皆为null |
output = ‘float input’ | 等效于 输入参数至少有一个是浮点数 |
output = ‘non-numeric input’ | 等效于 输入参数至少有一个是非数字 |
为输出值域设计测试用例如下:
测试用例 | 013 | 014 | 015 | 016 | 017 | 018 |
---|---|---|---|---|---|---|
输入参数1(考试成绩) | 0 | 0 | 1 | 29 | 25 | 40 |
输入参数2(平时表现) | -1 | 0 | 0 | 20 | 25 | 11 |
总分 | -1 | 0 | 1 | 49 | 50 | 51 |
被覆盖的输出值域边界值 | 0 | 0 | 0 | 50 | 50 | 50 |
输出结果 | error message | D | D | D | C | C |
测试用例 | 019 | 020 | 021 | 022 | 023 | 024 |
---|---|---|---|---|---|---|
输入参数1(考试成绩) | 39 | 49 | 51 | 65 | 72 | 66 |
输入参数2(平时表现) | 20 | 11 | 10 | 14 | 8 | 15 |
总分 | 59 | 60 | 61 | 79 | 80 | 81 |
被覆盖的输出值域边界值 | 60 | 60 | 60 | 80 | 80 | 80 |
输出结果 | C | B | B | B | A | A |
测试用例 | 025 | 026 | 027 |
输入参数1(考试成绩) | 79 | 80 | 81 |
输入参数2(平时表现) | 20 | 20 | 20 |
总分 | 99 | 100 | 101 |
被覆盖的输出值域边界值 | 100 | 100 | 100 |
输出结果 | A | A | error message |
③除了以上被划分的等价类的边界值外,还有一组隐形的边界值未确定。
仔细分析该组件的设计文档时发现,文档中规定两个输入参数是有符号整型。 文档中没有规定存储总分的变量是什么类型,此时假设开发人员把它也认为是有符号整型。在计算机上的有符号整型是有取值范围的:-2^31 ~ 2^31 -1
所以有:
考试成绩<0 | 等价于 -2^31<考试成绩<0 |
考试成绩>80 | 等价于 80<考试成绩<2^31-1 |
平时表现<0 | 等价于 -2^31<平时表现<2^31-1 |
平时表现>20 | 等价于 20<平时表现<2^31-1 |
100<总分 | 等价于 100<总分<2^31-1 |
总分<0 | 等价于 -2^31<总分<0 |
测试用例 | 028 | 029 | 030 | 031 | 032 | 033 |
输入参数1(考试成绩) | -2^31 -1 | -2^31 | -2^31 +1 | 2^32 -2 | 2^31 -1 | 2^31 |
输入参数2(平时表现) | 20 | 20 | 20 | 14 | 8 | 15 |
被覆盖的边界值(考试成绩相关) | -2^31 | -2^31 | -2^31 | 2^31 -1 | 2^31 -1 | 2^31 -1 |
输出结果 | error message | error message | error message | error message | error message | error message |
测试用例 | 034 | 035 | 036 | 037 | 038 | 039 |
输入参数1(考试成绩) | 70 | 70 | 70 | 70 | 70 | 70 |
输入参数2(平时表现) | -2^31 -1 | -2^31 | -2^31 +1 | 2^31 -2 | 2^31 -1 | 2^31 |
被覆盖的边界值(平时表现相关) | -2^31 | -2^31 | -2^31 | 2^31 -1 | 2^31 -1 | 2^31 -1 |
输出结果 | error message | error message | error message | error message | error message | error message |
测试用例 | 040 | 041 | 042 | 043 | 044 | 045 |
输入参数1(考试成绩) | -2^30 | -2^30 | -2^30 +1 | 2^30-1 | 2^30 | 2^30 |
输入参数2(平时表现) | -2^30 -1 | -2^30 | -2^30 | 2^30 -1 | 2^30 -1 | 2^30 |
总分 | -2^32 -1 | -2^31 | -2^31 +1 | 2^31 -2 | 2^31 -1 | 2^31 |
被覆盖的输出值域边界值 | -2^31 | -2^31 | -2^31 | 2^31 -1 | 2^31 -1 | 2^31 -1 |
输出结果 | error message | error message | error message | error message | error message | error message |
对于该组件来说,以上45条测试用例100%的覆盖了其输入值域和输出值域的边界点的值及其相邻值。
(4)状态转换测试法State Transition Testing
应用于以下模式:被测组件拥有多个状态,各个状态之间的转换由事件event来触发,各个状态之间的转换还可能导致一些动作action的产生。在该设计模式下测试用例将执行(覆盖)各个状态之间的转换。通常用状态转换图、状态转换模型、状态转换表来描述被测组件各状态之间的转换。
在该模式下,被测组件应当包括状态、转换、事件、动作、它们之间的联系。其中,各个状态之间是正交的;事件用于触发各状态之间的转换,事件的触发由该组件的输入产生;作为结果,状态的转换可能导致一些动作的产生,从而可能进一步产生输出。
每条测试用例可以覆盖多个转换,但必须包括:该组件的起始状态、对该组件的输入、期望输出、期望的最终状态。
对于每条测试用例中的期望状态,必须描述:起始状态、触发该状态转换至下一状态的事件、该转换所产生的期望动作、转换后的期望状态。下图,一个组件由事件触发而从一个状态转换为另一个状态,并产生输出。
该黑盒技术是基于被测组件涉及状态的转换为模式。下面通过实例来描述如何使用此方法。
例:该组件为一个手机上流媒体播放软件的显示屏幕。
它有4中状态的显示:“显示正在播放的节目(BF)”,“暂停时显示正在播放帧的静止画面(JZ)”,
“停止时显示节目开头第一帧画面(TZ)”,“无信号时显示‘无信号’提示画面(WXH)”。
触发状态转换的输入有:“单击停止按钮”,“单击播放按钮”,“单击暂停按钮”,“屏蔽信号”,“信号恢复”。
状态转换如下:
“单击停止按钮”可以使显示屏幕从“显示正在播放的节目”或“显示正在播放帧的静止画面”状态转换为“显示节目开头第一帧画面”状态。
“单击暂停按钮”可以使显示屏幕从“显示正在播放的节目”状态转换为“显示正在播放帧的静止画面”状态。
“单击播放按钮”可以使显示屏幕从“显示节目开头第一帧画面”或“显示正在播放帧的静止画面”状态转换为“显示正在播放帧的静止画面”。
“屏蔽信号”可以使显示屏幕从“显示正在播放的节目”状态转换为“无信号时显示‘无信号’提示图片”。
“信号恢复”可以使显示屏幕从“无信号时显示‘无信号’提示图片”状态转换为“显示正在播放的节目”。
根据上例组件设计文档中的描述,得到下图转换的结果:
转换后的表格: 表1 转换后的表格
测试用例 | 001 | 002 | 003 | 004 | 005 | 006 | 007 |
起始状态 | JZ | TZ | BF | BF | JZ | BF | WXH |
事件(输入) | 单击停止 | 单击播放 | 单击停止 | 单击暂停 | 单击播放 | 屏蔽信号 | 信号恢复 |
动作(输出) | 停止画面 | 播放节目 | 停止画面 | 静止画面 | 播放节目 | 无信号画面 | 播放节目 |
结束状态 | TZ | BF | TZ | JZ | BF | WXH | BF |
其可以测出比较显而易见的错误转换或错误输出,无法测试到需要进行一系列状态转换才能出现的问题。
提高覆盖级别,将测试用例设计为1-switch覆盖以在一个测试用例中执行多个状态的转换。
在设计该组件的每一个1-switch覆盖的测试用例时,从4个状态中的某一个状态出发,然后进行两次状态的转换并覆盖所有可能的路径。
测试用例 | 008 | 009 | 010 | 011 | 012 | 013 | 014 |
---|---|---|---|---|---|---|---|
起始状态 | WXH | WXH | WXH | BF | BF | BF | BF |
事件(输入) | 单击播放 | 信号恢复 | 信号恢复 | 屏蔽信号 | 单击停止 | 单击暂停 | 单击暂停 |
动作(输出) | 播放节目 | 播放节目 | 播放节目 | 无信号画面 | 停止画面 | 静止画面 | 静止画面 |
下一个状态 | BF | BF | BF | WXH | TZ | JZ | JZ |
事件(输入) | 屏蔽信号 | 单击停止 | 单击暂停 | 信号恢复 | 单击播放 | 单击播放 | 单击停止 |
动作(输出) | 无信号画面 | 停止画面 | 静止画面 | 播放节目 | 播放节目 | 播放节目 | 停止画面 |
最终状态 | WXH | TZ | JZ | BF | BF | BF | TZ |
测试用例 | 015 | 016 | 017 | 018 | 019 | 020 | 021 |
---|---|---|---|---|---|---|---|
起始状态 | TZ | TZ | TZ | JZ | JZ | JZ | JZ |
事件(输入) | 单击播放 | 单击播放 | 单击播放 | 单击暂停 | 单击播放 | 单击播放 | 单击播放 |
动作(输出) | 播放节目 | 播放节目 | 播放节目 | 停止画面 | 播放画面 | 播放画面 | 播放画面 |
下一个状态 | BF | BF | BF | TZ | BF | BF | BF |
事件(输入) | 单击停止 | 屏蔽信号 | 单击暂停 | 单击播放 | 单击暂停 | 单击停止 | 屏蔽信号 |
动作(输出) | 停止画面 | 无信号画面 | 静止画面 | 播放画面 | 静止画面 | 停止画面 | 无信号画面 |
最终状态 | TZ | WXH | JZ | BF | JZ | TZ | WXH |
发现,所有1-switch覆盖测试用例中的状态转换都已包含在0-switch覆盖的测试用例中。实际上,0-swicth覆盖的测试用例中的状态转换是所有n-switch覆盖的测试用例的状态转换全集,但0-switch覆盖的测试用例中的状态转换一般只局限于组件设计文档中的描述。
一般情况下,组件设计文档可能不会显式的描述一些隐藏的状态转换或一些无效的状态转换。即0-switch覆盖乃至n-switch覆盖的测试用例都可能会遗漏这一类隐藏的状态转换或无效的状态转换。
-->通过使用状态表的表格实现找到组件设计文档中未显示的描述一些隐藏的状态转换或一些无效的状态转换。
输入1 | 输入2 | 输入3 | ... ... | |
---|---|---|---|---|
状态1 | 状态/输出对A | 状态/输出对B | 状态/输出对3 | ... ... |
状态2 | 状态/输出对D | 状态/输出对E | 状态/输出对F | ... ... |
状态3 | 状态/输出对G | 状态/输出对H | 状态/输出对1 | ... ... |
... ... | ... ... | ... ... | ... ... | ... ... |
所以,该组件的状态表如下:
点击播放 | 点击停止 | 点击暂停 | 屏蔽信号 | 信号恢复 | |
---|---|---|---|---|---|
BF | NA-1 | TZ/停止画面 | JT/静止画面 | WXH/无信号画面 | NA-2 |
JZ | BF/播放节目 | TZ/停止画面 | NA-3 | NA-4 | NA-5 |
TZ | BF/播放节目 | NA-6 | NA-7 | NA-8 | NA-9 |
WXH | NA-10 | NA-11 | NA-12 | NA-13 | BF/播放节目 |
上述状态表中看到有4种状态(BF、JZ、TZ、WXH)和5种输入(点击播放、点击停止、点击暂停、屏蔽信号、信号恢复),所以有20种状态/输出对的组合。其中,有7种组合是在组件设计文档中被详细描述的,正对应于0-switch覆盖的测试用例中的所有状态变换。其余13种NA表示未在组件设计文档中描述或该状态变换无效。例如,NA-4在“暂停时显示正在播放帧的静止画面”的状态下对其进行“屏蔽信号”,这时组件设计者可选择“媒体播放软件的显示屏幕”显示“静止画面”或“无信号时显示‘无信号’提示画面”,但这并没有在设计文档中被明确描述。
强调:此类的状态转换(NA-4)属于其本身可以有符合逻辑的解释,但由于并不属于显而易见的转换而被忽略,测试人员就是要把这些被忽略的点找出来,并将其提交给设计人员敦促其给出详细的定义,然后再对新的设计文档重新画出状态转换图,重新分析,并重新设计测试用例。
(5)因果图法Cause Effect Graphing
应用于以下模式:被测组件多组因果关系的逻辑组合,每一个原因被表示为包含逻辑真/假的输入或输入组合的条件,每一个结果被表示为包含输出或输出组合的布尔表达式。在该模式下,组件被描述为一个逻辑图,测试人员基于逻辑图开发出一张包含因果关系的判定表。
依照该模式设计的测试用例应当包含定义该组件各个输入与输出之间关系的规则。每一个规则都对应于一个唯一的一组输入组合。
每一个测试用例应当包括:每一个原因的布尔状态(真/假值);每一个结果的布尔状态。
因果图法的覆盖率 =(被执行的规则的数量/规则的总数)×100%
因果的图例:
例:该组件用于处理信用卡刷卡时对不同数额的支付款项进行扣款,并输出扣款后的结果。
持卡人分为短信用户和非短信用户。短信用户的信用卡账户在短信通知限额内扣款(<信用额度),扣款将被执行,持卡人将不会收到银行的短信通知。短信用户账户在超出短信通知限额时扣款,扣款将被执行,银行将发送短信通知持卡人。短信用户和非短信用户的信用卡账户在扣款额高于信用额度时,扣款将不被执行,账户被挂起。
根据组件需求文档,可列出以下原因和结果。
原因: · c1 短信通知限额内扣款
· c2 短信通知限额外,但信用额度内扣款
· c3 短信用户
结果: · e1 执行扣款
· e2 账户挂起
· e3 银行向用户发送短信
所以,该组件对应的因果图如下:
因果图所对应的判定表:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | |
---|---|---|---|---|---|---|---|---|
c1 | T | T | F | F | F | F | T | T |
c2 | F | F | T | T | F | F | T | T |
c3 | F | T | T | F | F | T | T | F |
e1 | T | T | T | T | F | F | NA | NA |
e2 | F | F | F | F | T | T | NA | NA |
e3 | F | F | T | F | F | T | NA | NA |
此后根据判定表写出测试用例(自行完成。
(6)语法测试Syntax Test
运用于某些组件模型,这些组件的输入值有正式定义的语法。
语法本身代表的是一系列的规则,而每条规则规定了一个或一些标记在输入值中所处的位置、出现的频率以及各标记之间的关系。
对该类组件的输入值的语法规则进行分析设计出对该输入值域的有效值域(符合正式语法)和无效值域(不符合正式语法)进行覆盖的测试用例。
①用于覆盖有效值域(符合正式语法)的测试用例应当执行各语法元素规则所派生出来的各个选项分支。该类测试用例应当设计如下:
· 当语法元素含有多个可选择的值时,该语法元素的所有选项都必须有用例覆盖;
· 当语法元素可以重复出现时,测试用例中至少要覆盖以下两个选项:
可重复出现的语法元素最少次数的情况和可重复出现的语法元素出现超过最少次数的情况。
一个测试用例可以执行上述多个选项。每个测试用例包括:对组件的输入;测试用例执行的选项;测试用例的期望输出。
②用于覆盖无效值域(不符合正式语法)的测试用例应当设计如下:
· 设计一张体现语法元素产生常见错误的变体的列表;
· 该变体表中的变化可应用于语法元素以便于产生覆盖无效值域(不符合正式语法)的测试用例;
· 设计测试用例来覆盖所有变体/语法元素组合;
· 应当设计一些测试用例用于覆盖特别的变化。
对于每一个覆盖无效值域的测试用例包括:对组件的输入;被执行的变化;被执行变化所覆盖的语法元素;测试用例的期望输出。
-->采用BNF(Backus Naur Form)范式来表示浮点数的语法:
· 在双引号中的字(“word”)表示这些字符本身。
· 在双引号外的字(有可能有下划线)表示语法部分。
· 尖括号(< >)内包含的为必选项。
· 方括号([ ])内包含的为可选项。
· 大括号({ })内包含的为可重复0至无数次的项。
· 竖线( | )表示在其左右两边任选一项,“OR”。
· ::= 表示 被定义为 。
例:该组件用于将一个被输入的字符串转化成一个浮点数。
①浮点数的语法可以被表示为:
浮点数 ::= <整数>[<小数点><数字组合>] |
整数 ::= [符号]<无符号整数> |
符号 ::= <“+”>|<“-”> |
无符号整数 ::= (<非零数>[数字组合])|<零> |
小数点 ::= <“.”> |
数字组合 ::= {<数字>} |
数字 ::= <零>| <非零数> |
零 ::= <"0"> |
非零数 ::=<"1">|<"2">|<"3">|<"4">|<"5">|<"6">|<"7">|<"8">|<"9">| |
②有效输入
由上表得出:
· 浮点数中有两个选择项: <整数>opt1,<整数>[<小数点><数字组合>]opt2
· 整数中有两个选项:<无符号整数>opt3,[符号]<无符号整数>opt4
· 符号中有两个选项:<“+”>opt5,, <“-”>opt6
· 无符号整数有三个选项:<非零数>[数字组合]opt7,<非零数>opt8,<零>opt9
· 小数点无选项
· 数字组合有两个选项:单个<数字>opt10,多个<数字>opt11
· 数字有两个选项: <零>opt12,<非零数>opt13
· 零无选项
· 非零数有9个选项:每个非零数各为一个选项,记为opt14-opt22
③根据上述有效输入,设计测试用例,共有22个选项需要覆盖。
测试用例 | 被输入浮点数 | 被覆盖的选项 | 测试范围 |
---|---|---|---|
1 | 12 | opt1 | 有效输入 |
2 | 3.14 | opt2 | 有效输入 |
3 | 23 | opt3 | 有效输入 |
4 | 33 | opt4 | 有效输入 |
5 | 43.6 | opt5 | 有效输入 |
6 | -54.43 | opt6 | 有效输入 |
7 | 1787 | opt7 | 有效输入 |
8 | 6 | opt8 | 有效输入 |
9 | 0.1 | opt9 | 有效输入 |
10 | 2.1 | opt10 | 有效输入 |
11 | 4.123457 | opt11 | 有效输入 |
12 | 0 | opt12 | 有效输入 |
13 | 1.1 | opt13 | 有效输入 |
14 | 1.1 | opt14 | 有效输入 |
15 | 2.2 | opt15 | 有效输入 |
16 | 3.3 | opt16 | 有效输入 |
17 | 4.4 | opt17 | 有效输入 |
18 | 5.5 | opt18 | 有效输入 |
19 | 6.6 | opt19 | 有效输入 |
20 | 7.7 | opt20 | 有效输入 |
21 | 8.8 | opt21 | 有效输入 |
22 | 9.9 | opt22 | 有效输入 |
④无效输入
首先,构建一个总的变体列表。
· 变体1: 引入语法元素的无效值
· 变体2: 用其他已定义的语法元素来替代一个元素
· 变体3: 遗漏一个已定义的语法元素
· 变体4: 添加一个额外的元素
然后,将所有变体应用于每一个语法元素,用e_X来代替浮点数定义中的每个语法元素。 变体e_X
浮点数 ::= <整数>[<小数点><数字组合>] e_1 ::=e_2e_3e_4 |
整数 ::= [符号]<无符号整数> e_5::=e_6e_7 |
符号 ::= <“+”>|<“-”> e_8 ::=e_9 |
无符号整数 ::= (<非零数>[数字组合])|<零> e_10 ::=e_11e_12e_13 |
小数点 ::= <“.”> e_1 4::=e_15 |
数字组合 ::= {<数字>} e_16 ::=e_17 |
数字 ::= <零>| <非零数> e_18 ::=e_19e_20 |
零 ::= <"0"> e_21 ::=e_22 |
非零数 ::=<"1">|<"2">|<"3">|<"4">|<"5">|<"6">|<"7">|<"8">|<"9">| e_23 ::=e_24 |
⑤根据所有语法元素的不同变体设计覆盖无效输入的测试用例,其中,省略了一些与表中用例重复的变体/语法用例的组合。
测试用例 | 被输入浮点数 | 被覆盖的变体 | 被覆盖的语法元素 | 测试范围 |
---|---|---|---|---|
1 | a.3 | 变体1 | e_2 | 无效输入 |
2 | 3b2 | 变体1 | e_3 | 无效输入 |
3 | 2.c | 变体1 | e_4 | 无效输入 |
4 | a7.0 | 变体1 | e_6 | 无效输入 |
5 | +b | 变体1 | e_7 | 无效输入 |
6 | 001.9b | 变体1 | e_11 | 无效输入 |
7 | 1t.4 | 变体1 | e_12 | 无效输入 |
8 | ..3 | 变体2 | e_2 | 无效输入 |
9 | 2+3 | 变体2 | e_3 | 无效输入 |
10 | 2.. | 变体2 | e_4 | 无效输入 |
11 | .4.3 | 变体2 | e_6 | 无效输入 |
12 | ++ | 变体2 | e_7 | 无效输入 |
13 | 5..5 | 变体2 | e_12 | 无效输入 |
14 | .4 | 变体3 | e_2 | 无效输入 |
15 | 3. | 变体3 | e_4 | 无效输入 |
16 | - | 变体3 | e_7 | 无效输入 |
17 | . | 变体3 | e_17 | 无效输入 |
18 | 2.s9 | 变体4 | e_1 | 无效输入 |
19 | e+2.3 | 变体4 | e_5 | 无效输入 |
20 | +t3.4 | 变体4 | e_5 | 无效输入 |
21 | +3y.6 | 变体4 | e_5 | 无效输入 |
22 | 4c5.6 | 变体4 | e_11 | 无效输入 |
23 | 345v.8 | 变体4 | e_12 | 无效输入 |
24 | r0.9 | 变体4 | e_13 | 无效输入 |
25 | 0g.7 | 变体4 | e_13 | 无效输入 |