目录

软件测试期末复习要点整理

目录

软件测试期末复习要点整理

黑盒测试指测试人员通过各种输入和观察软件的各种输出结果来发现软件的缺陷,而不关心程序具体如何实现的一种测试方法。

集成测试又叫组装测试,通常在单元测试的基础上,将所有程序模块进行有序的、递增的测试。重点测试不同模块的接口部分。

组合覆盖:通过执行足够多的测试用例,使得程序中每个判定的所有可能的条件取值组合都至少出现一次。

满足组合覆盖的测试用例一定满足判定覆盖、条件覆盖和判定/条件覆盖。

软件可靠性定义为在某个给定时间间隔内,程序按照规格说明成功运行的概率。

1983年美国IEEE 对“软件可靠性”做出了明确定义,此后该定义被美国标准化研究所接受为国家标准,1989年我国也接受该定义为国家标准。该定义包括两方面的含义:

(1)在规定的条件下,在规定的时间内,软件不引起系统失效的概率;

(2)在规定的时间周期内,在所述条件下程序执行所要求的功能的能力;

其中的概率是系统输入和系统使用的函数,也是软件中存在的故障的函数,系统输入将确定是否会遇到已存在的故障(如果故障存在的话)。

  • 软件未达到产品说明书中标明的功能。
  • 软件出现了产品说明书中指明的不会出现的功能。
  • 软件功能超出了产品说明书中指明的范围。
  • 软件未达到产品说明书中指明应达到的目标。
  • 软件测试人员认为软件难以理解和使用、运行速度慢,或最终用户认为不好。

符合以上任意一种情况,即为软件缺陷。

测试用例,英文名为TestCase,缩写为TC,指的是在测试执行之前设计的一套详细的测试方案,包括测试环境、测试步骤、测试数据和预期结果。

当测试人员采用变异技术来评价测试集的充分性或是增强测试集时,这种活动就被称为是变异测试。

白盒测试又叫做结构测试,把程序看成装在一个透明的白盒子里,按照程序内部的逻辑测试程序,检测程序中的主要执行通路是否都能按预定要求正确工作。

回归测试是指软件被修改后重新进行的测试,如重复执行上一个版本测试时的用例,是为了保证对软件所做的修改没有引入新的错误而重复进行的测试。

检查软件能否在不同组合的环境下正常运行,或者软件之间能否正常交互和共享信息。软件兼容性是衡量软件好坏的重要指标之一。

第三方测试主要是指由开发者和用户以外的第三方进行的软件测试,其目的是为了保证测试的客观性。

第三方定义:

  • 狭义:独立的第三方测试机构
  • 广义:非本软件的开发人员

冒烟测试是指在对一个新版本进行系统大规模的测试之前,先验证一下软件的基本功能是否实现,是否具备可测试性。

确认测试又称有效性测试。有效性测试是在模拟的环境下,运用黑盒测试的方法,验证被测软件是否满足需求规格说明书列出的需求。

验收测试指按照项目任务书或合同、供需双方约定的验收依据文档进行的对整个系统的测试与评审,决定是否接收或拒收系统。

测试软件是否达到需求规格说明中规定的各类性能指标,并满足相关的约束和限制条件。

对系统不断施加压力的测试,通过确定一个系统的瓶颈或者不能接收的性能点,获得系统能提供的最大服务级别的测试。

通过在被测系统上不断加压,直到性能指标达到极限,例如“响应时间”超过预定指标或某种资源已经达到饱和状态。

测试软件在没有授权的内部或者外部的用户的攻击或者恶意的破坏时如何进行处理,是否能保证软件和数据的安全。

自动化测试就是通过测试工具或其他手段,按照测试工程师的预定计划对软件产品进行自动化的测试。

软件质量保证是 贯穿软件项目整个生命周期 的有计划和有系统的活动,经常针对整个项目质量计划执行情况进行评估,检查和改进,向管理者、顾客或其他方提供信任,确保项目质量与计划保持一致。

逻辑覆盖是一种以程序内部逻辑结构为依据的用例设计方法,包括语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、条件组合覆盖和路径覆盖等几种覆盖强度各不相同的逻辑覆盖形式。

https://i-blog.csdnimg.cn/blog_migrate/4bc03dede6891acd98e5814b56a132b6.png

图1 软件测试分类

(1)单元测试内容:

  • 模块接口测试
  • 局部数据结构测试
  • 路径测试
  • 错误处理测试
  • 边界测试

(2)测试的方法是为被测试模块编写驱动模块和桩模块来实现被测试单元的可运行。通过驱动模块来模拟被测试模块的上级调用模块,以上级模块调用被测模块的格式驱动被测模块,接收被测模块的测试结构并输出。桩模块则用来代替被测试模块所调用的模块。它的作用是返回被测模块所需的信息。

https://i-blog.csdnimg.cn/blog_migrate/c7b932d5bddd6aa2beac4712af557b58.png

图 2 bug综合评价模型

测试过程中发现的bug,测试人员对其中的bug进行发现、筛选、加权,可以得到最后的一个bug评估模型。

白盒测试法的覆盖标准有逻辑覆盖、循环覆盖和基本路径测试。其中逻辑覆盖包括语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、条件组合覆盖和路径覆盖。六种覆盖标准发现错误的能力呈由弱到强的变化。

(1)语句覆盖每条语句至少执行一次。

(2)判定覆盖每个判定的每个分支至少执行一次。

(3)条件覆盖每个判定的每个条件应取到各个可能的值。

(4)判定/条件覆盖的同时满足判定覆盖条件覆盖

(5)条件组合覆盖每个判定中各条件的每一种组合至少出现一次。

(6)路径覆盖使程序中每一条可能的路径至少执行一次。

(1)软件测试要经过的步骤

单元测试→集成测试→系统测试→验收测试

(2)关系

软件开发是一个自顶向下、逐步细化的过程,而测试过程是依相反顺序自底向上,逐步集成的过程。它对每个程序模块进行单元测试,消除程序模块内部逻辑和功能上的错误和缺陷;对照软件设计进行集成测试,检测和排除子系统或系统结构上的错误;对照需求,进行确认测试;最后从系统全体出发,运行系统,看是否能够满足要求。软件测试与软件开发各阶段的关系如下图所示:

https://i-blog.csdnimg.cn/blog_migrate/2350bb0e5d0875dc0597aa78fa1f681b.png

