黑盒测试: 一直产品的功能设计规格,可以进行测试证明每个实现了的功能是否符合要求。
白盒测试: 一直产品的内部工作过程,可以通过测试证明每种内部操作都符合设计规格要求,所有内部成分是否进行检查
黑盒测试
软件的黑盒测试意味着测试要在软件的接口处进行。这种方法是把测试对象看做一个黑盒子,测试人员完全不考虑程序内部的逻辑构造和内部特性,只依据程序的需求规格说明书,检查程序的功能是否符合它的功能说明。因此黑盒测试又叫功能测试或者数据驱动测试。
黑盒测试主要是为了发现以下几类错误:
1.是否有不正确的遗漏的功能?
2.在接口上,输入是否能正确的接受?能否输出正确的结果?
3.是否有数据结构错误或外部信息访问错误?
4.性能上能否满足要求?
5.是否有初始化或终止性错误?
具体的黑盒测试方法包括等价类划分、因果图、正交实验涉及法、边界分析、判定表驱动法、功能测试等。
等价类划分法
定义
是把所有可能的输入数据,即程序的输入域划分成若干部分(子集),然后从每一个子集中选取少数具有代表性的数据作为测试用例。该方法是一种重要的,常用的黑盒测试用例设计方法。
划分等价类
等价类是指某个输入域的子集合。在该子集合中,各个输入数据对于揭露程序中的错误都是等效的,并合理地假定:测试某等价类的代表值就等于对这一类其它值的测试,因此,可以把全部输入数据合理划分为若干等价类,在每一个等价类中取一个数据作为测试的输入条件就可以用少量代表性的测试数据取得较好的测试结果。等价类划分可有两种不同的情况:有效等价类和无效等价类。
有效等价类
是指对于程序的规格说明来说是合理的、有意义的输入数据构成的集合。利用有效等价类可检验程序是否实现了规格说明中所规定的功能和性能。
无效等价类
与有效等价类的定义恰巧相反。无效等价类指对程序的规格说明是不合理的或无意义的输入数据所构成的集合。对于具体的问题,无效等价类至少应有一个,也可能有多个。
设计测试用例时,要同时考虑这两种等价类。因为软件不仅要能接收合理的数据,也要能经受意外的考验,这样的测试才能确保软件具有更高的可靠性。
划分等价类的标准
-
完备测试、避免冗余;
-
划分等价类重要的是:集合的划分,划分为互不相交的一组子集,而子集的并是整个集合;
-
并是整个集合:完备性;
-
子集互不相交:保证一种形式的无冗余性;
-
同一类中标识(选择)一个测试用例,同一等价类中,往往处理相同,相同处理映射到"相同的执行路径"。
划分等价类的方法
-
在输入条件规定了取值范围或值的个数的情况下,则可以确立一个有效等价类和两个无效等价类。
-
在输入条件规定了输入值的集合或者规定了"必须如何"的条件的情况下,可确立一个有效等价类和一个无效等价类;
-
在输入条件是一个布尔量的情况下,可确定一个有效等价类和一个无效等价类。
-
在规定了输入数据的一组值(假定n个),并且程序要对每一个输入值分别处理的情况下,可确立n个有效等价类和一个无效等价类。例:输入条件说明学历可为:专科、本科、硕士、博士四种之一,则分别取这四种这四个值作为四个有效等价类,另外把四种学历之外的任何学历作为无效等价类。
-
在规定了输入数据必须遵守的规则的情况下,可确立一个有效等价类(符合规则)和若干个无效等价类(从不同角度违反规则);
-
在确知已划分的等价类中各元素在程序处理中的方式不同的情况下,则应再将该等价类进一步的划分为更小的等价类。
设计测试用例
在确立了等价类后,可建立等价类表,列出所有划分出的等价类输入条件:有效等价类、无效等价类,然后从划分出的等价类中按以下三个原则设计测试用例:
-
为每一个等价类规定一个唯一的编号;
-
设计一个新的测试用例,使其尽可能多地覆盖尚未被覆盖地有效等价类,重复这一步,直到所有的有效等价类都被覆盖为止;
-
设计一个新的测试用例,使其仅覆盖一个尚未被覆盖的无效等价类,重复这一步,直到所有的无效等价类都被覆盖为止。
三角形实例
某程序规定:"输入三个整数 a 、 b 、 c 分别作为三边的边长构成三角形。通过程序判定所构成的三角形的类型,当此三角形为一般三角形、等腰三角形及等边三角形时,分别作计算 … "。用等价类划分方法为该程序进行测试用例设计。(三角形问题的复杂之处在于输入与输出之间的关系比较复杂。)
分析题目中给出和隐含的对输入条件的要求:(1)整数 (2)三个数 (3)非零数 (4)正数(5)两边之和大于第三边 (6)等腰 (7)等边
如果 a 、 b 、 c 满足条件( 1 ) ~ ( 4 ),则输出下列四种情况之一:
-
如果不满足条件(5),则程序输出为 " 非三角形 " 。
-
如果三条边相等即满足条件(7),则程序输出为 " 等边三角形 " 。
-
如果只有两条边相等、即满足条件(6),则程序输出为 " 等腰三角形 " 。
-
如果三条边都不相等,则程序输出为 " 一般三角形 " 。
列出等价类表并编号
覆盖有效等价类:
覆盖无效等价类
边界值分析法
定义
边界值分析法就是对输入或输出的边界值进行测试的一种黑盒测试方法。通常边界值分析法是作为对等价类划分法的补充,这种情况下,其测试用例来自等价类的边界。
与等价划分的区别
-
边界值分析不是从某等价类中随便挑一个作为代表,而是使这个等价类的每个边界都要作为测试条件。
-
边界值分析不仅考虑输入条件,还要考虑输出空间产生的测试情况。
边界值分析方法的考虑
长期的测试工作经验告诉我们,大量的错误是发生在输入或输出范围的边界上,而不是发生在输入输出范围的内部。因此针对各种边界情况设计测试用例,可以查出更多的错误。使用边界值分析方法设计测试用例,首先应确定边界情况。通常输入和输出等价类的边界,就是应着重测试的边界情况。应当选取正好等于,刚刚大于或刚刚小于边界的值作为测试数据,而不是选取等价类中的典型值或任意值作为测试数据。
常见的边界值
-
对16-bit 的整数而言 32767 和 -32768 是边界
-
屏幕上光标在最左上、最右下位置
-
报表的第一行和最后一行
-
数组元素的第一个和最后一个
-
循环的第 0 次、第 1 次和倒数第 2 次、最后一次
边界值分析
-
边界值分析使用与等价类划分法相同的划分,只是边界值分析假定错误更多地存在于划分的边界上,因此在等价类的边界上以及两侧的情况设计测试用例。例:测试计算平方根的函数
–输入:实数
–输出:实数
–规格说明:当输入一个0或比0大的数的时候,返回其正平方根;当输入一个小于0的数时,显示错误信息"平方根非法-输入值小于0"并返回0;库函数Print-Line可以用来输出错误信息。 -
等价类划分:
I.可以考虑作出如下划分:
a、输入 (i)<0 和 (ii)>=0
b、输出 (a)>=0 和 (b) Error
II.测试用例有两个:
a、输入4,输出2。对应于 (ii) 和 (a) 。
b、输入-10,输出0和错误提示。对应于 (i) 和 (b) 。 -
边界值分析:划分(ii)的边界为0和最大正实数;划分(i)的边界为最小负实数和0。由此得到以下测试用例:
a、输入 {最小负实数}
b、输入 {绝对值很小的负数}
c、输入 0
d、输入 {绝对值很小的正数}
e、输入 {最大正实数} -
通常情况下,软件测试所包含的边界检验有几种类型:数字、字符、位置、重量、大小、速度、方位、尺寸、空间等。
-
相应地,以上类型的边界值应该在:最大/最小、首位/末位、上/下、最快/最慢、最高/最低、 最短/最长、 空/满等情况下。
-
利用边界值作为测试数据
-
内部边界值分析:在多数情况下,边界值条件是基于应用程序的功能设计而需要考虑的因素,可以从软件的规格说明或常识中得到,也是最终用户可以很容易发现问题的。然而,在测试用例设计过程中,某些边界值条件是不需要呈现给用户的,或者说用户是很难注意到的,但同时确实属于检验范畴内的边界条件,称为内部边界值条件或子边界值条件。
内部边界值条件主要有下面几种
a)数值的边界值检验:计算机是基于二进制进行工作的,因此,软件的任何数值运算都有一定的范围限制。
b)字符的边界值检验:在计算机软件中,字符也是很重要的表示元素,其中ASCII和Unicode是常见的编码方式。下表中列出了一些常用字符对应的ASCII码值。
c)其它边界值检验
基于边界值分析方法选择测试用例的原则
-
如果输入条件规定了值的范围,则应取刚达到这个范围的边界的值,以及刚刚超越这个范围边界的值作为测试输入数据。例如,如果程序的规格说明中规定:“重量在10公斤至50公斤范围内的邮件,其邮费计算公式为……”。作为测试用例,我们应取10及50,还应取10.01,49.99,9.99及50.01等。
-
如果输入条件规定了值的个数,则用最大个数,最小个数,比最小个数少一,比最大个数多一的数作为测试数据。比如,一个输入文件应包括1~255个记录,则测试用例可取1和255,还应取0及256等。
-
将规则1)和2)应用于输出条件,即设计测试用例使输出值达到边界值及其左右的值。例如,某程序的规格说明要求计算出"每月保险金扣除额为0至1165.25元",其测试用例可取0.00及1165.24、还可取一0.01及1165.26等。再如一程序属于情报检索系统,要求每次"最少显示1条、最多显示4条情报摘要",这时我们应考虑的测试用例包括1和4,还应包括0和5等。
-
如果程序的规格说明给出的输入域或输出域是有序集合,则应选取集合的第一个元素和最后一个元素作为测试用例。
-
如果程序中使用了一个内部数据结构,则应当选择这个内部数据结构的边界上的值作为测试用例。
-
分析规格说明,找出其它可能的边界条件。
实例说明
现有一个学生标准化考试批阅试卷,产生成绩报告的程序。其规格说明如下:程序的输入文件由一些有80个字符的记录组成,如右图所示,所有记录分为3组:
①标题:这一组只有一个记录,其内容为输出成绩报告的名字。
②试卷各题标准答案记录:每个记录均在第80个字符处标以数字"2"。该组的第一个记录的第1至第3个字符为题目编号(取值为1一999)。第10至第59个字符给出第1至第50题的答案(每个合法字符表示一个答案)。该组的第2,第3……个记录相应为第51至第100,第101至第150,…题的答案。
③每个学生的答卷描述:该组中每个记录的第80个字符均为数字"3"。每个学生的答卷在若干个记录中给出。如甲的首记录第1至第9字符给出学生姓名及学号,第10至第59字符列出的是甲所做的第1至第50题的答案。若试题数超过50,则第2,第3……纪录分别给出他的第51至第100,第101至第150……题的解答。然后是学生乙的答卷记录。
④学生人数不超过200,试题数不超过999。
⑤程序的输出有4个报告:
a)按学号排列的成绩单,列出每个学生的成绩、名次。
b)按学生成绩排序的成绩单。
c)平均分数及标准偏差的报告。
d)试题分析报告。按试题号排序,列出各题学生答对的百分比。
解答:分别考虑输入条件和输出条件,以及边界条件。给出下表所示的输入条件及相应的测试用例。
输出条件及测试用例表
三角形问题的边界值分析测试用例
在三角形问题描述中,除了要求边长是整数外,没有给出其它的限制条件。在此,我们将三角形每边边长的取范围值设值为[1, 100] 。
错误推测方法
定义
基于经验和直觉推测程序中所有可能存在的各种错误, 从而有针对性的设计测试用例的方法。
错误推测方法的基本思想:
列举出程序中所有可能有的错误和容易发生错误的特殊情况,根据他们选择测试用例。
-
例如, 输入数据和输出数据为0的情况;输入表格为空格或输入表格只有一行。 这些都是容易发生错误的情况。可选择这些情况下的例子作为测试用例。
-
例如,前面例子中成绩报告的程序,采用错误推测法还可补充设计一些测试用例:
I. 程序是否把空格作为回答
II. 在回答记录中混有标准答案记录
III. 除了标题记录外,还有一些的记录最后一个字符即不是2也不是3
IV. 有两个学生的学号相同
V. 试题数是负数。 -
再如,测试一个对线性表(比如数组)进行排序的程序,可推测列出以下几项需要特别测试的情况:
I. 输入的线性表为空表;
II. 表中只含有一个元素;
III. 输入表中所有元素已排好序;
IV. 输入表已按逆序排好;
V. 输入表中部分或全部元素相同。
因果图方法
定义
是一种利用图解法分析输入的各种组合情况,从而设计测试用例的方法,它适合于检查程序输入条件的各种组合情况。
因果图法产生的背景:
等价类划分法和边界值分析方法都是着重考虑输入条件,但没有考虑输入条件的各种组合、输入条件之间的相互制约关系。这样虽然各种输入条件可能出错的情况已经测试到了,但多个输入条件组合起来可能出错的情况却被忽视了。
如果在测试时必须考虑输入条件的各种组合,则可能的组合数目将是天文数字,因此必须考虑采用一种适合于描述多种条件的组合、相应产生多个动作的形式来进行测试用例的设计,这就需要利用因果图(逻辑模型)。
因果图介绍
-
因果图中使用了简单的逻辑符号,以直线联接左右结点。左结点表示输入状态(或称原因),右结点表示输出状态(或称结果)。
-
Ci表示原因,通常置于图的左部;ei表示结果,通常在图的右部。Ci和ei均可取值0或1,0表示某状态不出现,1表示某状态出现。
因果图概念
-
关系
①恒等:若ci是1,则ei也是1;否则ei为0。
②非:若ci是1,则ei是0;否则ei是1。
③或:若c1或c2或c3是1,则ei是1;否则ei为0。“或”可有任意个输入。
④与:若c1和c2都是1,则ei为1;否则ei为0。“与”也可有任意个输入。 -
约束输入状态相互之间还可能存在某些依赖关系,称为约束。例如, 某些输入条件本身不可能同时出现。输出状态之间也往往存在约束。在因果图中,用特定的符号标明这些约束。
-
A.输入条件的约束有以下4类:
① E约束(异):a和b中至多有一个可能为1,即a和b不能同时为1。
② I约束(或):a、b和c中至少有一个必须是1,即 a、b 和c不能同时为0。
③ O约束(唯一);a和b必须有一个,且仅有1个为1。
④R约束(要求):a是1时,b必须是1,即不可能a是1时b是0。
B.输出条件约束类型
输出条件的约束只有M约束(强制):若结果a是1,则结果b强制为0。
采用因果图法设计测试用例的步骤:
-
分析软件规格说明描述中, 那些是原因(即输入条件或输入条件的等价类),那些是结果(即输出条件), 并给每个原因和结果赋予一个标识符。
-
分析软件规格说明描述中的语义,找出原因与结果之间, 原因与原因之间对应的关系,根据这些关系,画出因果图。
-
由于语法或环境限制, 有些原因与原因之间,原因与结果之间的组合情况不可能出现,为表明这些特殊情况, 在因果图上用一些记号表明约束或限制条件。
-
把因果图转换为判定表。
-
把判定表的每一列拿出来作为依据,设计测试用例。
实例说明
例一
某软件规格说明书包含这样的要求:第一列字符必须是A或B,第二列字符必须是一个数字,在此情况下进行文件的修改,但如果第一列字符不正确,则给出信息L;如果第二列字符不是数字,则给出信息M。
-
根据题意,原因和结果如下:
原因:
1——第一列字符是A;
2——第一列字符是B;
3——第二列字符是一数字。
结果:
21——修改文件;
22 ——给出信息L;
23——给出信息M。 -
其对应的因果图如下:
11为中间节点;考虑到原因1和原因2不可能同时为1,因此在因果图上施加E约束。 -
根据因果图建立判定表。
表中8种情况的左面两列情况中,原因①和原因②同时为1,这是不可能出现的,故应排除这两种情况。表的最下一栏给出了6种情况的测试用例,这是我们所需要的数据。
例二
有一个处理单价为5角钱的饮料的自动售货机软件测试用例的设计。其规格说明如下:若投入5角钱或1元钱的硬币,押下〖橙汁〗或〖啤酒〗的按钮,则相应的饮料就送出来。若售货机没有零钱找,则一个显示〖零钱找完〗的红灯亮,这时在投入1元硬币并押下按钮后,饮料不送出来而且1元硬币也退出来;若有零钱找,则显示〖零钱找完〗的红灯灭,在送出饮料的同时退还5角硬币。
-
分析这一段说明,列出原因和结果
原因:
1.售货机有零钱找
2.投入1元硬币
3.投入5角硬币
4.押下橙汁按钮
5.押下啤酒按钮
结果:
21.售货机〖零钱找完〗灯亮
22.退还1元硬币
23.退还5角硬币
24.送出橙汁饮料
25.送出啤酒饮料 -
画出因果图,如图所示。所有原因结点列在左边,所有结果结点列在右边。建立中间结点,表示处理的中间状态。中间结点:
11.投入1元硬币且押下饮料按钮- 押下〖橙汁〗或〖啤酒〗的按钮
- 应当找5角零钱并且售货机有零钱找
- 钱已付清
-
转换成判定表
-
在判定表中,阴影部分表示因违反约束条件的不可能出现的情况,删去。第16列与第32列因什么动作也没做,也删去。最后可根据剩下的16列作为确定测试用例的依据。
判定表驱动分析方法
-
定义:判定表是分析和表达多逻辑条件下执行不同操作的情况的工具。
-
判定表的优点能够将复杂的问题按照各种可能的情况全部列举出来,简明并避免遗漏。因此,利用判定表能够设计出完整的测试用例集合。在一些数据处理问题当中,某些操作的实施依赖于多个逻辑条件的组合,即:针对不同逻辑条件的组合值,分别执行不同的操作。判定表很适合于处理这类问题。
-
"阅读指南”判定表
-
判定表通常由四个部分组成如下图所示。
-
条件桩(Condition Stub):列出了问题得所有条件。通常认为列出的条件的次序无关紧要。
-
动作桩(Action Stub):列出了问题规定可能采取的操作。这些操作的排列顺序没有约束。
-
条件项(Condition Entry):列出针对它左列条件的取值。在所有可能情况下的真假值。
-
动作项(Action Entry):列出在条件项的各种取值情况下应该采取的动作。
-
规则及规则合并
-
规则:任何一个条件组合的特定取值及其相应要执行的操作称为规则。在判定表中贯穿条件项和动作项的一列就是一条规则。显然,判定表中列出多少组条件取值,也就有多少条规则,既条件项和动作项有多少列。
-
化简:就是规则合并有两条或多条规则具有相同的动作,并且其条件项之间存在着极为相似的关系。
正交实验设计方法
利用因果图来设计测试用例时, 作为输入条件的原因与输出结果之间的因果关系,有时很难从软件需求规格说明中得到。往往因果关系非常庞大,以至于据此因果图而得到的测试用例数目多的惊人,给软件测试带来沉重的负担,为了有效地,合理地减少测试的工时与费用,可利用正交实验设计方法进行测试用例的设计。正交实验设计方法:依据Galois理论,从大量的(实验)数据(测试例)中挑选适量的,有代表性的点(例),从而合理地安排实验(测试)的一种科学实验设计方法.类似的方法有:聚类分析方法,因子方法方法等.
利用正交实验设计测试用例的步骤:
-
提取功能说明,构造因子–状态表
把影响实验指标的条件称为因子.而影响实验因子的条件叫因子的状态.利用正交实验设计方法来设计测试用例时,首先要根据被测试软件的规格说明书找出影响其功能实现的操作对象和外部因素,把他们当作因子,而把各个因子的取值当作状态.对软件需求规格说明中的功能要求进行划分,把整体的概要性的功能要求进行层层分解与展开,分解成具体的有相对独立性的基本的功能要求.这样就可以把被测试软件中所有的因子都确定下来,并为确定个因子的权值提供参考的依据.确定因子与状态是设计测试用例的关键.因此要求尽可能全面的正确的确定取值,以确保测试用例的设计作到完整与有效。 -
加权筛选,生成因素分析表
对因子与状态的选择可按其重要程度分别加权.可根据各个因子及状态的作用大小,出现频率的大小以及测试的需要,确定权值的大小。 -
利用正交表构造测试数据集
正交表的推导依据Galois理论(这里省略,需要时可查数理统计方面的教材)。利用正交实验设计方法设计测试用例,比使用等价类划分,边界值分析,因果图等方法有以下优点:节省测试工作工时;可控制生成的测试用例数量;测试用例具有一定的覆盖率。
功能图分析方法
一个程序的功能说明通常由动态说明和静态说明组成。动态说明描述了输入数据的次序或转移的次序。静态说明描述了输入条件与输出条件之间的对应关系。
对于较复杂的程序,由于存在大量的组合情况,因此,仅用静态说明组成的规格说明对于测试来说往往是不够的.必须用动态说明来补充功能说明.
功能图方法是用功能图FD形式化地表示程序的功能说明,并机械地生成功能图的测试用例. 功能图模型由状态迁移图和逻辑功能模型构成.状态迁移图用于表示输入数据序列以及相应的输出数据.在状态迁移图中,由输入数据和当前状态决定输出数据和后续状态.逻辑功能模型用于表示在状态中输入条件和输出条件之间的对应关系.逻辑功能模型只适合于描述静态说明,输出数据仅由输入数据决定.测试用例则是由测试中经过的一系列状态和在每个状态中必须依靠输入/输出数据满足的一对条件组成.功能图方法其实是是一种黑盒白盒混合用例设计方法。
(功能图方法中,要用到逻辑覆盖和路径测试的概念和方法,其属白盒测试方法中 的内容.逻辑覆盖是以程序内部的逻辑结构为基础的测试用例设计方法.该方法要求测试人员对程序的逻辑结构有清楚的了解.由于覆盖测试的目标不同,逻辑覆盖可分为:语句覆盖,判定覆盖,判定-条件覆盖,条件组合覆盖及路径覆盖.下面我们指的逻辑覆盖和路径是功能或系统水平上的,以区别与白盒测试中的程序内部的.)
-
功能图
功能图由状态迁移图和布尔函数组成.状态迁移图用状态和迁移来描述.一个状态指出数据输入的位置(或时间),而迁移则指明状态的改变.同时要依靠判定表或因果图表示的逻辑功能.例,一个简化的自动出纳机ATM的功能图。 -
测试用例生成方法
从功能图生成测试用例,得到的测试用例数是可接受的. 问题的关键的是如何从状态迁移图中选取测试用例. 若用节点代替状态,用弧线代替迁移,则状态迁移图就可转化成一个程序的控制流程图形式.问题就转化为程序的路径测试问题(如白盒测试)问题了. -
测试用例生成规则
为了把状态迁移(测试路径)的测试用例与逻辑模型(局部测试用例)的测试用例组合起来,从功能图生成实用的测试用例,须定义下面的规则.在一个结构化的状态迁移(SST)中,定义三种形式的循环:顺序,选择和重复.但分辨一个状态迁移中的所有循环是有困难的.(其表示图形省略)。 -
从功能图生成测试用例的过程
4.1 生成局部测试用例:在每个状态中,从因果图生成局部测试用例.局部测试用例由原因值(输入数据)组合与对应的结果值(输出数据或状态)构成。
4.2 测试路径生成:利用上面的规则(三种)生成从初始状态到最后状态的测试路径。
4.3 测试用例合成:合成测试路径与功能图中每个状态中的局部测试用例.结果是初始状态到最后状态的一个状态序列,以及每个状态中输入数据与对应输出数据的组合。 -
测试用例的合成算法:采用条件构造树.
场景设计方法
现在的软件几乎都是用事件触发来控制流程的,事件触发时的情景便形成了场景,而同一事件不同的触发顺序和处理结果就形成事件流。这种在软件设计方面的思想也可以引入到软件测试中,可以比较生动地描绘出事件触发时的情景,有利于测试设计者设计测试用例,同时使测试用例更容易理解和执行。基本流和备选流:如下图所示,图中经过用例的每条路径都用基本流和备选流来表示,直黑线表示基本流,是经过用例的最简单的路径。备选流用不同的色彩表示,一个备选流可能从基本流开始,在某个特定条件下执行,然后重新加入基本流中(如备选流1和3);也可能起源于另一个备选流(如备选流2),或者终止用例而不再重新加入到某个流(如备选流2和4)。
实例说明:下图所示是ATM例子的流程示意图。
以下是生成的场景:
用例设计
对于这7个场景中的每一个场景都需要确定测试用例。可以采用矩阵或决策表来确定和管理测试用例。下面显示了一种通用格式,其中各行代表各个测试用例,而各列则代表测试用例的信息。本示例中,对于每个测试用例,存在一个测试用例ID、条件(或说明)、测试用例中涉及的所有数据元素(作为输入或已经存在于数据库中)以及预期结果。
对于这7个场景中的每一个场景都需要确定测试用例。可以采用矩阵或决策表来确定和管理测试用例。下面显示了一种通用格式,其中各行代表各个测试用例,而各列则代表测试用例的信息。本示例中,对于每个测试用例,存在一个测试用例ID、条件(或说明)、测试用例中涉及的所有数据元素(作为输入或已经存在于数据库中)以及预期结果。
数据设计
一旦确定了所有的测试用例,则应对这些用例进行复审和验证以确保其准确且适度,并取消多余或等效的测试用例。测试用例一经认可,就可以确定实际数据值(在测试用例实施矩阵中)并且设定测试数据,如表3-10所示。
白盒测试
软件的白盒测试是对软件的过程性细节做细致的检查。这种方法是把测试对象看做一个打开的盒子,它允许测试人员利用程序内部的逻辑结构及有关信息,设计或者选择测试用例,对程序所有的逻辑路径进行测试。通过在不同点检查程序状态,确定实际状态是否与预期的状态一致。因此白盒测试又称为结构测试或逻辑驱动测试。
白盒测试主要是想对程序模块进行如下检查:
1.对程序模块的所有独立的执行路径至少测试一遍。
2.对所有的逻辑判定,取“真”与取“假”的两种情况都能至少测一遍。
3.在循环的边界和运行的界限内执行循环体
4.测试内部数据结构的有效性等等
白盒测试方法包括:语句覆盖、判定覆盖、条件覆盖、条件组合覆盖、路径覆盖等
逻辑覆盖率:语句覆盖<条件覆盖<判定覆盖<条件-判定覆盖<组合覆盖<路径覆盖
语句覆盖
基本思想:设计用例,使程序中的每个可执行语句至少执行一次。每个可执行语句:每个语句,那么下图中执行为:1->2->3->4
-
优点:可以很直观的从源代码获得用例,无需细分每条判定表达式
-
缺点:由于这种测试方法仅仅针对程序逻辑中显式存在的语句,但对于隐藏的条件是无法测试的,如在多分支的逻辑运算中无法全面考虑。语句覆盖是最弱的逻辑覆盖
判定覆盖
基本思想:设计用例,使得程序中的每一个判断的取真分支和取假分支至少经历一次,即判断真假值均曾被满足
重点是判定(针对于真假判断),覆盖条件:
条件1:T,条件3:F |
或者
条件1:T,条件3:T |
-
优点:判定覆盖比语句覆盖具有更强的测试能力。同时判定覆盖与具有和语句覆盖一样的简单性,无需细分每个判定就可以得到测试用例
-
缺点:往往大部分的测试用例是由多个逻辑条件组合的,若仅仅判断其整个的最终结果,而忽略每个条件的取值情况,必然会遗漏部分测试路径,判定覆盖仍是很弱的逻辑覆盖
条件覆盖
基本思想:设计用例,使每个判断中的每个条件的可能取值至少满足一次
重点是判断语句的条件(针对条件语句)
判断表达式1: |
覆盖条件:
F1,T2,F3,T4 |
我们用条件覆盖的思想就是覆盖T1,T2,T3,T4,F1,F2,F3,F4
-
优点:增加了对条件判断情况的测试,增加了测试路径
-
缺点:条件覆盖不一定包含判定覆盖,例如,上面的测试用例中就不包含判断1的T分支,判断3的F分支。条件覆盖只能保证每个条件语句取值至少有一次为真,而不考虑所有的判定结果
条件–判定覆盖
基本思想:设计用例,使判定条件中的所有可能(条件成立、不成立)至少执行一次取值,同时,所有判断的可能结果(取真,取假),至少执行一次
覆盖条件用例:
T1,T2,T3,T4 |
要满足:T1,T2,T3,T4,F1,F2,F3,F4
-
优点:能同时考虑到判定,条件两种覆盖
-
缺点:未考虑条件的组合情况
组合覆盖
基本思路:设计用例,使所有可能的条件取值组合至少执行一次
重点:所有条件取值的组合
编号 | 覆盖条件取值 |
---|---|
1 | T1,T2 |
2 | T1,F2 |
3 | F1,T2 |
4 | F1,F2 |
5 | T3,T4 |
6 | T3,F4 |
7 | F3,T4 |
8 | F3,F4 |
覆盖条件 | 覆盖组合 |
---|---|
T1,T2 , T3 , T4 | 1,5 |
T1,F2 , T3 , F4 | 2,6 |
F1,T2 , F3 , T4 | 3,7 |
F1,F2 , F3 , F4 | 4,8 |
-
优点:组合覆盖满足了判定覆盖、条件覆盖、和判定、条件覆盖准则。
-
缺点:线性的增加了测试用例的数量
路径覆盖
基本思想:设计测试用例,来覆盖程序中的所有可能执行的路径
继上面的的条件取值表格
覆盖路径 | 覆盖组合 |
---|---|
1-2-4 | 1,5 |
1-2-5 | 1,8 |
1-3-4 | 4,7 |
1-3-5 | 4,8 |
-
优点:这种测试方法可以对程序进行彻底的测试,比前面五种的测试要广
-
缺点:需要设计大量的,复杂的测试用例,使得工作量呈指数增长,不见得能把所有的条件组合都覆盖
代码复杂度
圈复杂度用来描述一段代码“可测性”很好(可测性这里指需要构建完善的覆盖全面的单元测试需要付出多少代价),但它的设计模型很难得出一个很好的“可读性&可维护性”的测量结果
新版soanrqube引入了认知复杂度的概念,这个复杂度指标弥补了圈复杂度的一些不足,能更准确的反映一段代码的理解成本,以及维护这段代码的困难程度。
圈复杂度
圈复杂度(Cyclomatic complexity)是一种代码复杂度的衡量标准,在1976年由Thomas J. McCabe, Sr. 提出,目标是为了指导程序员写出更具可测性和可维护性的代码。
它可以用来衡量一个模块判定结构的复杂程度,数量上表现为独立路径条数,也可以理解为覆盖所有可能的情况最少需要的测试用例数量。
代码圈复杂度的计算方法
通常采用的计算方法为点边计算法(当然还有节点判定法),计算公式为:
V(G) = e – n + 2
e 代表在控制流图中的边的数量(对应代码中顺序结构的部分),n 代表在控制流图中的节点数量,包括起点和终点(注:所有终点只计算一次,即便有多个return或者throw;节点对应代码中的分支语句)
假定有如下这样一段代码:
根据公式 V(G) = e – n + 2 = 12 – 8 + 2 = 6 ,上图的圈复杂段为6。
注:说明一下为什么n = 8,虽然图上的真正节点有12个,但是其中有5个节点为throw、return,这样的节点为end节点,只能记做一个
认知复杂度
圈复杂度最初的目的是用来识别“难以测试和维护的软件模块”,它能算出最少的全覆盖的测试用例量,但是不能测出一个让人满意的“理解难度”。
这是因为同样圈复杂度的代码,不一定会具有相同的可维护性,我们看看下面的两个例子:
上面这两段代码具有相同的圈复杂度,但显然不具有相同的可读性和可维护性性,这就是圈复杂度的不足之处。
因为圈复杂度理论是在1976年提出的,它不包含一些现代的语言结构,比如try-catch、lambda。
并且,每个方法都默认有一个最小圈复杂度1,这就让我们无从得知,一个给定的类如果圈复杂度很高,它是一个大的易维护的类,还是一个很小很复杂的类。
为了解决上述这些问题,所以引入了“认知复杂度”,它将一段代码被阅读和理解时的复杂程度,估算成一个具体数字
认知复杂度评定基本原则
-
对线性的代码逻辑中,出现一个打断逻辑的东西,复杂度+1;
-
当打断逻辑的是一个嵌套时,复杂度+1;
-
忽略简写:把多句代码缩写为一句可读的代码,复杂度不会额外增加;
上面这种描述可能有点抽象,具体一点说,以下控制流结构会导致认知复杂度增加:
for, while, do while, 三元运算符, if/elif/else, catch语句, 跳转语句(goto/break/continue), 以及嵌套的控制流(每一层嵌套复杂度递增)
我们继续拿上面提到的两个例子举例:
圈复杂度对于getWord方法本身会默认有1的复杂度,每多一个case复杂度+1,所以最终圈复杂度为4
而认知复杂度,对于整个 switch 结构只增加1的复杂度,因为从可理解、可维护程度来说,多几个case并不会导致其增加(当然,大量的case也是我们应当尽力去避免的)
我们接着看另外一个例子:
如你所看到的,认知复杂度考虑到了使这个方法比前面提到的getWords()方法更难理解的因素——嵌套以及跳转语句
因此,虽然这两个方法的圈复杂度是一样的,但是它们的认知复杂度数据很好的反映了它们两者在可理解性/可维护性上的差异。
另外,相对于圈复杂度默认所有方法至少有1的复杂度,认知复杂度并没有这样一个评定规则,这对于entity等简单类的复杂度评判会更加友好和客观:
附、代码复杂度与软件质量关系
灰盒测试
灰盒测试,是介于白盒测试与黑盒测试之间,可以这样理解,灰盒测试关注输出对于输入的正确性,同事也关注内部表现,但这种关注不像白盒那样详细、完整,只是通过一些表现性的现象、时间、标志来判断内部的运行状态,有时候输出是正确的,但内部其实已经错误了,这种情况非常多,如果每次都通过白盒测试来操作,效率会很低,因此需要采取这样的一种灰盒测试方法。
Reference
[1] 一次弄懂黑白灰盒测试: https://blog.csdn.net/lemo_ice/article/details/102474858
[2] 八大黑盒测试方法总结【超详细】: https://blog.csdn.net/Gabbana/article/details/108698502#t31
[3] 浅析代码圈复杂度及认知复杂度: https://www.cnblogs.com/tony-g/p/15842247.html
[4] 软件测试复杂度如何度量: https://docs.pingcode.com/baike/3206436
[5] 语句覆盖、条件覆盖、判定覆盖、条件-判定覆盖、组合覆盖、路径覆盖: https://blog.csdn.net/qq_39722988/article/details/90411581