图 3 软件测试与软件开发各阶段的关系

(1)完全测试程序是不可能的

(2) 软件测试是有风险的

(3) 测试无法显示隐藏的软件故障

(4)存在的故障数量与发现的故障数成正比

(5)杀虫剂现象

(6)并非所有软件故障都能修复

(7)一般不要丢弃测试用例

(8)应避免测试自己编写的程序

(9)软件测试是一项复杂且具有创造性的和需要高度智慧的挑战性任务

类别描述缺陷所属的类型,以便查找对应开发人员,以及后期缺陷分析。类别通常可以分为以下几种情况:

表 1 软件缺陷类型

#类别描述
1界面(UI)界面错误,如界面显示不符合需求、提示信息不合规范等。
2功能(Function)系统功能无效、不相应、不符合需求
3性能(Performance)系统相应过慢、无法承受预期负荷等
4安全性(Security)存在安全隐患的缺陷
5数据(Data)数据导入或设置不正确
6其它(Other)不在上述类别范围的其它错误

https://i-blog.csdnimg.cn/blog_migrate/2d9505b9dafdd1f52b2fcd265241a186.png

图4 测试自动化的基本结构

(1)基于测试阶段的原则

(2)基于测试用例的原则

(3)基于缺陷收敛趋势及缺陷修复率原则

(4)基于验收测试的原则

(5)基于覆盖率的原则

(6)软件项目暂停或终止,则测试活动也相应暂停或终止

(1)交流不充分及沟通不畅

(2)软件需求的变更

(3)软件开发工具的缺陷

(4)软件的复杂性

(5)软件项目的时间压力

(6)程序开发人员的错误

(7)软件项目文档的缺乏

(1) 测试需求的分析和确定

(2) 测试计划

(3)测试设计

(4)测试执行

(5)测试记录和缺陷跟踪

(6)回归测试

(7)测试总结报告

  • 一般地,测试人员识别缺陷,其初始状态是“新建”;

  • 项目经理或技术领导分析缺陷,分配给合适的开发人员来解决,状态流转为“待解决”;

  • 指定的工程师解决缺陷,将其状态跟踪到“已解决”;

  • 测试人员回归该缺陷,如果回归通过,则关闭缺陷,如果回归不通过,则重新打开该缺陷。

    https://i-blog.csdnimg.cn/blog_migrate/a73ac60c1ad47dd2c150f0c9499d6481.png

    图 5 软件缺陷生命周期(PPT)

    https://i-blog.csdnimg.cn/blog_migrate/999e4dc5c7644fae892a8f03ad827c17.png

    图 6 软件缺陷生命周期(课本)

(1)自动化测试的好处

  • 对程序回归测试更方便,尤其是程序修改比较频繁的情况。
  • 建立可靠、重复的测试,减少人为失误,更好地利用资源。
  • 增强测试质量和覆盖率。
  • 执行手工测试不可能完成的任务。

(2)自动化测试的局限性

  • 不能取代手工测试。
  • 发现的问题和缺陷比手工测试要少。
  • 不能用于测试周期很短的项目、不能保证100%的测试覆盖率、不能测试不稳定的软件和软件易用性等。

功能测试是黑盒测试的一方面,它检查实际软件的功能是否符合用户的需求。

功能测试包含:

  • 逻辑功能测试
  • 界面测试
  • 易用性测试
  • 安全测试
  • 兼容性测试

https://i-blog.csdnimg.cn/blog_migrate/2d85c95c6653e68afca0ffdbb4ef51c6.png

图 6 测试用例的范例

等价类划分 边界值划分 错误推测法 因果图法 正交表试验法 场景图 功能图

等价类划分就是解决如何选择适当的数据子集代表整个数据集的问题,通过降低测试的数目去实现“合理的”覆盖,覆盖了更多的可能数据,以发现更多的软件缺陷。

等价类划分法是一种典型的、重要的黑盒测试方法,它将程序所有可能的输入数据(有效的和无效的)划分成若干个等价类。然后从每个部分中选取具有代表性的数据作为测试用例进行合理的分类,测试用例由有效等价类和无效等价类的代表组成,从而保证测试用例具有完整性和代表性。利用这一方法设计测试用例可以不考虑程序的内部结构,以需求规格说明书为依据,选择适当的典型子集,认真分析和推敲说明书中的各项需求,特别是功能需求,尽可能多地发现错误。等价类划分法是一种系统性的确定要输入的测试条件的方法。

等价类是指某个输入域的子集合。

等价类划分为:

  • 有效等价类:指符合《需求规格说明书》,输入合理的数据集合。
  • 无效等价类:指不符合《需求规格说明书》,输入不合理的数据集合。

示例:计算两个1~100之间整数的和。

  1. 等价类划分

    https://i-blog.csdnimg.cn/blog_migrate/2a00815d5c217a956c975bebc97dad74.png

  2. 将输入域分成一个有效等价类(1~100)和两个无效等价类(<1,>100),并为每一个等价类进行编号,然后就可以从每一个等价类中选取一个代表性的数据来测试,设计如下表所示的测试用例:

    https://i-blog.csdnimg.cn/blog_migrate/2afcec6408a59305ee8afb1757093e27.png

  3. 刚才的等价类还不完善,只考虑了输入数据的范围,没有考虑输入数据的类型(我们认为只输入数据,可是最终用户输入什么都有可能)。综合考虑输入数据的类型和范围划分等价类,如下图所示:

    https://i-blog.csdnimg.cn/blog_migrate/d4a922f20743b428774b4f34aa8cb344.png

  4. 等价类划分的测试用例

    https://i-blog.csdnimg.cn/blog_migrate/ff32a0d4d6c0656de8cde2ab21545272.png

  1. 先考虑输入数据的 数据类型 (合法和非法的)
  2. 再考虑 数据范围 (合法类型中的合法区间和非法区间)
  3. 画出 示意图 ,区分等价类
  4. 为每一个等价类 编号
  5. 从一个等价类中选择一个测试数据 构造测试用例
  • 有一个档案管理系统,要求用户输入以年月表示的日期。
  • 条件:日期限定在1990年1月~2049年12月,并规定日期由6位数字字符组成,前4位表示年,后2位表示月。

测试用例

a. 划分等价类并编号,下表为等价类划分的结果:

https://i-blog.csdnimg.cn/blog_migrate/a4182b49151a7cb6e102ed65655f3104.png

b. 设计测试用例,以便覆盖所有的有效等价类。表4列出了3个有效等价类,编号分别为①、⑤、⑧,设计的测试用例如下:

https://i-blog.csdnimg.cn/blog_migrate/1acf3949eacfff89095d81bf87f3093b.png

c. 为每一个无效等价类设计一个测试用例,设计结果如下:

https://i-blog.csdnimg.cn/blog_migrate/a6fce3839602ea1e6e5e65399c6280fc.png

程序的很多错误发生在输入或输出范围的边界上,因此针对各种边界情况设置测试用例,可以发现不少程序缺陷。

边界值分析法就是对输入或输出的边界值进行测试的一种黑盒测试方法。通常边界值分析法是作为对等价类划分法的补充,这种情况下,其测试用例来自等价类的边界。

  • 确定边界情况(输入或输出等价类的边界)
  • 选取正好等于、刚刚大于或刚刚小于边界值作为测试数据

输入要求是1 ~ 100之间的整数,因此自然产生了1和100两个边界。在设计测试用例的时,要重点考虑这两个边界问题。

根据边界值方法,测试用例修改如下:

https://i-blog.csdnimg.cn/blog_migrate/932839d0befe2b20ee40581259c6d598.png

  • 边界值分析不是从某等价类中随便挑一个作为代表,而是这个等价类的每个边界都要作为测试条件。
  • 边界值分析不仅考虑输入条件,还要考虑输出空间产生的测试情况。
  • 文本框接受字符个数,比如用户名长度,密码长度等。
  • 报表的第一行和最后一行。
  • 数组元素的第一个和最后一个。
  • 循环的第 1 次、第 2 次和倒数第 2 次、最后一次。

边界值分析法作为测试方法的一种,在测试范围的边界值上进行考虑,相对来说是比较简便易行的,生成的测试数据成本也很低。但对于整个测试过程来说,它的测试用例不够充分,也不能发现测试变量之间的依赖关系。边界值分析法产生的测试用例不考虑含义和性质,因此只能作为初步测试用例使用。

某保险公司保费计算方式为投保额*保险率,保险率又依点数不同而有差别,10点以上费率为0.6%,10点以下费率为0.1%。保险率和以下参数有关:

  • 年龄:数字 0-150
  • 性别:字符组合,区分大小写
  • 婚姻:字符组合
  • 扶养人:数字 1-9人

注:其中前三个为必填项,最后一个为选填项。

https://i-blog.csdnimg.cn/blog_migrate/d409118e1210065e8c0707fcb1336423.png

(1)考虑等价类

a. 确定输入

  • 输入:年龄、性别、婚姻、抚养人数

b. 确定每个输入的输入条件

  • 年龄:非负整数、0-150、必填
  • 性别:字符组合、区分大小写、MALE或者 FEMALE、必填
  • 婚姻:字符组合、已婚或者未婚、必填
  • 抚养人数:正整数、1-9、选填

c. 对每个输入的输入条件进行等价类划分

https://i-blog.csdnimg.cn/blog_migrate/2ce9848ef9a5c14d352444e4e5f26db2.png

(2)针对每个输入设计数据覆盖等价类

https://i-blog.csdnimg.cn/blog_migrate/e6da941e6f524b079639724883c09dd3.png

https://i-blog.csdnimg.cn/blog_migrate/e2f63bf58711c1519c50e71b8726c362.png

(3)设计用例覆盖多个输入的有效值和无效值

用例编号年龄性别婚姻抚养人数点数
115MALE未婚不填12
225FEMALE已婚89
350MALE未婚511
480FEMALE已婚17
50MALE未婚不填12
619FEMALE未婚不填10
720MALE未婚不填16
839FEMALE已婚69
940MALE已婚79
1059FEMALE已婚97
1160MALE未婚不填12
12150FEMALE已婚9
13-20FEMALE已婚9
1415.5FEMALE已婚9
15aFEMALE已婚9
16&FEMALE已婚9
17-999.5FEMALE已婚9
18180FEMALE已婚9
19不填FEMALE已婚9
20-1FEMALE已婚9
21151FEMALE已婚9
22396553已婚9
2339male已婚9
2439fEMALE已婚9
2539已婚9
2639不填已婚9
2739MALE12349
2839MALE离婚9
2939MALE不填9
3039FEMALE已婚-6
3139FEMALE已婚5.1
3239FEMALE已婚a
3339FEMALE已婚$
3439FEMALE已婚-100
3539FEMALE已婚100
3639FEMALE已婚0
3739FEMALE已婚10

因果图法比较适合输入条件比较多的情况,测试所有的输入条件的排列组合。所谓的原因就是输入,所谓的结果就是输出。

利用因果图导出测试用例需要经过以下几个步骤:

  1. 分析程序规格说明的描述中,哪些是原因,哪些是结果。原因常常是输入条件或输入条件的等价类,而结果是输出条件。
  2. 分析程序规格说明的描述中的语义内容,并将其表示成连接各个原因与各个结果的“因果图”。
  3. 标明约束条件。由于语法或环境的限制,有些原因和结果的组合情况是不可能出现的。
  4. 把因果图转换成判定表(决策表)。
  5. 为判定表中的每一列表示的情况设计测试用例。
  • 恒等:若原因出现,则结果出现;若原因不出现,则结果不出现。

  • 非(~):若原因出现,则结果不出现;若原因不出现,则结果出现。

  • 或(∨):若几个原因中有一个出现,则结果出现;若几个原因都不出现,则结果不出现。

  • 与(∧):若几个原因都出现,结果才出现;若其中有一个原因不出现,则结果不出现。

    https://i-blog.csdnimg.cn/blog_migrate/809432505d2805bb7e90995c4f3b68c3.png

  • E(互斥):表示两个原因不会同时成立,两个中最多有一个可能成立

  • I(包含):表示三个原因中至少有一个必须成立

  • O(惟一):表示两个原因中必须有一个,且仅有一个成立

  • R(要求):表示两个原因,a出现时,b也必须出现,a出现时,b不可能不出现

  • M(屏蔽):两个结果,a为1时,b必须是0,当a为0时,b值不定

    https://i-blog.csdnimg.cn/blog_migrate/ee7d158b85bbdabbece1ef276893ce70.png

有一个处理单价为2.5元的盒装饮料的自动售货机软件。若投入2.5元硬币,按“可乐”、“啤酒”、或“奶茶”按钮,相应的饮料就送出来。若投入的是3元硬币,在送出饮料的同时退还5角硬币。

分析这一段说明,我们可列出原因和结果:

原因(输入):

① 投入2.5元硬币;

② 投入3元;

③ 按“可乐”按钮;

④ 按“啤酒”按钮;

⑤ 按“奶茶”按钮。

中间状态: ① 已投币;②已按钮

结果(输出):

① 退还5角硬币;

② 送出“可乐”饮料;

③ 送出“啤酒”饮料;

④ 送出“奶茶”饮料;

a. 根据原因和结果,可以设计这样一个因果图:

https://i-blog.csdnimg.cn/blog_migrate/c0232c510012b2bb23801620b5557c89.png

b. 因果图转换为判定表:

https://i-blog.csdnimg.cn/blog_migrate/d0b4f133b533bad0662ba1996eeaaa57.png

c. 根据判定表设计测试用例

https://i-blog.csdnimg.cn/blog_migrate/afcc76f99040d70044d2d28e6ab1ac72.png

正交试验设计是研究多因素多水平的又一种设计方法,它是根据正交性从全面试验中挑选出部分有代表性的点进行试验,这些有代表性的点具备了“均匀分散、齐整可比”的特点,正交试验是一种高效率、快速、经济的实验设计方法。

利用正交实验设计方法设计测试用例, 可以控制生成的测试用例数量;设计的测试用例也具有一定的覆盖率和代表性。

正交试验设计法,是一种成对测试交互的系统的统计方法。它提供了一种能对所有变量对的组合进行典型覆盖(均匀分布)的方法。可以从大量的试验点中挑出适量的、有代表性的点,利用“正交表”,合理的安排试验的一种科学的试验设计方法。

  • 行数:正交表中的行的数量,即试验的次数,也是通过正交实验法设计的测试用例的个数。

  • 因素数:正交表中列的数量,即要测试的功能点。

  • 水平数:任何单个因素能够取得的值的最大个数,即要测试功能点的取值个数。

  • 正交表的形式:L行数(水平数因素数) 如:L8(27)

    https://i-blog.csdnimg.cn/blog_migrate/4274aab1ba8ff38cc41cb71849701da0.png

  1. 有哪些因素(功能点)
  2. 每个因素有哪几个水平(功能点的取值)
  3. 选择一个合适的正交表
  4. 把变量的值映射到表中
  5. 把每一行的各因素水平的组合作为一个测试用例
  6. 加上你认为可疑且没有在表中出现的组合
  • 考虑因素(功能点)的个数
  • 考虑因素水平(功能点的取值)的个数
  • 考虑正交表的行数
  • 取行数最少的一个
  • 因素数(变量)、水平数(变量值)相符:因素数与水平数刚好符合正交表。
  • 因素数不相同:如果因素数不同的话,可以采用包含的方法,在正交表公式中找到包含该情况的公式,如果有N个符合条件的公式,那么选取行数最少的公式。
  • 水平数不相同:采用包含和组合的方法选取合适的正交表公式。

视图选项卡上的“显示/隐藏”组中有3个可用选项:

https://i-blog.csdnimg.cn/blog_migrate/0e709cd431bf23002ba238a2b0b4e26f.png

  • 有3个因素:网格线、编辑栏、标题
  • 每个因素有2个水平:选与不选

a. 选择正交表的分析

  1. 表中的因素数>=3;
  2. 表中至少有3个因素数的水平数>=2;
  3. 行数取最少的一个。
  4. 从正交表公式中开始查找,结果为:L4(23)

利用正交表设计测试用例,我们得到的测试用例个数是n=3*(2-1)+1=4(这个公式就是(因素数*(最大水平数-1)+1)),对于三因素两水平的刚好有L4(2^3)的正交表可以套用。

b. 正交表变量的映射

  • 网格线:0 → 选,1 → 不选

  • 编辑栏:0 → 选,1 → 不选

  • 标 题:0 → 选,1 → 不选

    https://i-blog.csdnimg.cn/blog_migrate/c5e39a40b6e081fe3eedd401f241ebd7.png

c. 测试用例

  1. 选中网格线、选中编辑栏、选中标题
  2. 选中网格线、不选编辑栏、不选标题
  3. 不选网格线、选中编辑栏、不选标题
  4. 不选网格线、不选编辑栏、选中标题

增补测试用例

  5. 不选风格线、不选编辑栏、不选标题

测试用例的减少数: 8 → 5

根据PowerPoint的打印功能的描述设计测试用例,功能描述如下:

  • 打印范围分:全部、当前幻灯片、给定范围
  • 打印内容分:幻灯片、讲义、备注页、大纲视图
  • 打印颜色/灰度分:颜色、灰度、黑白
  • 打印效果分:幻灯片加框、幻灯片不加框

a. 案例分析

根据以上提到的功能说明,构造因子状态表,得到因子状态:

https://i-blog.csdnimg.cn/blog_migrate/adfc212937f6bd8a90a3328a6db13fab.png

将中文字转换成字母的因子状态表:

https://i-blog.csdnimg.cn/blog_migrate/34c50f314fa620ae57d58ab2021439c4.png

选择正交表的分析:

  1. 表中的因素数>=4;
  2. 表中至少有4个因素数的水平数>=2;
  3. 行数取最少的一个。
  4. 从正交表公式中开始查找,结果为: L16(45)

注:此案例中有四个被测对象,每个被测对象的状态都不一样。

b. 正交表

https://i-blog.csdnimg.cn/blog_migrate/2d98214f35dffc3fbb7de6f2b61e5071.png

c. 用字母代替的正交表

https://i-blog.csdnimg.cn/blog_migrate/acb86d1f113c2297a64e790659d64bfd.png

通过分析:第5列没有意义可以删掉,由于四个因素里有三个的水平值小于3,所以从第13行到16行的测试用例可以忽略。

d. 测试用例

https://i-blog.csdnimg.cn/blog_migrate/df5033fe5635a8db1afd598782be99ec.png

用例场景是用来描述流经用例路径的过程,这个过程从开始到结束遍历用例中所有基本流和备选流。

算法流程图是针对程序的内部结构的,而黑盒测试的流程图是针对整个系统业务功能流程的。

流程图法的步骤:

  • 第一步:详细了解需求
  • 第二步:根据需求说明或界面原型,找出业务流程的各个页面以及各页面之间的流转关系
  • 第三步:画出业务流程
  • 第四步:写用例,覆盖所有的路径分支
  • 逻辑覆盖法(逻辑驱动测试)
  • 基本路径测试方法
  • 控制流图(可简称流图)是对程序流程图进行简化后得到的,它可以更加突出的表示程序控制流的结构。

  • 控制流图中包括两种图形符号:节点和控制流线。

  • 节点由带标号的圆圈表示,可代表一个或多个语句、一个处理框序列和一个条件判定框(假设不包含复合条件)。

  • 控制流线由带箭头的弧或线表示,可称为边。它代表程序中的控制流。

    https://i-blog.csdnimg.cn/blog_migrate/9921d394585705fe1b1f4fbcc77963b0.png

    其中,包含条件的节点被称为 判定节点 (也叫谓词节点),由判定节点发出的边必须终止于某一个节点,由边和节点所限定的范围被称为 区域

  • 对于复合条件,则可将其分解为多个单个条件,并映射成控制流图。

a. 概述

  • 环形复杂度也称为圈复杂度,它是一种为程序逻辑复杂度提供定量尺度的软件度量。
  • 环形复杂度的应用——可以将环形复杂度用于基本路径方法,它可以提供:程序基本集的独立路径数量;确保所有语句至少执行一次的测试数量的上界。
  • 独立路径是指程序中至少引入了一个新的处理语句集合或一个新条件的程序通路。采用流图的术语,即独立路径必须至少包含一条在本次定义路径之前不曾用过的边。
  • 测试可以被设计为基本路径集的执行过程,但基本路径集通常并不唯一。

b. 计算环形复杂度的方法

  • 环形复杂度以图论为基础,为我们提供了非常有用的软件度量。可用如下三种方法之一来计算环形复杂度:

  • 控制流图中区域的数量对应于环形复杂度。

  • 给定控制流图G的环形复杂度—V(G),定义为V(G) = E-N+2.

    其中,E是控制流图中边的数量,N是控制流图中的节点数量。

  • 给定控制流图G的环形复杂度—V(G),也可定义为V(G) = P+1.

    其中,P是控制流图G中判定节点的数量。

  • 图矩阵是控制流图的矩阵表示形式。

  • 图矩阵是一个方形矩阵,其维数等于控制流图的节点数。矩阵中的每列和每行都对应于标识的节点,矩阵元素对应于节点间的边。

  • 通常,控制流图中的结点用数字标识,边则用字母标识。如果在控制流图中从第 i

    个结点到第 j 个结点有一个标识为 x 的边相连接,则在对应图矩阵的第 i 行第 j

    列有一个非空的元素 x 。

https://i-blog.csdnimg.cn/blog_migrate/637f29315b14c9eed731d8b63c7c103a.png

根据上图给出的程序流程图,完成以下要求:

(1)画出相应的控制流图。

(2)计算环形复杂度。

(3)给出相应的图矩阵。

(4)找出程序的独立路径集合。

https://i-blog.csdnimg.cn/blog_migrate/31a12a82377f8051035eeeb134e5595b.png

对于复合条件,则可将其分解为多个单个条件,并映射成控制流图。

  • 测试覆盖率:用于确定测试所执行到的覆盖项的百分比。其中的覆盖项是指作为测试基础的一个入口或属性,比如语句、分支、条件等。
  • 测试覆盖率可以表示出测试的充分性,在测试分析报告中可以作为量化指标的依据,测试覆盖率越高效果越好。但覆盖率不是目标,只是一种手段。
  • 测试覆盖率包括 功能点覆盖率结构覆盖率
  • 功能点覆盖率大致用于表示软件已经实现的功能与软件需要实现的功能之间的比例关系。
  • 结构覆盖率 包括 语句覆盖率分支覆盖率循环覆盖率路径覆盖率 等等。
  • 根据覆盖目标的不同,逻辑覆盖又可分为语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、组合覆盖和路径覆盖。

  • 语句覆盖:选择足够多的测试用例,使得程序中的每个可执行语句至少执行一次。

  • 判定覆盖:通过执行足够的测试用例,使得程序中的每个判定至少都获得一次“真”值和“假”值,

    也就是使程序中的每个取“真”分支和取“假”分支至少均经历一次,也称为“分支覆盖”。

  • 条件覆盖:设计足够多的测试用例,使得程序中每个判定包含的每个条件的可能取值(真/假)都至少满足一次。

  • 判定/条件覆盖:设计足够多的测试用例,使得程序中每个判定包含的每个条件的所有情况(真/假)至少出现一次,并且每个判定本身的判定结果(真/假)也至少出现一次。

    ——满足判定/条件覆盖的测试用例一定同时满足判定覆盖和条件覆盖。

  • 组合覆盖:通过执行足够的测试用例,使得程序中每个判定的所有可能的条件取值组合都至少出现一次。

    ——满足组合覆盖的测试用例一定满足判定覆盖、条件覆盖和判定/条件覆盖。

  • 路径覆盖:设计足够多的测试用例,要求覆盖程序中所有可能的路径。

    https://i-blog.csdnimg.cn/blog_migrate/95fe4e0204e619543e30871fa1268bd7.png

Void DoWork (int x, int y, int z)
{
   Int k=0, j=0; 
   if ( (x > 3) && (z < 10) ) {
       k = x * y - 1;   //语句块1 
       j = sqrt(k);   
   }   
   if ( (x == 4) || (y > 5) ) {
       j = x * y + 10;   //语句块2
} 
   j = j % 3;    //语句块3
}

https://i-blog.csdnimg.cn/blog_migrate/fec16ca526d72272304fbeac5bdef82a.png

  • 要实现DoWork函数的语句覆盖,只需设计一个测试用例就可以覆盖程序中的所有可执行语句。
  • 测试用例输入为:{ x=4、y=5、z=5 }
  • 程序执行的路径是:abd
  • 分析:语句覆盖可以保证程序中的每个语句都得到执行,但发现不了判定中逻辑运算的错误,即它并不是一种充分的检验方法。例如在第一个判定((x>3)&&(z<10))中把“&&”错误的写成了“||”,这时仍使用该测试用例,则程序仍会按照流程图上的路径abd执行。可以说语句覆盖是最弱的逻辑覆盖准则。
  • 要实现DoWork函数的判定覆盖,需要设计两个测试用例。

  • 测试用例的输入为:{x=4、y=5、z=5};{x=2、y=5、z=5}

  • 程序执行的路径分别是:abd;ace

  • 分析:上述两个测试用例不仅满足了判定覆盖,同时还做到语句覆盖。从这点看似乎判定覆盖比语句覆盖更强一些,但仍然无法确定判定内部条件的错误。例如把第二个判定中的条件y>5错误写为y<5,使用上述测试用例,照样能按原路径执行而不影响结果。因此,需要有更强的逻辑覆盖准则去检验判定内的条件。

  • 说明:以上仅考虑了两出口的判断,我们还应把判定覆盖准则扩充到多出口判断(如Case语句)的情况。因此,判定覆盖更为广泛的含义应该是使得每一个判定获得每一种可能的结果至少一次。

    https://i-blog.csdnimg.cn/blog_migrate/00f8ee452d999af591af7b3d9b73a692.png

  • 在实际程序代码中,一个判定中通常都包含若干条件。条件覆盖的目的是设计若干测试用例,在执行被测程序后,要使每个判定中每个条件的可能值至少满足一次。

  • 对DoWork函数的各个判定的各种条件取值加以标记。

  • 对于第一个判定( (x>3)&&(z<10) ):

    条件x>3 取真值记为T1,取假值记为-T1

    条件z<10 取真值记为T2,取假值记为-T2

  • 对于第二个判定( (x==4)||(y>5) ):

    条件x==4 取真值记为T3,取假值记为-T3

    条件y>5 取真值记为T4,取假值记为-T4

  • 根据条件覆盖的基本思想,要使上述4个条件可能产生的8种情况至少满足一次,设计测试用例如下:

    https://i-blog.csdnimg.cn/blog_migrate/1d7d8b722d94ce207a99b80a0695418c.png

  • 分析:上面这组测试用例不但覆盖了4个条件的全部8种情况,而且将两个判定的4个分支b、c、d、e也同时覆盖了,即同时达到了条件覆盖和判定覆盖。

  • 说明:虽然前面的一组测试用例同时达到了条件覆盖和判定覆盖,但是, 并不是说满足条件覆盖就一定能满足判定覆盖 。如果设计了下表中的这组测试用例,则虽然满足了条件覆盖,但只是覆盖了程序中第一个判定的取假分支c和第二个判定的取真分支d,不满足判定覆盖的要求。

    https://i-blog.csdnimg.cn/blog_migrate/ab5b2f618c4e4db729c6718bdd0d1a71.png

  • 判定/条件覆盖实际上是将判定覆盖和条件覆盖结合起来的一种方法,即:设计足够的测试用例,使得判定中每个条件的所有可能取值至少满足一次,同时每个判定的可能结果也至少出现一次。

  • 根据判定/条件覆盖的基本思想,只需设计以下两个测试用例便可以覆盖4个条件的8种取值以及4个判定分支。

    https://i-blog.csdnimg.cn/blog_migrate/79b3fb62e7459b57b1457adb868eff3d.png

  • 分析:从表面上看,判定/条件覆盖测试了各个判定中的所有条件的取值,但实际上,编译器在检查含有多个条件的逻辑表达式时,某些情况下的某些条件将会被其它条件所掩盖。因此, 判定/条件覆盖也不一定能够完全检查出逻辑表达式中的错误

  • 例如:对于第一个判定(x>3)&&(z<10)来说,必须x>3和z<10这两个条件同时满足才能确定该判定为真。如果x>3为假,则编译器将不再检查z<10这个条件,那么即使这个条件有错也无法被发现。对于第二个判定(x 4)||(y>5)来说,若条件x 4满足,就认为该判定为真,这时将不会再检查y>5,那么同样也无法发现这个条件中的错误。

  • 组合覆盖的目的是要使设计的测试用例能覆盖每一个判定的所有可能的条件取值组合。

  • 对DoWork函数中的各个判定的条件取值组合加以标记:

      1、x\>3, z\<10 记做T1 T2,第一个判定的取真分支 
      2、x\>3, z\>=10 记做T1 -T2,第一个判定的取假分支
      3、x\<=3, z\<10 记做-T1 T2,第一个判定的取假分支
      4、x\<=3, z\>=10 记做-T1 -T2,第一个判定的取假分支
      5、x==4, y\>5 记做T3 T4,第二个判定的取真分支
      6、x==4, y\<=5 记做T3 -T4,第二个判定的取真分支
      7、x!=4, y\>5 记做-T3 T4,第二个判定的取真分支
      8、x!=4, y\<=5 记做-T3 -T4,第二个判定的取假分支
  • 根据组合覆盖的基本思想,设计测试用例如下:

    https://i-blog.csdnimg.cn/blog_migrate/0787f767a885a246d6879b32bdb79ff1.png

  • 分析:上面这组测试用例覆盖了所有8种条件取值的组合,覆盖了所有判定的真假分支,但是却丢失了一条路径abe。

  • 前面提到的5种逻辑覆盖都未涉及到路径的覆盖。事实上,只有当程序中的每一条路径都受到了检验,才能使程序受到全面检验。路径覆盖的目的就是要使设计的测试用例能覆盖被测程序中所有可能的路径。

  • 根据路径覆盖的基本思想,在满足组合覆盖的测试用例中修改其中一个测试用例,则可以实现路径覆盖:

    https://i-blog.csdnimg.cn/blog_migrate/edcd5797beedf19565b4036f3db1ce91.png

  • 分析:虽然前面一组测试用例满足了路径覆盖,但并没有覆盖程序中所有的条件组合(丢失了组合3和7),即 满足路径覆盖的测试用例并不一定满足组合覆盖

  • 说明:

    • 对于比较简单的小程序,实现路径覆盖是可能做到的。但如果程序中出现较多判断和较多循环,可能的路径数目将会急剧增长,要在测试中覆盖所有的路径是无法实现的。为了解决这个难题,只有把覆盖路径数量压缩到一定的限度内,如程序中的循环体只执行一次。
    • 在实际测试中,即使对于路径数很有限的程序已经做到路径覆盖,仍然不能保证被测试程序的正确性,还需要采用其他测试方法进行补充。

为以下流程图所示的程序段设计一组测试用例,要求分别满足语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、组合覆盖和路径覆盖。

https://i-blog.csdnimg.cn/blog_migrate/b57355c4cf749d5021f631956fa11006.png

  • 由于传统的结构化度量没有考虑面向对象的一些特性(如多态、继承和封装等),所以在面向对象领域,传统的结构化覆盖必须被加强,以满足面向对象特性。
  • 继承上下文覆盖考虑在每个类的上下文内获得的覆盖率级别。它是扩展到面向对象领域里的一种覆盖率度量方法,用于度量在系统中的多态调用被测试得多好。
  • 继承上下文定义将基类上下文内例行程序的执行作为独立于继承类上下文内例行程序的执行。同样,它们在考虑继承类上下文内例行程序的执行也独立于基类上下文内例行程序的执行。为了获得100%继承上下文覆盖,代码必须在每个适当的上下文内被完全执行。
  • 在绝大多数面向对象的系统中存在这样的一些类:这些类的对象可以存在于众多不同状态中的任何一种,并且由于类的行为依赖于状态,每个类的行为在每个可能的状态中其性质是不同的。
  • 基于状态的上下文覆盖对应于被测类对象的潜在状态。
  • 这样基于状态的上下文覆盖把一个状态上下文内的一个例行程序的执行认为是独立于另一个状态内相同例行程序的执行。为了达到100%的基于状态的上下文覆盖,例行程序必须在每个适当的上下文(状态)内被执行。
  • ESTCA覆盖准则:在容易发生问题的地方设计测试用例,即重视程序中谓词(条件判断)的取值。

  • ESTCA覆盖准则是一套错误敏感用例分析规则。这一规则虽然并不完备,但在普通程序中却是有效的。原因在于这是一种经验型的覆盖准则,规则本身针对了程序编写人员容易发生的错误,或是围绕着发生错误的频繁区域,从而提高了发现错误的命中率。具体规则如下:

    • [规则1] 对于A rel B型 (rel可以是<、= 或 >)

      的分支谓词,应适当的选择A与B的值,使得测试执行到该分支语句时,A<B、A=B、A>B的情况分别出现一次。

      ——这是为了检测逻辑符号写错的情况,如将“A<B”错写为“A>B”。

    • [规则2] 对于A rel C型 (rel可以是>或<, A是变量,C是常量)的分支谓词:当rel为<时,应适当的选择A的值,使A=C-M

      (M是距C最小的机器容许正数,若A和C都为正整数时,M=1);当rel为>时,应适当的选择A的值,使A=C+M。

      ——这是为了检测“差1”之类的错误,如“A>1”错写成“A>0”。

    • [规则3] 对外部输入变量赋值,使其在每一个测试用例中均有不同的值与符号,并与同一组测试用例中其他变量的值与符号不同。

      ——这是为了检测程序语句中的错误,如应该引用某一变量而错成引用另一个常量。

  • 基于LCSAJ与路径的关系,提出了层次LCSAJ覆盖准则。它是一个分层的覆盖准则,可以概括的描述为:

    • 第一层 — 语句覆盖。
    • 第二层 — 分支覆盖。
    • 第三层 — LCSAJ覆盖,即程序中的每一个LCSAJ都至少在测试中经历过一次。
    • 第四层 — 两两LCSAJ覆盖,即程序中的每两个相连的LCSAJ组合起来在测试中都要经历一次。
    • 第n+2层 — 每n个首尾相连的LCSAJ组合在测试中都要经历一次。
  • 在实施测试时,若要实现上述的层次LCSAJ覆盖,需要产生被测程序的所有LCSAJ。

  • 为了满足路径覆盖,必须首先确定具体的路径以及路径的个数。我们通常采用控制流图的边(弧)序列和节点序列表示某一条具体路径,更为概括的表示方法为:

    1. 弧a和弧b相乘,表示为ab,它表明路径是先经历弧a,接着再经历弧b,弧a和弧b是先后相接的。
    2. 弧a和弧b相加,表示为a+b,它表明两条弧是“或”的关系,是并行的路段。
  • 路径数的计算:

    在路径表达式中,将所有弧均以数值1来代替,再进行表达式的相乘和相加运算,最后得到的数值即为该程序的路径数。

  • 路径测试就是从一个程序的入口开始,执行所经历的各个语句的完整过程。从广义的角度讲,任何有关路径分析的测试都可以被称为路径测试。
  • 完成路径测试的理想情况是做到路径覆盖,但对于复杂性大的程序要做到所有路径覆盖(测试所有可执行路径)是不可能的。
  • 在不能做到所有路径覆盖的前提下,如果某一程序的每一个独立路径都被测试过,那么可以认为程序中的每个语句都已经检验过了,即达到了语句覆盖。这种测试方法就是通常所说的基本路径测试方法。

基本路径测试方法是在控制流图的基础上,通过分析控制结构的环形复杂度,导出执行路径的基本集,再从该基本集设计测试用例。基本路径测试方法包括以下4个步骤:

  1. 画出程序的控制流图。
  2. 计算程序的环形复杂度,导出程序基本路径集中的独立路径条数,这是确定程序中每个可执行语句至少执行一次所必须的测试用例数目的最小数目。
  3. 导出基本路径集,确定程序的独立路径。
  4. 根据(3)中的独立路径,设计测试用例的输入数据和预期输出。
void  Sort ( int  iRecordNum, int iType )
1 {  
2    int  x=0;
3    int  y=0;
4    while ( iRecordNum-- > 0 )
5    {
6	   If ( iType==0 )
7		{x=y+2;break;}
8     else
9	      If ( iType==1 )
10            x=y+10;
11       else
12            x=y+20;
13    }
14 }
  • 画出控制流图:

    https://i-blog.csdnimg.cn/blog_migrate/99d6da91f19e44e67e1bd28fbfb01a32.png

  • 计算环形复杂度:

    10(条边)- 8(个节点)+ 2 = 4
  • 导出独立路径(用语句编号表示)

    路径1:4→14
    路径2:4→6→7→14
    路径3:4→6→9→10→13→4→14
    路径4:4→6→9→12→13→4→14
  • 设计测试用例:

    https://i-blog.csdnimg.cn/blog_migrate/f7fd748b3933705084c29293c005a205.png

1、使用基本路径测试方法,为以下程序段设计测试用例。

       void Do (int X,int A,int B)
       {
 1       if ( (A>1)&&(B=0) )
 2           X = X/A;
 3       if ( (A=2)||(X>1) )
 4           X = X+1;
 5    }

2、在三角形问题中,要求输入三个边长:a,b,c。当三边不可能构成三角形时提示错误,可构成三角形时计算三角形的周长。若是等腰三角形打印“等腰三角形”,若是等边三角形,则打印“等边三角形”。画出相应的程序流程图,并采用基本路径测试方法为该程序设计测试用例。

  • 从本质上说,循环测试的目的就是检查循环结构的有效性。
  • 通常,循环可以划分为简单循环、嵌套循环、串接循环和非结构循环4类。

a. 测试简单循环。设其循环的最大次数为n ,可采用以下测试集:

  • 跳过整个循环;

  • 只循环一次;

  • 只循环两次;

  • 循环 m 次,其中m<n;

  • 分别循环 n-1、n 和 n+1 次。

    https://i-blog.csdnimg.cn/blog_migrate/5068187c283a4cdc972749ede4ea9451.png

b. 测试嵌套循环。如果将简单循环的测试方法用于嵌套循环,可能的测试次数会随嵌套层数成几何级数增加。 此时可采用以下办法减少测试次数:

  • 测试从最内层循环开始,所有外层循环次数设置为最小值;
  • 对最内层循环按照简单循环的测试方法进行;
  • 由内向外进行下一个循环的测试,本层循环的所有外层循环仍取最小值,而由本层循环嵌套的循环取某些“典型”值;
  • 重复上一步的过程,直到测试完所有循环。

c. 测试串接循环。若串接的各个循环相互独立,则可分别采用简单循环的测试方法;否则采用嵌套循环的测试方法。

d. 对于非结构循环这种情况,无法进行测试,需要按结构化程序设计的思想将程序结构化后,再进行测试。

e. Z路径覆盖下的循环测试方法

  • Z路径覆盖是路径覆盖的一种变体,它是将程序中的循环结构简化为选择结构的一种路径覆盖。

  • 循环简化的目的是限制循环的次数,无论循环的形式和循环体实际执行的次数,简化后的循环测试只考虑执行循环体一次和零次(不执行)两种情况,即考虑执行时进入循环体一次和跳过循环体这两种情况。

    https://i-blog.csdnimg.cn/blog_migrate/ef74b9b31782ce37a58f62b6da90f58d.png

在实践中,除了前面给出的各种方法外,通常还可以采用以下三种方法来补充设计测试用例:

  • 通过非路径分析得到测试用例

    这种方法得到的测试用例是在应用系统本身的实践中提供的,基本上是测试人员凭工作经验的得到,甚至是猜测得到的。

  • 寻找尚未测试过的路径并生成相应的测试用例

    这种方法需要穷举被测程序的所有路径,并与前面已测试路径进行对比。

  • 通过指定特定路径并生成相应的测试用例

  • 为实现测试的逻辑覆盖,必须设计足够多的测试用例,并使用这些测试用例执行被测程序,实施测试。我们关心的是:对于某个具体的程序来说,至少需要设计多少个测试用例。这里提供一种估算最少测试用例数的方法。

  • 我们知道,结构化程序是由 3种基本控制结构组成:顺序型(构成串行操作)、选择型(构成分支操作)和重复型(构成循环操作)。

  • 为了把问题化简,避免出现测试用例极多的组合爆炸, 把构成循环操作的重复型结构用选择结构代替 。这样,任一循环便改造成进入循环体或不进入循环体的分支操作了。

  • 用N-S图表示程序的3种基本控制结构:

    • 图中A、B、C、D、S均表示要执行的操作,P是可取真假值的谓词,Y表真值,N表假值。

    • 图中的(c)和(d)两种重复型结构代表了两种循环。在做了简化循环的假设以后,对于一般的程序控制流,我们只考虑选择型结构。事实上它已经能体现顺序型和重复型结构了。

      https://i-blog.csdnimg.cn/blog_migrate/738808ffd21dc9bd0278e55818431cb3.png

a. 例一

下图表达了两个顺序执行的分支结构。当两个分支谓词P1和P2取不同值时,将分别执行a或b及c或d操作。

https://i-blog.csdnimg.cn/blog_migrate/37e72f471f8dae86e93937cf7d3ceb8c.png

显然,要测试这个小程序,需要至少提供4个测试用例才能作到逻辑覆盖,使得ac、ad、bc及bd操作均得到检验。其实,这里的4是图中的第1个分支谓词引出的两个操作,及第2个分支谓词引出的两个操作组合起来而得到的,即2×2=4。并且,这里的2是由于两个并列的操作,即1+1=2 而得到的。

  • 对于一般的、更为复杂的问题,估算最少测试用例个数的原则也是同样的:

    • 如果在N-S图中存在有并列的层次A1、A2,A1和A2的最少测试用例个数分别为a1、a2,则由 A1、A2 两层所组合的 N-S图对应的最少测试用例数为a1×a2。
    • 如果在N-S图中不存在有并列的层次,则对应的最少测试用例数由并列的操作数决定,即N-S图中除谓词之外的操作框的个数。

b. 例二

如下图所示的N-S图,至少需要多少个测试用例完成逻辑覆盖?

https://i-blog.csdnimg.cn/blog_migrate/b5dd9d2b94b3ac6ed377a84057047002.png

  • 分析该N-S图:

    图中的2345和67是并列的两层。其中,2345层对应的最少测试用例数为1+1+1+1+1=5,67层对应的测试用例数为1+1+1=3,2345和67这两层组合后对应的测试用例数为5×3=15。最后,由于两层组合后的部分是不满足谓词1时所要做的操作,还要加上满足谓词1要做的操作,因此整个程序所需测试用例数为15+1=16。

c. 习题

  • 将下图所示的流程图转换为N-S图,并估算至少需要多少个测试用例完成逻辑覆盖?

    https://i-blog.csdnimg.cn/blog_migrate/0be541afe5cb59e4ea074da4d8114595.png

  • 某程序所画出的N-S图如下图所示的,至少需要多少个测试用例才能对该程序实现逻辑覆盖?

    https://i-blog.csdnimg.cn/blog_migrate/78a49ed399ebe94a9ac9b7085d9e03b2.png