软件测试重点

文章1章 软件测试概述 什么是软件测试 ü 广义的概念:它指的是整个软件生命周期的检查、审查和验证,其中包含分析、设计阶段,毕开发后维护阶段的各类文档、代码

文章1章  软件测试概述

什么是软件测试

ü  广义的概念:它指的是整个软件生命周期的检查、审查和验证,其中包含分析、设计阶段,毕开发后维护阶段的各类文档、代码的审查和确认

ü  狭义概念:识别软件缺陷的过程,即实际结果与预期结果的不一致

ü  软件測试通常包含验证(verification)和确认(validation):

-    验证指保证软件正确的实现了某一特定功能的一系列活动

-    确认指的是保证软件的实现满足了用户需求的一系列活动

软件測试的目的

ü  測试的目的就是发现软件中的各种缺陷

ü  測试仅仅能证明软件存在缺陷,不能证明软件不存在缺陷

ü  測试能够使软件中缺陷减少到一定程度。而不是彻底消灭

ü  以较少的用例、时间和人力找出软件中的各种错误和缺陷,以确保软件的质量

測试的目标

ü  终于目的是确保软件的功能符合用户的需求。把尽可能多的问题在公布或交付前发现并改正:

-    确保软件完毕了它所承诺或发布的功能

-    确保软件满足性能的要求

-    确保软件是健壮的和适应用户环境的

ü  为软件的质量评估提供根据

ü  为软件质量改进和管理提供帮助

软件測试原则

ü  Good-enough: 一种权衡投入/产出比的原则

ü  保证測试的覆盖程度。但穷举測试是不可能的

ü  全部的測试都应追溯到用户需求

ü  越早測试越好,測试过程与开发过程应是相结合的

ü  測试的规模由小而大,从单元測试到系统測试

ü  为了尽可能地发现错误,应该由独立的第三方来測试

ü  不能为了便于測试擅自改动程序

ü  既应该測试软件该做什么也应该測试软件不该做什么

測试的规律

ü  木桶原理:

-    软件质量的关键因素是分析、设计和实现,測试应该是融于当中的补充检查手段,其它管理、支持、甚至文化因素也会影响终于软件的质量

-    測试是提高软件质量的必要条件,最直接、最快捷的手段。但决不是一种根本手段

ü  Bug的80-20原则

-    在分析、设计、实现阶段的复审和測试工作可以发现和避免80%的Bug

-    而系统測试又能找出其余Bug中的80%

-    最后的5%的Bug可能仅仅 有在用户的大范围、长时间使用后才会曝露出来

软件測试的重点

ü  測试用例的良好设计

-    測试用例的设计是整个软件測试工作的核心

-    測试用例反映对被測对象的质量要求,决定对測试对象的质量评估

ü  測试工作的管理

-    尤其是对包括多个子系统的大型软件系统,其測试工作涉及大量人力和物力,有效的測试工作管理是保证有效測试工作的必要前提

ü  測试环境的建立

-    測试环境应该与实际測试环境一致

软件缺陷含义

ü  IEEE (1983) 729 软件缺陷一个标准的定义:

-    从产品内部看。软件缺陷是软件产品开发或维护过程中所存在的错误、毛病等各种问题;

-    从外部看,软件缺陷是系统所须要实现的某种功能的失效或违背。

软件缺陷的主要类型/现象:

-    功能、特性没有实现或部分实现

-    设计不合理,存在缺陷

-    实际结果和预期结果不一致

-    执行出错。包含执行中断、系统崩溃、界面混乱

-    数据结果不对、精度不够

-    用户不能接受的其它问题,如存取时间过长、界面不美观

ü  软件缺陷的产生

①      技术问题:算法错误,语法错误。计算和精度问题,接口參数传递不匹配

②      团队工作:误解、沟通不充分

③      软件本身:文档错误、用户使用场景(user scenario)。时间上不协调、或不一致性所带来的问题。系统的自我恢复或数据的异地备份、灾难性恢复等问题

软件缺陷在不同阶段的分布

在真正的程序測试之前。通过审查、评审会能够发现很多其它的缺陷。规格说明书的缺陷会在需求分析审查、设计、编码、測试等过程中会逐步发现,而不能在需求分析一个阶段发现

软件測试的质量

ü  软件測试能够发现下面软件缺陷:

-    软件实现的功能不对

-    “缺少”:软件没有实现某项功能

-    “多余”:软件实现的某项功能在需求中未定义

ü  发现第一类软件缺陷的过程 --- “验证”

ü  发现后两类软件缺陷的过程 --- “确认”

ü  软件測试本身的质量在于:

-    发现软件缺陷并能区分其类型

-    提供关于软件质量和开发过程质量的信息

软件測试度量

ü  測试覆盖率

-    有多少需求、代码已经被測试了

ü  缺陷发现率

-    缺陷是何时被发现。而且有多少缺陷已经被发现。

缺陷能够依据严重性来分类。需记录下面值:

Ø  缺陷数目

Ø  缺陷的严重性

软件測试的分类

ü  典型的软件測试类型

-    功能測试

-    可靠性測试

-    容错性測试

-    恢复測试

-    易用性測试

-    性能測试

-    可维护性測试

-    可移植性測试

-    安全性測试

-    用户文档測试

-    软件測试技术

ü  黑盒測试/白盒測试

ü  动态測试/静态測试

黑盒測试和白盒測试

ü  黑盒測试

-    又称功能測试或数据驱动測试,是针对软件的功能需求/实现进行測试

-    通过測试来检測每一个功能是否符合需求,不考虑程序内部的逻辑结构

-    穷举输入測试

ü  黑盒測试方法

-    功能划分

-    等价类划分

-    边界值分析

-    因果图

-    错误猜測等

-    白盒測试

-    白盒測试也称结构測试或逻辑驱动測试

-    必须知道软件内部工作过程,通过測试来检測软件内部是否依照需求、设计正常执行

-    通过逻辑覆盖、路径覆盖等方式选择測试用例。能够用測试覆盖率评价測试用例

ü  白盒測试的主要方法

-    相应于程序的一些主要结构:语句、分支、逻辑路径、变量

Ø  语句覆盖方法

Ø  分支覆盖方法

Ø  逻辑覆盖方法

动态測试和静态測试

ü  动态測试

-    动态測试须要在开发/測试环境或实际执行环境中执行软件。并使用測试用例去查找软件缺陷

-    动态測试包含功能确认与接口測试、覆盖率分析、性能分析、内存分析等 

ü  静态測试

-    静态測试不实际执行软件。主要是对软件的编程格式、结构等方面进行评估

-    静态測试包含代码检查、程序结构分析、代码质量度量等。

它能够由人工进行,也能够借助软件工具自己主动进行

黑盒白盒測试与动态静态測试的关系

ü  黑盒測试、白盒測试

-    測试用例设计阶段採用的方法

ü  动态測试、静态測试

-    測试运行阶段採用的方法

软件測试方法

手工測试和自己主动測试

ü  手工測试

ü  自己主动測试

ü  适合自己主动化的測试操作

ü  手工測试和自己主动測试的比較

ü  手工測试

ü  传统的測试方法

ü  由測试人员手工编写測试用例

ü  缺点在于測试工作量大,反复多,回归測试难以实现

自己主动測试

ü  利用软件測试工具自己主动实现所有或部分測试工作:管理、设计、运行和报告

ü  自己主动測试节省大量的測试开销,并可以完毕一些手工測试无法实现的測试

适合自己主动化的測试操作

ü  測试用例的生成(包含測试输入,标准输出,測试操作指令等)

ü  測试的执行与控制(包含单机与网络多机分布执行;夜间及假日执行)

ü  測试对象、范围、版本号等的控制

ü  測试结果与预期输出的对照

ü  不吻合的測试结果的分析、记录、分类、和通报

ü  測试的统计,报表的产生

手工測试和自己主动測试的比較

ü  手工完毕測试的所有过程无法保证測试的科学性与严密性:

-    改动的缺陷越多,回归測试越困难

-    没有人能向决策层提供精确的数据以度量当前的工作进度及工作效率

-    重复測试带来的倦怠情绪及其它人为因素使得測试标准前后不一

-    測试花费的时间越长。測试的严格性也就越低

ü  自己主动測试将測试人员从重复、烦杂的測试运行中解放出来。用很多其它的时间进行測试设计和结果分析

ü  软件測试不可能全然自己主动化

ü  不能完毕全部手工測试任务

ü  无创造性且灵活性差,不能改进測试的有效性

ü  过程中可能会遇到很多意想不到的问题,特别是当软件不稳定时

ü  測试脚本的维护高

測试流程

ü  单元測试

ü  集成測试

ü  系统測试

ü  用户验收測试

ü  回归測试

ü  V模型示意图

单元測试

ü  完毕对最小的软件设计单元—模块的验证工作

ü  目标是确保模块被正确地编码

ü  使用过程设计描写叙述作为指南,对重要的控制路径进行測试以发现模块内的错误

ü  通常情况下是面向白盒的

ü  对代码风格和规则、程序设计和结构、业务逻辑等进行静态測试。及早地发现和解决不易显现的错误

单元測试

ü  单元測试的内容

-    接口測试

-    内部数据结构

-    全局数据结构

-    边界

-    语句覆盖

-    错误路径

集成測试

ü  通过測试发现与模块接口有关的问题

ü  目标是把通过了单元測试的模块拿来,构造一个在设计中所描写叙述的程序结构

ü  应当避免一次性的集成(除非软件规模非常小),而採用增量集成

系统測试

ü  依据软件需求规范的要求进行系统測试,确认系统满足需求的要求

ü  系统測试人员相当于用户代言人

ü  在需求分析阶段要确定软件的可測性,保证有效完毕系统測试工作

ü  系统測试主要内容

-    全部功能需求得到满足

-    全部性能需求得到满足

-    其它需求(比如安全性、容错性、兼容性等)得到满足

用户验收/确认測试

ü  配置审查

-    确保已开发软件的全部文件资料均已编写齐全,并分类编目

ü  Alpha測试

-    是由用户在开发人员的场所来进行的。Alpha測试是在一个受控的环境中进行的

ü  Beta測试

-    由软件的终于用户在一个或多个用户场所来进行的

-    开发人员通常不在现场。用户记录測试中遇到的问题并报告给开发人员

-    开发人员对系统进行最后的改动,并開始准备公布终于的软件

回归測试

ü  当发现并改动缺陷后,或者在软件中加入新功能后,又一次測试,用来检查被发现的缺陷是否被改正,而且所作的改动没有引发新的问题

ü  回归測试能够通过人工又一次运行測试用例,也能够使用自己主动化的捕获回放工具来进行

ü  回归測试方式

-    再測试所实用例

Ø  选择基线測试用例库中的所有測试用例组成回归測试包。測试成本最高

-    基于风险选择測试

Ø  能够基于一定的风险标准来从基线測试用例库中选择回归測试包

各阶段測试所使用的方法技术

ü  单元測试

白盒、自己主动、静态

ü  集成測试

白盒、黑盒、自己主动、静态

ü  系统測试

黑盒、自己主动、手工

ü  用户验收/确认測试

黑盒、自己主动、手工

第2章  软件測试策略与过程

2.1  软件測试的复杂性分析

1、无法对程序进行全然測试

(1)測试所须要的输入量太大

(2)測试的输出结果太多

(3)软件实现的途径太多

(4)软件规格说明没有一个客观标准

2、測试无法显示潜在的软件缺陷和故障

    ——通过软件測试仅仅能报告软件已被发现的缺陷和故障,无法报告隐藏的软件故障。

3、存在的故障现象与发现的故障数量成正比

    ——结论:应当对故障集中的程序段进行重点測试

4、不能修复全部的软件故障

    ——原因:没有足够的进行修复;修复的风险较大;  不值得修复。可不算做故障的一些缺陷。“杀虫剂现象”。

    ——结论:关键是要进行正确的推断、合理的取舍,依据风险分析决定哪些故障必须修复,哪些故障能够不修复。

5、软件測试的代价

    ——工作原则:就是怎样将无边无际的可能性减小到一个能够控制的范围。以及怎样针对软件风险做出恰当选择,去粗存精。找到最佳的測试量,使得測试工作量不多也不少。既能达到測试的目的,又能较为经济。

2.2  软件測试方法与策略

软件測试策略

l  什么是软件測试策略?

    ——是为软件project过程定义的一个软件測试的模板,也就是把特定的測试用例方法放置进去的一系列步骤。

l  软件測试策略包括的特征:

(1)測试从模块层開始,然后扩大延伸到整个基于计算机的系统集合中。

(2)不同的測试技术适用于不同的时间点。

(3)測试是由软件的开发者和(对于大型系统而言)独立的測试组来管理的。

(4)測试和调试是不同的活动,可是调试必须可以适应不论什么的測试策略。

软件測试充分性准则

l  对不论什么软件都存在有限的充分測试集合。

l  假设一个软件系统在一个測试数据集合上的測试是充分的。那么再多測试一些数据也应该是充分的。这一特性称为单调性。

l  即使对软件全部成分都进行了充分的測试,也并不表明整个软件的測试已经充分了。

这一特性称为非复合性。

l  即使对软件系统总体的測试是充分的,也并不意味软件系统中各个成分都已经充分地得到了測试。这个特性称为非分解性。

l  软件測试的充分性应该与软件的需求和软件的实现都相关。

l  软件越复杂。须要的測试数据就越多。

这一特性称为复杂性。

l  測试得越多,进一步測试所能得到的充分性增长就越少。这一特性称为回报递减率。

2.2.1  静态測试与动态測试

1、静态測试

l  静态測试不实际执行软件。主要是对软件的编程格式、结构等方面进行评估。

l  静态測试包含代码检查静态结构分析代码质量度量等。它能够由人工进行,也能够借助软件工具自己主动进行。

l  静态測试方法也可利用计算机作为对被測程序进行特性分析的工具。但与人工測试方式有着根本差别。

还有一方面。因它并不真正执行被測程序,仅仅进行特性分析,这又与动态方法不同。

所以。静态方法经常称为“分析”,静态測试是对被測程序进行特性分析方法的总称。

代码检查

l  代码检查包含代码走查、桌面检查、代码审查等。主要检查代码和设计的一致性,代码对标准的遵循、可读性,代码的逻辑表达的正确性。代码结构的合理性等方面。

l  代码检查的详细内容:变量检查、命名和类型审查、程序逻辑审查、程序语法检查和程序结构检查等。

l  代码检查的长处:在实际使用中。代码检查比动态測试更有效率。能高速找到缺陷,发现30%~70%的逻辑设计和编码缺陷;代码检查看到的是问题本身而非征兆。

l  代码检查的缺点:很耗费时间。并且代码检查须要知识和经验的积累。

静态结构分析

l  静态结构分析主要是以图形的方式表现程序的内部结构。

比如函数调用关系图、函数内部控制流图。当中:

——函数调用关系图以直观的图形方式描写叙述一个应用程序中各个函数的调用和被调用关系。

——控制流图显示一个函数的逻辑结构,由很多节点组成,一个节点代表一条语句或数条语句,连接结点的叫边。边表示节点间的控制流向。

代码质量度量

l  软件质量包含六个方面:功能性、可靠性、易用性、效率、可维护性和可移植性。软件的质量是软件属性的各种标准度量的组合。

l  针对软件的可维护性,眼下业界主要存在三种度量參数:Line复杂度Halstead复杂度McCabe复杂度。当中Line复杂度以代码的行数作为计算的基准。Halstead以程序中使用到的运算符与运算元数量作为计数目标(直接測量指标),然后能够据以计算出程序容量、工作量等。McCabe复杂度 一般称为圈复杂度。它将软件的流程图转化为有向图,然后以图论来衡量软件的质量。

静态測试与动态測试(续)

l  静态測试阶段的任务:

(1)检查算法的逻辑正确性。

(2)检查模块接口的正确性。

(3)检查输入參数是否有合法性检查。

(4)检查调用其它模块的接口是否正确。

(5)检查是否设置了适当的出错处理。

(6)检查表达式、语句是否正确,是否含有二义性。

(7)检查常量或全局变量使用是否正确。

(8)检查标识符的使用是否规范、一致。

(9)检查程序风格的一致性、规范性。

(10)检查代码能否够优化,算法效率是否最高。

(11)检查代码凝视是否完整,是否正确反映了代码的功能。

静态測试能够完毕下面工作:

(1)发现下列程序的错误:错用局部变量和全局变量;没有定义的变量、不匹配的參数;不适当的循环嵌套或分支嵌套、死循环、不同意的递归。调用不存在的子程序,遗漏标号或代码。

(2)找出下面问题的根源:从未使用过的变量。不会运行到的代码、从未使用过的标号。潜在的死循环。

(3)提供程序缺陷的间接信息:所用变量和常量的交叉应用表;是否违背编码规则。标识符的用法和过程的调用层次。

(4)为进一步查找做好准备。

(5)选择測试用例。

(6)进行符号測试。

2、动态測试

l  动态方法的主要特征是:

——计算机必须真正执行被測试的程序,通过输入測试用例,对其执行情况即输入与输出的相应关系进行分析,以达到检測的目的。

l  动态測试包含:

(1)功能确认与接口測试

(2)覆盖率分析

(3)性能分析

(4)内存分析

2.2.2  黑盒測试和白盒測试

l  若測试规划是基于产品的功能,目的是检查程序各个功能是否可以实现,并检查当中的功能错误。则这样的測试方法称为黑盒測试(Black-box Testing)方法。

——黑盒測试又称为功能測试、数据驱动測试和基于规格说明的測试。

它是一种从用户观点出发的測试,一般被用来确认软件功能的正确性和可操作性。

l  若測试规划基于产品的内部结构进行測试。检查内部操作是否按规定运行,软件各个部分功能是否得到充分使用。则这样的測试方法称为白盒測试(White-box Testing)方法。

——白盒測试又称为结构測试、逻辑驱动測试或基于程序的測试,一般用来分析程序的内部结构。

1、黑盒測试

l  黑盒測试的基本观点是:不论什么程序都能够看作是从输入定义域映射到输出值域的函数过程。被測程序被觉得是一个打不开的黑盒子,黑盒中的内容(实现过程)全然不知道,仅仅明白要做到什么。

l  黑盒測试主要依据规格说明书设计測试用例,并不涉及程序内部构造和内部特性。仅仅依靠被測程序输入和输出之间的关系或程序的功能设计測试用例。

l  黑盒測试的特点:

(1)黑盒測试与软件的详细实现过程无关。在软件实现的过程发生变化时。測试用例仍然能够使用。

(2)黑盒測试用例的设计可以和软件实现同一时候进行,这样可以压缩总的开发时间。

黑盒測试是在程序接口进行測试。它仅仅是检查程序功能是否依照规格说明书的规定正常使用。也被称为用户測试。

l  黑盒測试主要是为了发现下面几类错误:

-    是否有不对或遗漏了的功能?

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

-    是否有数据结构错误或外部信息訪问错误?

-    性能上是否可以满足要求?

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

l  黑盒測试的难点:在哪个层次上进行測试?

l  黑盒測试的详细技术方法 :

①边界值分析法 ②等价类划分法 ③因果图法 ④决策表法

2、白盒測试

l  白盒測试将被測程序看作一个打开的盒子。測试者可以看到被測源程序。可以分析被測程序的内部结构,此时測试的焦点集中在依据其内部结构设计測试用例。

l  白盒測试要求是对某些程序的结构特性做到一定程度的覆盖,或者说这样的測试是“基于覆盖率的測试”。

l  通常的程序结构覆盖有:

①语句覆盖 ②判定覆盖 ③条件覆盖 ④判定/条件覆盖 ⑤路径覆盖

白盒測试须要全然了解程序结构和处理过程,它依照程序内部逻辑測试程序。检验程序中每条通路是否按预定要求正确工作。也被称为程序猿測试。

l  黑盒測试:

    ——以用户的观点。从输入数据与输出数据的相应关系,即依据程序外部特性进行測试,而不考虑内部结构及工作情况。

    ——黑盒測试技术注重于软件的信息域(范围)。通过划分程序的输入和输出域来确定測试用例。

    ——若外部特性本身存在问题或规格说明的规定有误,则应用黑盒測试方法是不能发现问题的。

l  白盒測试:

    ——仅仅依据程序的内部结构进行測试。

——測试用例的设计要保证測试时程序的全部语句至少运行一次。并且要检查全部的逻辑条件。

——假设程序的结构本身有问题,比方说程序逻辑有错误或者有遗漏,那也是无法发现的。

项目

黑盒測试

白盒測试

规划方面

功能的測试

结构的測试

有点方面

能确保从用户的角度出发进行測试

能对程序内部的特定部位进行覆盖測试

缺点方面

无法測试程序内部特定部位;当规格说明有误。则不能发现问题

无法检查程序的外部特性;

无法对未实现规格说明的程序内部欠缺部分进行測试

应用范围

边界分析法

等价类划分法

决策表測试

语句覆盖。判定覆盖。条件覆盖,

判定/条件覆盖,路径覆盖,循环覆盖,

模块接口測试

2.2.3  软件測试过程

软件測试的过程流程

l  单元測试:针对每一个单元的測试。 以确保每一个模块能正常工作为目标。

l  集成測试:对已測试过的模块进行组装,进行集成測试。

目的在于检验与软件设计相关的程序结构问题。

l  确认(有效性)測试:是检验所开发的软件是否能满足全部功能和性能需求的最后手段。

l  系统測试:检验软件产品是否能与系统的其它部分(比方。硬件、数据库及操作人员)协调工作。

l  验收(用户)測试:检验软件产品质量的最后一道工序。主要突出用户的作用。同一时候软件开发者也应有一定程度的參与。

2.3  单元測试

l  单元測试针对每一个程序的模块,主要測试5个方面的问题:

    ——模块接口、局部数据结构、边界条件、独立的路径和错误处理。

模块接口

l  这是对模块接口进行的測试。检查进出程序单元的数据流是否正确。模块接口測试必须在不论什么其他測试之前进行。

l  模块接口測试至少须要例如以下的測试项目:

(1)调用所測模块时的输入參数与模块的形式參数在个数、属性、顺序上是否匹配。

(2)所測模块调用子模块时。它输入给子模块的參数与子模块中的形式參数在个数、属性、顺序上是否匹配。

(3)是否改动了仅仅做输入用的形式參数;

(4)调用标准函数的參数在个数、属性、顺序上是否正确;

(5)全局变量的定义在各模块中是否一致。

局部数据结构

l  在模块工作过程中,必须測试模块内部的数据是否能保持完整性,包含内部数据的内容、形式及相互关系不错误发生。

l  对于局部数据结构,应该在单元測试中注意发现下面几类错误:

(1)不对的或不一致的类型说明。

(2)错误的初始化或默认值。

(3)错误的变量名,如拼写错误或书写错误。

(4)下溢、上溢或者地址错误。

路径測试

l  在单元測试中。最基本的測试是针对路径的測试。測试用例必须可以发现因为计算错误、不对的判定或不正常的控制流而产生的错误。

l  常见的错误有:

    误解的或不对的算术优先级;混合模式的运算;错误的初始化;准确度不够精确;表达式的不对符号表示。

l  针对判定和条件覆盖,測试用例还要可以发现例如以下错误:

    不同数据类型的比較;不对的逻辑操作或优先级;应当相等的地方因为准确度的错误而不能相等。不对的判定或不对的变量;不对的或不存在的循环终止;当遇到分支循环时不能退出;不适当地改动循环变量。

边界条件

l  边界測试是单元測试的最后一步,必须採用边界值分析方法来设计測试用例,认真细致地測试为限制数据处理而设置的边界处。看模块是否可以正常工作。

l  一些可能与边界有关的数据类型如数值、字符、位置、数量、尺寸等。还要注意这些边界的首个、最后一个、最大值、最小值、最长、最短、最高、最低等特征。

l  在边界条件測试中,应设计測试用例检查下面情况:

(1)在n次循环的第0次、1次、n次是否有错误。

(2)运算或推断中取最大值、最小值时是否有错误。

(3)数据流、控制流中刚好等于、大于、小于确定的比較值是否出现错误。

出错处理

l  測试出错处理的重点是模块在工作中发生了错误,当中的出错处理设施是否有效。

l  检验程序中的出错处理可能面对的情况有:

(1)对执行发生的错误描写叙述难以理解。

(2)所报告的错误与实际遇到的错误不一致。

(3)出错后。在错误处理之前就引起系统的干预。

(4)例外条件的处理不对。

(5)提供的错误信息不足。以至于无法找到错误的原因。

2.3.2  单元測试的运行过程

l  何时进行单元測试?单元測试经常是和代码编写工作同一时候进行的,在完毕了程序编写、复查和语法正确性验证后。就应进行单元測试用例设计。

l  在单元測试时,假设模块不是独立的程序,须要设置一些辅助測试模块。

辅助測试模块有两种:

(1)驱动模块(Drive)  用来模拟被測试模块的上一级模块。相当于被測模块的主程序。它接收数据,将相关数据传送给被測模块,启动被測模块,并打印出对应的结果。

(2)桩模块(Stub)  用来模拟被測模块工作过程中所调用的模块。它们一般仅仅进行非常少的数据处理。

l  驱动模块和桩模块都是额外的开销。尽管在单元測试中必须编写。但并不须要作为终于的产品提供给用户。

l  被測模块、驱动模块和桩模块共同构成了一个例如以下图所看到的的单元測试的測试环境:

2.4  集成測试

2.4.1  非增量式測试

实例  採用非增量式測试方法进行集成測试

l  非增量式測试是採用一步到位的方法来构造測试:  

——对全部模块进行个别的单元測试后,依照程序结构图将各模块连接起来,把连接后的程序当作一个总体进行測试。

l  採用非增量式測试方法进行集成測试

l  非增量式測试的缺点:

——当一次集成的模块较多时,非增量式測试easy出现混乱,由于測试时可能发现了很多故障,为每个故障定位和纠正非常困难。而且在修正一个故障的同一时候,可能又引入了新的故障。新旧故障混杂。非常难判定出错的详细原因和位置。

2.4.2  增量式測试

l  增量式測试的集成是逐步实现的:

    ——逐次将未曾集成測试的模块和已经集成測试的模块(或子系统)结合成程序包。再将这些模块集成为较大系统。在集成的过程中边连接边測试。以发现连接过程中产生的问题。

l  依照不同的实施次序。增量式集成測试又能够分为三种不同的方法:

   (1)自顶向下增量式測试

   (2)自底向上增量式測试

   (3)混合增量式測试

自顶向下增量式測试

l  自顶向下增量式測试表示逐步集成和逐步測试是按照结构图自上而下进行的。即模块集成的顺序是首先集成主控模块(主程序),然后按照控制层次结构向下进行集成。从属于主控模块的按深度优先方式(纵向)或者广度优先方式(横向)集成到结构中去。

l  深度优先方式的集成:

    ——首先集成在结构中的一个主控路径下的全部模块,主控路径的选择是随意的。

l  广度优先方式的集成:

    ——首先沿着水平方向,把每一层中全部直接隶属于上一层的模块集成起来,直究竟层。

集成測试的整个过程由3个步骤完毕:

  (1)主控模块作为測试驱动器。

  (2)依据集成的方式(深度或广度),下层的桩模块一次一次地被替换为真正的模块。

  (3)在每一个模块被集成时,都必须进行单元測试。

反复第2步,直到整个系统被測试完毕。

l 实例 依照广度优先方式进行集成測试

l 实例 依照深度优先方式进行集成測试

自底向上增量式測试

l  自底向上增量式測试表示逐步集成和逐步測试的工作是按结构图自下而上进行的,即从程序模块结构的最底层模块開始集成和測试。

l  因为是从最底层開始集成。对于一个给定层次的模块。它的子模块(包含子模块的全部下属模块)已经集成并測试完毕,所以不再须要使用桩模块进行辅助測试。

在模块的測试过程中须要从子模块得到的信息能够直接执行子模块得到。

实例 採用自底向上增量式測试方法进行集成測试

混合增量式測试

l  混合增量式測试是把自顶向下測试和自底向上測试这两种方式结合起来进行集成和測试。

这样能够兼具两者的长处,而摒弃其缺点。

l  常见的两种混合增量式測试方式:

(1)衍变的自顶向下的增量式測试:基本思想是强化对输入/输出模块和引入新算法模块的測试,并自底向上集成为功能相对完整且相对独立的子系统。然后由主模块開始自顶向下进行增量式測试。

(2)自底向上-自顶向下的增量式測试:首先对含读操作的子系统自底向上直至根节点模块进行集成和測试,然后对含写操作的子系统做自顶向下的集成与測试。

2.4.3  不同集成測试方法的比較

1、非增量式測试与增量式測试的比較

l  非增量式測试的方法是先分散測试。然后集中起来再一次完毕集成測试。

假如在模块的接口处存在错误。仅仅会在最后的集成測试时一下子暴露出来。

l  增量式測试是逐步集成和逐步測试的方法,把可能出现的差错分散暴露出来,便于找出问题和改动。并且一些模块在逐步集成的測试中。得到了较多次的考验。因此。可能会取得较好的測试效果。

结论:增量式測试要比非增量式測试具有一定的优越性。

2、自顶向下与自底向上增量式測试的比較

l  自顶向下增量式測试:

——主要长处在于它能够自然的做到逐步求精。一開始就能让測试者看到系统的框架。

——主要缺点是须要提供桩模块,而且在输入/输出模块接入系统曾经,在桩模块中表示測试数据有一定困难。

l  自底向上增量式測试:

——长处在于,因为驱动模块模拟了全部调用參数,即使数据流并未构成有向的非环状图,生成測试数据也无困难。

——主要缺点在于,直到最后一个模块被加进去之后才干看到整个程序(系统)的框架。

2.4.4  回归測试

l  什么是回归測试?

——在集成測试策略的环境中,回归測试是对某些已经进行过的測试的某些子集再又一次进行一遍,以保证上述改变不会传播无法预料的副作用或引发新的问题。

——在更广的环境里,回归測试就是用来保证(因为測试或其它原因的)修改不会带来不可预料的行为或另外的错误。

l  回归測试能够通过又一次运行全部的測试用例的一个子集人工地进行,也能够使用自己主动化的捕获回放工具来进行。

l  回归測试集包含三种不同类型的測试用例:

 (1)可以測试软件的全部功能的代表性測试用例

 (2)专门针对可能会被改动而影响软件功能的附加測试

 (3)针对改动过的软件成分的測试

2.5  确认測试

1、确认測试的准则

l  确认測试也称为合格性測试,是检验所开发的软件能否按用户提出的要求进行。软件确认要通过一系列证明软件功能和要求一致的黑盒測试来完毕。

l  经过确认測试,应该为已开发的软件给出结论性评价:

(1)经过检验的软件的功能、性能及其它要求均已满足需求规格说明书的规定,则可被觉得是合格的软件。

(2)经过检验发现与需求说明书有相当的偏离。得到一个各项缺陷清单。

2、配置审查的内容

l  确认測试过程的重要环节就是配置审查工作。其目的在于确保已开发软件的全部文件资料均已编写齐全。并得到分类编目,足以支持执行以后的软件维护工作。

l  配置审查的文件资料包含用户所需的下面资料:

   (1)用户手冊

   (2)操作手冊

   (3)设计资料——如:设计说明书、源程序以及測试资料(測试说明书、測试报告)等

2.6  系统測试

l  为什么要进行系统測试?

    ——因为软件仅仅是计算机系统中的一个组成部分。软件开发完毕之后。终于还要和系统中的硬件系统、某些支持软件、数据信息等其它部分配套执行。

因此,在投入执行前要完毕系统測试。以保证各组成部分不仅能单独的得到检验,并且在系统各部分协调工作的环境下也能正常工作。

l  虽然每个检验有特定的目标,然而全部的检測工作都要验证系统中每个部分均已得到正确的集成,并能完毕指定的功能。

l  严格的说。系统測试超出了软件project范围。通常这项工作并不由系统开发者或系统开发组织来承担,而是由软件用户或软件开发机构托付独立測试机构来完毕。

恢复測试

l  恢复測试是通过各种手段,强制性地使软件出错。使其不能正常工作,进而检验系统的恢复能力。

l  恢复測试包括的内容:

    ——假设系统恢复是自己主动的(由系统自身完毕),则应该检验:又一次初始化、检验点设置机构、数据恢复以及又一次启动是否正确。

    ——假设这一恢复须要人为干预,则应考虑平均修复时间是否在限定的、能够接受的范围之内。

安全測试

l  安全測试的目的在于验证安装在系统内的保护机制是否能在实际中保护系统且不受非法入侵,不受各种非法干扰。

l  在安全測试中。測试者扮演着试图攻击系统的个人角色:

   — 尝试去通过外部的手段来获取系统的password

   — 使用能够瓦解不论什么防守的客户软件来攻击系统

   — 把系统“瘫痪”。使得其它用户无法訪问

   — 有目的地引发系统错误,期望在恢复过程中侵入系统

   — 通过浏览非保密的数据。从中找到进入系统的钥匙

l  系统的安全測试要设置一些測试用例试图突破系统的安全保密措施。检验系统是否有安全保密的漏洞。

强度測试

l  从本质上来说。强度測试(也称压力測试-Stree Testing)的目的是要检測非正常的情形,測试是想要破坏程序。

    强度測试须要在反常规数据量、频率或资源的方式下执行系统,以检验系统能力的最高实际限度。

l  举例:

    — 假设正常的中断频率为每秒5次,强度測试设计为每秒50次中断。

    — 把输入数据的量提高一个数量级来測试输入功能会怎样响应。

    — 若某系统正常执行可支持200个终端并行工作。强度測试则检验1000个终端并行工作的情况。

    — 执行大量的消耗内存或其它系统资源的測试实例。

性能測试

l  性能測试用来測试软件在系统集成中的执行性能,特别是针对实时系统和嵌入式系统。仅提供符合功能需求但不符合性能需求的软件是不能被接受的。

l  性能測试能够在測试过程的随意阶段进行,但仅仅有当整个系统的全部成分都集成在一起后。才干检查一个系统的真正性能。

l  性能測试经常和强度(压力)測试结合起来进行,并且经常须要硬件和软件測试设备,这就是说,经常有必要在一种苛刻的环境中衡量资源的使用(比方,处理器周期)。

正确性測试

l  正确性測试检查软件的功能是否符合规格说明。

l  正确性測试的方法:

   ——枚举法,即构造一些合理输入。检查是否得到期望的输出。

測试时应尽量设法降低枚举的次数,关键在于寻找等价区间,由于在等价区间中。仅仅需用随意值測试一次就可以。

     ——边界值測试,即採用定义域或者等价区间的边界值进行測试。

由于程序设计easy疏忽边界情况,程序也easy在边界值处出错。

可靠性測试

l  可靠性測试是从验证的角度出发,检验系统的可靠性是否达到预期的目标。同一时候给出当前系统可能的可靠性增长情况。

l  对可靠性性測试来说,最关键的測试数据包含失效间隔时间,失效修复时间,失效数量。失效级别等。依据获得的測试数据。应用可靠性模型,能够得到系统的失效率及可靠性增长趋势。

l  可靠性指标有时非常难測试,通常採用平均无故障时间或系统投入执行后出现的故障不能大于多少数量这些指标来对可靠性进行评估。

兼容性測试

l  软件兼容性測试是检測各软件之间是否能正确地交互和共享信息,其目标是保证软件依照用户期望的方式进行交互。使用其他软件检查软件操作的过程。

l  兼容性的測试通常须要解决下面问题:

  (1)新开发的软件须要与哪种操作系统、Web浏览器和应用软件保持兼容。假设要測试的软件是一个平台,那么要求应用程序能在其上执行。

  (2)应该遵守哪种定义软件之间交互的标准或者规范。

  (3)软件使用何种数据与其他平台、与新的软件进行交互和共享信息。

2.7  验收測试

2.7.1  验收測试的内容

l  软件验收測试应完毕的工作内容包含:

(1)明白验收项目。规定验收測试通过的标准。

(2)确定測试方法。

(3)决定验收測试的组织机构和可利用的资源。

(4)选定測试结果分析方法。

(5)指定验收測试计划并进行评审。

(6)设计验收測试所用的測试用例。

(7)审查验收測试准备工作。

(8)运行验收測试。

(9)分析測试结果。

(10)做出验收结论,明白通过验收或不通过验收。

在验收測试计划其中,可能包含的检验方面有下面几种:

l  功能測试。如完整的工资计算过程。

l  逆向測试。如检验不符合要求数据而引起出错的恢复能力。

l  特殊情况。如极限測试、不存在的路径測试。

l  文档检查。

l  强度检查。如大批量的数据或者最大用户并发使用。

l  恢复測试。

如硬件故障或用户不良数据引起的一些情况。

l  可维护性的评价。

l  用户操作測试。如启动、退出系统等。

l  用户友好性检验。

l  安全測试。

2.7.2  软件配置和文档资料測试

l  对文档的測试包含下面内容:

  (1)检查产品说明书属性 

  (2)检查是否完整 

  (3)检查是否准确 

  (4)检查是否精确

  (5)检查是否一致

  (6)检查是否贴切

  (7)检查是否合理 

  (8)检查代码无关 

  (9)检查可測试性

2.8  測试后的调试

l  软件调试和软件測试有全然不同的含义:

     ——測试的目的是显示存在错误。

     ——调试的目的是发现错误或导致程序失效的错误原因,并改动程序以修正错误。

l  通常情况是在測试以后紧接着要进行调试,调试是在測试发现错误后消除错误的过程。实际上这两项工作是交叉进行的。

2.9  面向对象的软件測试

1、面向对象的软件測试

l  面向对象软件測试的目标与传统測试一样。即用尽可能低的測试成本和尽可能少的測试用例,发现尽可能多的软件缺陷。

面向对象的測试策略也遵循从“小型測试”到“大型測试”,即从单元測试到终于的功能性測试和系统性測试。

l  但面向对象技术所独有的封装、继承、多态等新特点给測试带来一系列新的问题,添加了測试的难度。与传统的面向过程程序设计相比,面向对象程序设计产生错误的可能性增大,或者使得传统软件測试中的重点不再那么突出,或者使得原来測试经验和实践证明的次要方面成为了主要问题。

2、面向对象的单元測试

l  与传统的单元不同,面向对象软件測试中的单元是封装的类和对象。每一个类和类的实例(对象)包括了属性和操作这些属性的方法。

l  类包括一组不同的操作。而且某个或某些特殊操作可能作为一组不同的类的一部分而存在,測试时不再測试单个孤立的操作。而是測试操作类及类的一部分,单元測试的意义发生了较大的变化。

l  对面向对象软件的类測试等价于对面向过程软件的单元測试。

传统的单元測试主要关注模块的算法和模块接口间数据的流动。即输入和输出;而面向对象软件的类測试主要是測试封装在类中的操作以及类的状态行为。

3、面向对象的集成測试

l  面向对象的集成測试通常须要进行两级集成:

  (1)将成员函数集成到完整类中;

  (2)将类与其他类集成。

l  对面向对象的集成測试有两种不同的策略:

  (1)基于线程的測试。

集成针对回应系统的一个输入或事件所需的一组类,每一个线程被集成并分别进行測试。

  (2)基于使用的測试。首先測试独立的类,并開始构造系统,然后測试下一层的依赖类(使用独立类的类),通过依赖类层次的測试序列逐步构造完整的系统。

4、面向对象的确认測试

l  与传统的确认測试一样。面向对象软件的有效性集中在用户可见的动作(事件驱动与过程)和用户可识别的系统输出(结果),通过測试检验软件是否满足用户的需求。

l  在面向对象的确认測试中。通常採用传统的黑盒測试方法。以证明软件功能和需求的一致性。

第3章  黑盒測试及其用例的设计

3.1  測试用例设计概述

3.1.1  測试用例的定义和特征

測试用例的定义:

(1)測试用例是为特定的目的而设计的一组測试输入、  运行条件和预期的结果。

(2)測试用例是运行的最小实体。

測试用例的特征:

(1)最有可能抓住错误的;

(2)不是反复的、多余的;

(3)一组相似測试用例中最有效的。

(4)既不是太简单。也不是太复杂。

3.1.2  设计測试用例的基本准则

測试用例的代表性

可以代表并覆盖各种合理的和不合理的、合法的和非法的、边界的和越界的以及极限的输入数据、操作和环境设置等。

測试结果的可判定性

即測试运行结果的正确性是可判定的,每个測试用例都应有对应的期望结果。

測试结果的可再现性

即对相同的測试用例。系统的运行结果应当是相同的。

3.1.3  设计測试用例的着眼点

l  依据产品规格,測试基本功能;

l  考虑设计一般用户(非专业人员)的使用方案;

l  考虑设计稀有或特殊的使用方案;

l  与系统其它组成部分的配合(如FAX和上网可能要用到MODEM。測试中考虑对设备的共享);

l  考虑特殊情况(如内存和硬件的冲突等);

l  设计极端情况(如内存泄漏、破坏性測试等);

l  好的測试用例集能花费最小的代价(人力、物力、財力、时间)做最好的測试。

3.1.4  測试用例设计书写标准

在ANSI/IEEE829-1983标准中列出了和測试设计相关的測试用例编写规范和模板。标准模板中主要元素例如以下:

l  标识符——惟一标识每个測试用例

l  測试项——准确的描写叙述所须要測试的项及其特征

l  測试环境要求——表征运行该測试用例须要的測试环境

l  输入标准——运行測试用例的输入需求(这些输入可能包含数据、文件或者操作)

l  输出标准——依照指定的环境和输入标准得到的期望输出结果

l  測试用例之间的关联——标识该測试用例与其他的測试(或其他測试用例)之间的依赖关系

3.2  黑盒測试法的概念

l  黑盒測试被称为功能測试或数据驱动測试。在測试时,把被測程序视为一个不能打开的黑盒子。在全然不考虑程序内部结构和内部特性的情况下进行。

l  採用黑盒測试的目的主要是在已知软件产品所应具有的功能的基础上,进行:

(1)检查程序功能是否能按需求规格说明书的规定正常使用。測试各个功能是否有遗漏,检測性能等特性要求是否满足。

(2)检測人机交互是否错误,检測数据结构或外部数据库訪问是否错误,程序能否适当地接收输入数据而产生正确的输出结果,并保持外部信息(如数据库或文件)的完整性。

(3)检測程序初始化和终止方面的错误。

3.3  三角形问题与NextDate函数

1、三角形问题

输入三个整数a、b、c,分别作为三角形的三条边,现通过程序推断由三条边构成的三角形的类型为等边三角形、等腰三角形、一般三角形(特殊的还有直角三角形),以及构不成三角形。

如今要求输入三个整数a、b、c,必须满足下面条件:

条件1   1≤a≤100        条件4   a<b+ c

条件2   1≤b≤100        条件5   b<a+ c

条件3   1≤c≤100        条件6   c<a+ b

l  假设输入值a、b、c不满足条件1、条件2和条件3 ,程序给出“边的取值超出同意范围”的信息。

l  假设输入值a、b、c 满足条件1、条件2和条件3。则输出下列四种情况之中的一个:

(1)假设不满足条件4、条件5和条件6中的一个,则程序输出为“非三角形”。

(2)假设三条边相等,则程序输出为“等边三角形”。

(3)假设恰好有两条边相等,则程序输出为“等腰三角形”。

(4)假设三条边都不相等。则程序输出为“一般三角形”。

l  结论:三角形问题的复杂之处在于输入与输出之间的关系比較复杂。

2、NextDate函数

NextDate函数说明还有一种复杂的关系。即输入变量之间逻辑关系的复杂性。

NextDate函数包括三个变量month、day和year,函数的输出为输入日期后一天的日期。

要求输入变量month、day和year均为整数值,而且满足下列条件:

条件1  1≤ month≤12

条件2  1≤ day ≤31

条件3  1912≤ year≤2050

l  结论:在NextDate函数中有两种复杂性的输入来源,一是输入域的复杂性,二是确定闰年的规则并要添加“额外天”。

3.4  等价类划分法

l  等价类划分法是一种重要的、经常使用的黑盒測试方法。它将不能穷举的測试过程进行合理分类,从而保证设计出来的測试用例具有完整性和代表性。

l  举例:设计这种測试用例,来实现一个对全部实数进行开平方运算( y =sqrt(x) )的程序的測试。

l  思考方向:因为开平方运算仅仅对非负实数有效,这时须要将全部的实数(输入域x)进行划分,能够分成:正实数、0 和 负实数。

如果我们选定+1.4444代表正实数,-2.345代表负实数。则为该程序设计的測试用例的输入为+1.4444、 0 和 -2.345。

l  等价类划分法是把全部可能的输入数据。即程序的输入域划分为若干部分(子集),然后从每个子集中选取少数具有代表性的数据作为測试用例。

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

在该子集合中。各个输入数据对于揭露程序中的错误都是等效的。它们具有等价特性,即每一类的代表性数据在測试中的作用都等价于这一类中的其他数据。这样,对于表征该类的数据输入将能代表整个子集合的输入。因此。能够合理的假定:——測试某等价类的代表值就是等效于对于这一类其他值的測试。

3.4.1  等价类的划分原则

l  等价类是输入域的某个子集合。而全部等价类的并集就是整个输入域。因此,等价类对于測试有两个重要的意义:

Ø  完备性——整个输入域提供一种形式的完备性

Ø  无冗余性——若互不相交则可保证一种形式的无冗余性

l  怎样划分?——先从程序的规格说明书中找出各个输入条件,再为每一个输入条件划分两个或多个等价类,形成若干的互不相交的子集。

l  採用等价类划分法设计測试用例通常分两步进行:

(1)确定等价类,列出等价类表。

(2)确定測试用例。

l  划分等价类可分为两种情况:

(1)有效等价类

是指对软件规格说明而言。是有意义的、合理的输入数据所组成的集合。利用有效等价类。可以检验程序是否实现了规格说明中预先规定的功能和性能。

(2)无效等价类

是指对软件规格说明而言,是无意义的、不合理的输入数据所构成的集合。利用无效等价类,能够鉴别程序异常处理的情况,检查被測对象的功能和性能的实现是否有不符合规格说明要求的地方。

l  进行等价类划分的根据:

(1)依照区间划分——在输入条件规定了取值范围或值的个数的情况下,能够确定一个有效等价类和两个无效等价类。

例:程序输入条件为小于100大于10的整数x,则有效等价类为10<x<100,两个无效等价类为x≤10和x≥100。

(2)依照数值划分——在规定了一组输入数据(如果包含n个输入值),而且程序要对每个输入值分别进行处理的情况下,可确定n个有效等价类(每个值确定一个有效等价类)和一个无效等价类(全部不同意的输入值的集合)。

例:程序输入x取值于一个固定的枚举类型{1,3,7,15},且程序 中对这4个数值分别进行了处理,则有效等价类为x=1、x=3、x=7、x=15,无效等价类为x≠1,3,7,15的值的集合。

(3)依照数值集合划分——在输入条件规定了输入值的集合或规定了“必须怎样”的条件下。能够确定一个有效等价类和一个无效等价类(该集合有效值之外)。

例:程序输入条件为取值为奇数的整数x。则有效等价类为x的值为奇数的整数。无效等价类为x的值不为奇数的整数。

(4)依照限制条件或规则划分——在规定了输入数据必须遵守的规则或限制条件的情况下。可确定一个有效等价类(符合规则)和若干个无效等价类(从不同角度违反规定)。

例:程序输入条件为以字符‘a’开头、长度为8的字符串。而且字符串不包括‘a’~ ‘z’之外的其他字符。则有效等价类为满足了上述全部条件的字符串,无效等价类为不以‘a’开头的字符串、长度不为8的字符串和包括了‘a’~ ‘z’之外其他字符的字符串。

(5)细分等价类——在确知已划分的等价类中各元素在程序中的处理方式不同的情况下,则应再将该等价类进一步划分为更小的等价类,并建立等价类表。

3.4.2  等价类划分法的測试用例设计

l  在设计測试用例时,应同一时候考虑有效等价类和无效等价类測试用例的设计。

l  依据已列出的等价类表可确定測试用例,详细步骤例如以下:

(1)首先为等价类表中的每个等价类分别规定一个唯一的编号。

(2)设计一个新的測试用例。使它可以尽量覆盖尚未覆盖的有效等价类。反复这个步骤。直到全部的有效等价类均被測试用例所覆盖。

(3)设计一个新的測试用例,使它仅覆盖一个尚未覆盖的无效等价类。反复这一步骤,直到全部的无效等价类均被測试用例所覆盖。

3.4.3  常见等价类划分測试形式

l  针对是否对无效数据进行測试,能够将等价类測试分为 标准等价类測试和健壮等价类測试。

Ø  标准等价类測试——不考虑无效数据值,測试用例使用 每一个等价类中的一个值。

Ø  健壮等价类測试——基本的出发点是考虑了无效等价类。对有效输入,測试用例从每一个有效等价类中取一个值; 对无效输入,一个測试用例有一个无效值,其它值均取 有效值。

健壮等价类測试存在两个问题:

(1)须要花费精力定义无效測试用例的期望输出

(2)对强类型的语言没有必要考虑无效的输入

3.4.4  使用等价类划分法測试的实例

实例1  三角形问题

分析:

在多数情况下,是从输入域划分等价类的。但并不是不能从被測程序的输出域反过来定义等价类,其实,这对于三角形问题却是最简单的划分方法。

在三角形问题中,有四种可能的输出:等边三角形、等腰三角形、一般三角形和非三角形。

利用这些信息可以确定下列输出(值域)等价类。

R1 = { <a,b,c>: 边为a,b,c的等边三角形 }

R2 = { <a,b,c>: 边为a,b,c的等腰三角形 }

R3 = { <a,b,c>: 边为a,b,c的一般三角形 }

R4 = { <a,b,c>: 边为a,b,c不能组成三角形 }

三角形问题的4个标准等价类測试用例

測试用例

a

b

c

预期输出

Test1

10

10

10

等边三角形

Test2

10

10

5

等腰三角形

Test3

3

4

5

一般三角形

Test4

4

1

2

非三角形

三角形问题的7个健壮等价类測试用例

測试用例

a

b

c

预期输出

Test1

5

6

7

一般三角形

Test2

-1

5

5

a值超出输入值定义域

Test3

5

-1

5

b值超出输入值定义域

Test4

5

5

-1

c值超出输入值定义域

Test5

101

5

5

a值超出输入值定义域

Test6

5

101

5

b值超出输入值定义域

Test7

5

5

101

c值超出输入值定义域

实例2  保险公司计算保费费率的程序

某保险公司的人寿保险的保费计算方式为:投保额×保险费率

当中,保险费率依点数不同而有别,10点及10点以上保险费率为0.6%。10点下面保险费率为0.1%;而点数又是由投保人的年龄、性别、婚姻状况和抚养人数来决定,详细规则例如以下:

年龄

性别

婚姻

抚养人数

20~39

40~59

其他

M

F

已婚

未婚

1人扣0.5点,最多扣3点

(四舍五入取整)

6点

4点

2点

5点

3点

3点

5点

计算保费费率的程序

(1)分析程序规格说明中给出和隐含的对输入条件的要求。列出等价类表(包含有效等价类和无效等价类)。

l  年龄:一位或两位非零整数。值的有效范围为1~99

l  性别:一位英文字符,仅仅能取值‘M’或’F’

l  婚姻:字符,仅仅能取值‘已婚’或‘未婚’

l  抚养人数:空白或一位非零整数(1~9)

l  点数 :一位或两位非零整数,值的范围为1~99

输入条件

有效等价类

编号

无效等价类

编号

年龄

20~39岁

1

 

 

40~59岁

2

 

 

1~19岁

60~99岁

3

小于1

12

大于99

13

性别

单个英文字符

4

非英文字符

14

非单个英文字符

15

M

5

除‘M’和‘F’之外的其他单个字符

16

F

6

婚姻

已婚

7

除‘已婚’和‘未婚’之外的其他字符

17

未婚

8

抚养人数

空白

9

除空白和数字之外的其他字符

18

1~6人

10

小于1

19

6~9人

11

大于9

20

(2)依据(1)中的等价类表。设计能覆盖全部等价类的測试用例。

測试用例编号

输入数据

预期输出

年龄

性别

婚姻

抚养人数

保险费率

1

27

F

未婚

空白

0.6%

2

50

M

已婚

2

0.6%

3

70

F

已婚

7

0.1%

4

0

M

未婚

空白

无法推算

5

100

F

已婚

3

无法推算

6

99

已婚

4

无法推算

7

1

Child

未婚

空白

无法推算

8

45

N

已婚

5

无法推算

9

38

F

离婚

1

无法推算

10

62

M

已婚

没有

无法推算

11

18

F

未婚

0

无法推算

12

40

M

未婚

10

无法推算

3.5  边界值分析法

3.5.1  边界值分析法概要

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

l  为什么使用边界值分析法?

无数的測试实践表明,大量的故障往往发生在输入定义域或输出值域的边界上,而不是在其内部。因此,针对各种边界情况设计測试用例,一般会取得非常好的測试效果。

l  如何用边界值分析法设计測试用例?

(1)首先确定边界情况。通常输入或输出等价类的边界就是应该着重測试的边界情况。

(2)选取正好等于、刚刚大于或刚刚小于边界的值作为測试数据,而不是选取等价类中的典型值或随意值。

边界值分析

l  边界值分析使用与等价类划分法同样的划分,仅仅是边界值分析假定错误很多其它地存在于划分的边界上,因此在等价类的边界上以及两側的情况设计測试用例。

l  例:測试计算平方根的函数

——输入:实数

——输出:实数

——规格说明:当输入一个0或比0大的数的时候,返回其正平方根;当输入一个小于0的数时,显示错误信息“平方根非法-输入值小于0”并返回0。库函数Print-Line能够用来输出错误信息。

实例分析

l  等价类划分:

-    能够考虑作出例如以下划分:

ü  输入 (i)<0 和 (ii)>=0

ü  输出 (a)>=0 和 (b) Error

-    測试用例有两个:

ü  输入4,输出2。

相应于 (ii) 和 (a) 。

ü  输入-10,输出0和错误提示。相应于(i)和(b)

l  边界值分析:

-    划分(ii)的边界为0和最大正实数;划分(i)的边界为最小负实数和0。由此得到下面測试用例:

ü  输入 {最小负实数}

ü  输入 {绝对值非常小的负数}

ü  输入 0

ü  输入 {绝对值非常小的正数}

ü  输入 {最大正实数}

l  通常情况下,软件測试所包括的边界检验有几种类型:

数字、字符、位置、质量、大小、速度、方位、尺寸、空间等

l  对应地,以上类型的边界值应该在:

最大/最小、首位/末位、上/下、最快/最慢、最高/最低、最短/最长、空/满等情况下

选择測试用例的原则

(1)假设输入条件规定了值的范围。则应取刚达到这个范围的边界值以及刚刚超过这个范围边界的值作为測试输入数据。

(2)假设输入条件规定了值的个数,则用最大个数、最小个数和比最大个数多1个、比最小个数少1个的数作为測试数据。

(3)依据程序规格说明的每一个输出条件,使用原则 (1)。

(4)依据程序规格说明的每一个输出条件,使用原则 (2) 。

(5)假设程序的规格说明给出的输入域或输出域是有序集合(如有序表、顺序文件等)。则应选取集合中的第一个和最后一个元素作为測试用例。

(6)假设程序中使用了一个内部数据结构,则应当选择这个内部数据结构的边界上的值作为測试用例。

(7)分析程序规格说明,找出其他可能的边界条件。

3.5.2  边界值分析法測试用例

l  採用边界值分析測试的基本思想是:故障往往出如今输入变量的边界值附近。

——因此,边界值分析法利用输入变量的最小值(min)、略大于最小值(min+)、输入值域内的随意值(nom)、略小于最大值(max-)和最大值(max)来设计測试用例。

l  边界值分析法是基于可靠性理论中称为“单故障”的如果,即有两个或两个以上故障同一时候出现而导致软件失效的情况非常少。也就是说。软件失效基本上是由单故障引起的。

——因此,在边界值分析法中获取測试用例的方法是:

(1) 每次保留程序中一个变量,让其余的变量取正常值。被保留的变量依次取min、min+、nom、max-和max。

(2) 对程序中的每一个变量反复 (1) 。

例:有二元函数f(x,y),当中x∈[1,12],y∈[1,31]。则採用边界值分析法设计的測试用例是:

{ <1,15>, <2,15>, <11,15>,<12,15>, <6,15>, <6,1>, <6,2>, <6,30>, <6,31>}

Ø  推论:对于一个含有n个变量的程序,採用边界值分析法測试程序会产生4n+1个測试用例。

健壮性測试

l  健壮性測试是作为边界值分析的一个简单的扩充。它除了对变量的5个边界值分析取值外,还须要添加一个略大于最大值(max+)以及略小于最小值(min-)的取值,检查超过极限值时系统的情况。因此,对于有n个变量的函数採用健壮性測试须要6n+1个測试用例。

3.5.3  边界值分析法測试举例

实例1  三角形问题的边界值分析測试用例

在三角形问题描写叙述中,除了要求边长是整数外,没有给出其他的限制条件。在此,我们将三角形每边边长的取范围值设值为[1, 100] 。

说明:假设程序规格说明中没有显式地给出边界值。则能够在设计測试用例前先设定取值的下限值和上限值。

測试用例

a

b

c

预期输出

Test1

60

60

1

等腰三角形

Test2

60

60

2

等腰三角形

Test3

60

60

60

等边三角形

Test4

50

50

99

等腰三角形

Test5

50

50

100

非三角形

Test6

60

1

60

等腰三角形

Test7

60

2

60

等腰三角形

Test8

50

99

50

等腰三角形

Test9

50

100

50

非三角形

Test10

1

60

60

等腰三角形

Test11

2

60

60

等腰三角形

Test12

99

50

50

等腰三角形

Test13

100

50

50

非三角形

 

实例2  NextDate函数的边界值分析測试用例

在NextDate函数中,隐含规定了变量mouth和变量day的取值范围为1≤mouth≤12和1≤day≤31。并设定变量year的取值范围为1912≤year≤2050 。

測试用例

Month

Day

Year

预期输出

Test1

6

15

1911

1911.6.16

Test2

6

15

1912

1912.6.16

Test3

6

15

1913

1913.6.16

Test4

6

15

1975

1975.6.16

Test5

6

15

2049

2049.6.15

Test6

6

15

2050

2050.6.15

Test7

6

15

2051

2051.6.15

Test8

6

-1

2001

day超出[1…31]

Test9

6

1

2001

2001.6.1

Test10

6

2

2001

2001.6.2

Test11

6

30

2001

2001.6.30

Test12

6

31

2001

输入日期超界

Test13

6

32

2001

day超出[1…31]

Test14

-1

15

2001

Mouth超出[1…12]

Test15

1

15

2001

20011.15

Test16

2

15

2001

2001.2.15

Test17

11

15

2001

2001.11.15

Test18

12

15

2001

2001.12.15

Test19

13

15

2001

Mouth超出[1…12]

3.6  因果图法

3.6.1  因果图法的简单介绍

l  因果图法产生的背景:

等价类划分法和边界值分析方法都是着重考虑输入条件,但没有考虑输入条件的各种组合、输入条件之间的相互制约关系。这样尽管各种输入条件可能出错的情况已经測试到了。但多个输入条件组合起来可能出错的情况却被忽视了。

假设在測试时必须考虑输入条件的各种组合,则可能的组合数目将是天文数字。因此必须考虑採用一种适合于描写叙述多种条件的组合、对应产生多个动作的形式来进行測试用例的设计,这就须要利用因果图(逻辑模型)。

l  因果图法是基于这种一种思想:一些程序的功能能够用判定表(或称决策表)的形式来表示。并依据输入条件的组合情况规定对应的操作。

l  因果图法的定义:是一种利用图解法分析输入的各种组合情况,从而设计測试用例的方法,它适合于检查程序输入条件的各种组合情况。

l  採用因果图法设计測试用例的步骤:

(1)依据程序规格说明书描写叙述,分析并确定因(输入条件)和果(输出结果或程序状态的改变)。画出因果图。

(2)将得到的因果图转换为判定表。

(3)为判定表中每一列所表示的情况设计一个測试用例。

l  使用因果图法的长处:

(1)考虑到了输入情况的各种组合以及各个输入情况之间的相互制约关系。

(2)可以帮助測试人员依照一定的步骤。高效率的开发測试用例。

(3)因果图法是将自然语言规格说明转化成形式语言规格说明的一种严格的方法,能够指出规格说明存在的不完整性和二义性。

3.6.2  因果图

l  因果图中用来表示4种因果关系的基本符号:

l  因果图中的4种基本关系

在因果图的基本符号中,图中的左结点ci表示输入状态(或称原因),右结点ei表示输出状态(或称结果)。ci 与 ei 取值0或1,0表示某状态不出现。1则表示某状态出现。

Ø  恒等:若c1是1,则e1也为1,否则e1为0。

Ø  非:若c1是1。则e1为0,否则e1为1。

Ø  或:若c1或c2或c3是1,则e1为1,否则为0。

Ø  与:若c1和c2都是1,则e1为1,否则e1为0。

l  因果图中的约束

在实际问题中输入状态相互之间、输出状态相互之间可能存在某些依赖关系,称为“约束”。对于输入条件的约束有E、I、O、R四种约束,对于输出条件的约束仅仅有M约束。

Ø  E约束(异):a和b中最多有一个可能为1,即a和b不能同一时候 为1。

Ø  I 约束(或):a、b、c中至少有一个必须为1。即 a、b、c不能同一时候为0。

Ø  O约束(唯一):a和b必须有一个且仅有一个为1。

Ø  R约束(要求):a是1时,b必须是1,即a为1时,b不能为0。

Ø  M约束(强制):若结果a为1,则结果b强制为0。

l  因果图中用来表示约束关系的约束符号:

l  因果图法终于生成的是决策表。利用因果图生成測试用例的基本过程例如以下:

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

(2)分析软件规格说明中的语义。找出原因与结果之间、原因与原因之间相应的关系, 依据这些关系画出因果图。

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

(4)把因果图转换为决策表。

(5)依据决策表中的每一列设计測试用例。

3.6.3  因果图法測试举例

l  实例  用因果图法測试下面程序。

程序的规格说明要求:输入的第一个字符必须是#或*,第二个字符必须是一个数字,此情况下进行文件的改动。假设第一个字符不是#或*。则给出信息N,假设第二个字符不是数字,则给出信息M。

Ø  解题步骤:

(1)分析程序的规格说明。列出原因和结果。

(2)找出原因与结果之间的因果关系、原因与原因之间的约束关系,画出因果图。

(3)将因果图转换成决策表。

(4)依据(3)中的决策表。设计測试用例的输入数据和预期输出。

因果图法測试举例(续)

(1)分析程序规格说明中的原因和结果:

原因

结果

c1:第一个字符是#

e1:给出信息N

c2:第一个字符是*

e2:改动文件

c3:第二个字符是一个数字

e3:给出信息M

(2)画出因果图(编号为10的中间结点是导出结果的进一步原因):

(3)将因果图转换成例如以下所看到的的决策表:

     规则

选项

1

2

3

4

5

6

7

8

条件:C1

1

1

1

1

0

0

0

0

C2

1

1

0

0

1

1

0

0

C3

1

0

1

0

1

0

1

0

10

 

 

1

1

1

1

0

0

动作:e1

 

 

 

 

 

 

e2

 

 

 

 

 

 

e3

 

 

 

 

 

不可能

 

 

 

 

 

 

測试用例

#3

#A

*6

*B

A1

GT

(4)依据决策表中的每一列设计測试用例:

測试用例编号

输入数据

预期输出

1

#3

改动文件

2

#A

给出信息M

3

*6

改动文件

4

*B

给出信息M

5

A1

给出信息N

6

GT

给出信息N和信息M

3.7  决策表法

3.7.1  决策表

l  在全部的黑盒測试方法中,基于决策表(也称判定表)的測试是最为严格、最具有逻辑性的測试方法。

l  决策表的概念:决策表是分析和表达多逻辑条件下运行不同操作的情况的工具。

l  决策表的长处:可以将复杂的问题依照各种可能的情况所有列举出来,简明并避免遗漏。因此,利用决策表可以设计出完整的測试用例集合。

l  在一些数据处理问题其中,某些操作的实施依赖于多个逻辑条件的组合,即:针对不同逻辑条件的组合值,分别运行不同的操作。决策表非常适合于处理这类问题。

决策表实例——“阅读指南”决策表

            规则

选项

1

2

3

4

5

6

7

8

问题

认为疲倦?

Y

Y

Y

Y

N

N

N

N

感兴趣吗?

Y

Y

N

N

Y

Y

N

N

糊涂吗?

Y

N

Y

N

Y

N

Y

N

建议

重读

 

 

 

 

 

 

 

继续

 

 

 

 

 

 

 

跳下一章

 

 

 

 

 

 

歇息

 

 

 

 

决策表的组成

l  决策表通常由下面4部分组成:

Ø  条件桩—列出问题的全部条件

Ø  条件项—针对条件桩给出的条件列出全部可能的取值

Ø  动作桩—列出问题规定的可能採取的操作

Ø  动作项—指出在条件项的各组取值情况下应採取的动作

决策表的生成

l  构造决策表的5个步骤:

(1) 确定规则的个数。

Ø  有n个条件的决策表有2n个规则(每一个条件取真、假值)。

(2) 列出全部的条件桩和动作桩。

(3) 填入条件项。

(4) 填入动作项,得到初始决策表。

(5) 简化决策表。合并相似规则。

Ø  若表中有两条以上规则具有同样的动作,而且在条件项之间存在极为相似的关系,便能够合并。

Ø  合并后的条件项用符号“-”表示,说明运行的动作与该条件的取值无关,称为无关条件。

三角形问题的决策表

               规则

选项

规则1-8

规则9

规则10

规则11

规则12

规则13

规则14

规则15

规则16

条件:

 

 

 

 

 

 

 

 

 

c1:a,b,c构成三角形?

N

Y

Y

Y

Y

Y

Y

Y

Y

c2:a=b?

-

Y

Y

Y

Y

N

N

N

N

c3:a=c?

-

Y

Y

N

N

Y

Y

N

N

c4:b=c?

-

Y

N

Y

N

Y

N

Y

N

动作:

 

 

 

 

 

 

 

 

 

a1:非三角形

 

 

 

 

 

 

 

 

a2:一般三角形

 

 

 

 

 

 

 

 

a3:等腰三角形

 

 

 

 

 

 

a4:等边三角形

 

 

 

 

 

 

 

 

a5:不可能

 

 

 

 

 

 

3.7.2  决策表应用

l  NextDate函数的决策表測试用例设计

Ø  问题分析:NextDate函数的三个变量之间在输入定义域中存在一定的逻辑依赖关系,因为等价类划分和边界值分析測试都如果了变量是独立的。如果採用上述两种方法设计測试用例,那么这些依赖关系在机械的选取输入值时可能会丢失。而採用决策表法则能够通过使用“不可能动作”的概念表示条件的不可能组合,来强调这样的依赖关系。

Ø  说明:当决策表规模(指规则的数目。n个条件的决策表有2n个规则)较大时,能够通过扩展条目决策表(条件使用等价类)、代数简化表、将大表“分解”为小表等方法。

实例说明

NextDate函数

l  为了获得下一个日期,NextDate函数运行例如以下操作:

Ø  假设输入日期不是当月最后一天,则把day变量的值加1;

Ø  假设输入日期是1~11月份中某月的最后一天。则把day变量的值复位为1,month变量的值加1;

Ø  假设输入日期是12月的最后一天。则day变量和month变量的值都复位为1,year变量的值加1。

l  关于最后一天的推断:

Ø  假设是有31天的月份(1,3,5,7,8,10,12),day变量值为31;

Ø  假设是有30天的月份(4,6,9,11)。 day变量值为30;

Ø  假设是有29天的月份(闰年的2月),day变量值为29。

Ø  假设是有28天的月份(非闰年的2月),day变量值为28。

NextDate函数的动作桩和条件桩

l  依据所运行的操作,可列出NextDate函数的动作桩:

a1: 不可能;a2:day加1;a3: day复位;a4: month加1;a5: month复位;a6: year加1

l  考虑到决策表的规模,条件使用month、day、year变量的等价类,在下面等价类集合上建立决策表:

Ø  对于month变量的取值

M1: {mouth: mouth有30天};   M2:{mouth:mouth有31天。12月除外};   

M3: {mouth:mouth有12月};    M4:{mouth:mouth是2月}。

Ø  对于day变量的取值

D1:{day:1≤day≤27};   D2: {day:day=28}。

D3: {day:day=29};     D4: {day:day=30};     D5: {day:day=31};

Ø  对于year变量的取值

Y1:{year:year是闰年};      Y2:{year:year不是闰年}

决策表应用(续)

l  决策表測试法适用于具有下面特征的应用程序:

if-then-else逻辑突出。输入变量之间存在逻辑关系。涉及输入变量子集的计算;输入与输出之间存在因果关系。

l  适用于使用决策表设计測试用例的条件:

Ø  规格说明以决策表形式给出,或较easy转换为决策表。

Ø  条件的排列顺序不会也不应影响运行的操作。

Ø  规则的排列顺序不会也不应影响运行的操作。

Ø  当某一规则的条件已经满足。并确定要运行的操作后,不必检验别的规则。

Ø  假设某一规则的条件要运行多个操作,这些操作的运行顺序无关紧要。

3.7.3  决策表測试应用案例

l  用决策表測试法測试下面程序:

该程序有三个输入变量month、day、year(month、day和year均为整数值,而且满足:1≤month≤12和1≤day≤31),分别作为输入日期的月份、日、年份,通过程序能够输出该输入日期在日历上隔一天的日期。比如,输入为2004年11月29日。则该程序的输出为2000年12月1日。

(1)分析各种输入情况,列出为输入变量month、day、year划分的有效等价类。

(2)分析程序规格说明。结合以上等价类划分的情况给出问题规定的可能採取的操作(即列出全部的动作桩)。

(3)依据(1)和(2),画出简化后的决策表。

案例分析

l  month变量的有效等价类:

M1: {month=4,6,9,11}  M2:{month=1,3,5,7,8,10}    M3: {month=12}   M4: {month=2}

l  day变量的有效等价类:

D1: {1≤day≤26}    D2: {day=27}        D3: {day=28}        D4: {day=29}        D5:{day=30}        D6: {day=31}

l  year变量的有效等价类:

Y1:  {year是闰年}             Y2:  {year不是闰年}

l  考虑各种有效的输入情况,程序中可能採取的操作有下面六种:

a1: day+2              a2: day=2       a3: day=1              a4:month+1   a5: month=1   a6: year+1

3.8  错误猜測法

l  错误猜測法的概念:基于经验和直觉猜測程序中全部可能存在的各种错误。从而有针对性的设计測试用例的方法。

l  错误猜測方法的基本思想:列举出程序中全部可能有的错误和easy错误发生的特殊情况。依据它们选择測试用例。

比如:

Ø  在单元測试时曾列出的很多在模块中常见的错误、以前产品測试中以前发现的错误等。这些就是经验的总结。

Ø  还有,输入数据和输出数据为0的情况、输入表格为空格或输入表格仅仅有一行等。这些都是easy错误发生的情况。可选择这些情况下的样例作为測试用例。

第4章  白盒測试及其用例的设计

4.1  白盒測试方法

l  为什么要进行白盒測试?

假设全部软件错误的根源都能够追溯到某个唯一原因,那么问题就简单了。然而,其实一个bug 经常是由多个因素共同导致的。

如果此时开发工作已结束。程序送交到測试组,没有人知道代码中有一个潜在的被 0 除的错误。若測试组採用的測试用例的运行路径没有同一时候经过x=0和y=5/x进行測试,显然測试工作似乎很完好,測试用例覆盖了全部运行语句,也没有被 0 除的发生错误。

l  白盒測试也称结构測试或逻辑驱动測试。是针对被測单元内部是怎样进行工作的測试。

它依据程序的控制结构设计測试用例。主要用于软件或程序验证。

l  白盒測试法检查程序内部逻辑结构。对全部逻辑路径进行測试,是一种穷举路径的測试方法。但即使每条路径都測试过了,仍然可能存在错误。由于:

Ø  穷举路径測试无法检查出程序本身是否违反了设计规范。即程序是否是一个错误的程序。

Ø  穷举路径測试不可能查出程序由于遗漏路径而出错。

Ø  穷举路径測试发现不了一些与数据相关的错误。

l  採用白盒測试方法必须遵循下面几条原则。才干达到測试的目的:

Ø  保证一个模块中的全部独立路径至少被測试一次。

Ø  全部逻辑值均需測试真 (true) 和假 (false) 两种情况。

Ø  检查程序的内部数据结构,保证其结构的有效性。

Ø  在上下边界及可操作范围内执行全部循环。

l  白盒測试主要是检查程序的内部结构、逻辑、循环和路径。经常使用測试用例设计方法有:

Ø  逻辑覆盖法(逻辑驱动測试)

Ø  基本路径測试方法

4.2  白盒測试的基本概念

4.2.1  控制流图

l  控制流图(可简称流图)是对程序流程图进行简化后得到的,它能够更加突出的表示程序控制流的结构。

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

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

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

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

常见结构的控制流图

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

4.2.2  环形复杂度

l  环形复杂度也称为圈复杂度。它是一种为程序逻辑复杂度提供定量尺度的软件度量。

l  环形复杂度的应用——能够将环形复杂度用于基本路径方法,它能够提供:程序基本集的独立路径数量。确保全部语句至少运行一次的測试数量的上界。

Ø  独立路径是指程序中至少引入了一个新的处理语句集合或一个新条件的程序通路。採用流图的术语,即独立路径必须至少包括一条在本次定义路径之前不曾用过的边。

l  測试能够被设计为基本路径集的运行过程,但基本路径集通常并不唯一。

计算环形复杂度的方法

l  环形复杂度以图论为基础。为我们提供了很实用的软件度量。可用例如以下三种方法之中的一个来计算环形复杂度:

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

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

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

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

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

4.2.3  图矩阵

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

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

l  通常,控制流图中的结点用数字标识,边则用字母标识。

假设在控制流图中从第 i 个结点到第 j 个结点有一个标识为 x 的边相连接,则在相应图矩阵的第 i 行第 j 列有一个非空的元素 x 。

4.3  覆盖測试

4.3.1  測试覆盖率

l  測试覆盖率:用于确定測试所运行到的覆盖项的百分比。当中的覆盖项是指作为測试基础的一个入口或属性,比方语句、分支、条件等。

l  測试覆盖率能够表示出測试的充分性。在測试分析报告中能够作为量化指标的根据。測试覆盖率越高效果越好。但覆盖率不是目标,仅仅是一种手段。

l  測试覆盖率包含功能点覆盖率和结构覆盖率:

Ø  功能点覆盖率大致用于表示软件已经实现的功能与软件须要实现的功能之间的比例关系。

Ø  结构覆盖率包含语句覆盖率、分支覆盖率、循环覆盖率、路径覆盖率等等。

4.3.2  逻辑覆盖法

l  依据覆盖目标的不同。逻辑覆盖又可分为语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、组合覆盖和路径覆盖。

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

Ø  判定覆盖:通过运行足够的測试用例,使得程序中的每一个判定至少都获得一次“真”值和“假”值, 也就是使程序中的每一个取“真”分支和取“假”分支至少均经历一次。也称为“分支覆盖”。

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

l  判定/条件覆盖:设计足够多的測试用例,使得程序中每一个判定包括的每一个条件的全部情况(真/假)至少出现一次,而且每一个判定本身的判定结果(真/假)也至少出现一次。

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

l  组合覆盖:通过运行足够的測试用例,使得程序中每一个判定的全部可能的条件取值组合都至少出现一次。

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

l  路径覆盖:设计足够多的測试用例,要求覆盖程序中全部可能的路径。

语句覆盖

l  要实现DoWork函数的语句覆盖。仅仅需设计一个測试用例就能够覆盖程序中的全部可运行语句。

Ø  測试用例输入为:{ x=4、y=5、z=5 }

Ø  程序运行的路径是:abd

l  分析:

语句覆盖能够保证程序中的每一个语句都得到运行,但发现不了判定中逻辑运算的错误,即它并非一种充分的检验方法。比如在第一个判定((x>3)&&(z<10))中把“&&”错误的写成了“||”,这时仍使用该測试用例。则程序仍会依照流程图上的路径abd运行。能够说语句覆盖是最弱的逻辑覆盖准则。

判定覆盖

l  要实现DoWork函数的判定覆盖。须要设计两个測试用例。

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

Ø  程序运行的路径各自是:abd。ace

l  分析:

上述两个測试用例不仅满足了判定覆盖,同一时候还做到语句覆盖。

从这点看似乎判定覆盖比语句覆盖更强一些,但仍然无法确定判定内部条件的错误。比如把第二个判定中的条件y>5错误写为y<5,使用上述測试用例。照样能按原路径运行而不影响结果。因此。须要有更强的逻辑覆盖准则去检验判定内的条件。

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

条件覆盖

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

l  对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

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

測试用例

运行路径

覆盖条件

覆盖分支

x=4、y=6、z=5

abd

T1、T2、T3、T4

bd

x=2、y=5、z=15

ace

-T1、-T2、-T3、-T4

ce

l  分析:上面这组測试用例不但覆盖了4个条件的所有8种情况。并且将两个判定的4个分支b、c、d、e也同一时候覆盖了。即同一时候达到了条件覆盖和判定覆盖。

l  说明:尽管前面的一组測试用例同一时候达到了条件覆盖和判定覆盖,可是,并非说满足条件覆盖就一定能满足判定覆盖。

假设设计了下表中的这组測试用例,则尽管满足了条件覆盖,但仅仅是覆盖了程序中第一个判定的取假分支c 和第二个判定的取真分支d,不满足判定覆盖的要求。

測试用例

运行路径

覆盖条件

覆盖分支

x=2、y=6、z=5

acd

-T1、T2、-T3、T4

cd

x=4、y=5、z=15

acd

T1、-T2、T3、-T4

cd

判定/条件覆盖

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

l  依据判定/条件覆盖的基本思想,仅仅需设计下面两个測试用例便能够覆盖4个条件的8种取值以及4个判定分支

測试用例

运行路径

覆盖条件

覆盖分支

x=4、y=6、z=5

abd

T1、T2、T3、T4

bd

x=2、y=5、z=15

ace

-T1、-T2、-T3、-T4

ce

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

Ø  比如:对于第一个判定(x>3)&&(z<10)来说,必须x>3和z<10这两个条件同一时候满足才干确定该判定为真。

假设x>3为假。则编译器将不再检查z<10这个条件,那么即使这个条件有错也无法被发现。对于第二个判定(x==4)||(y>5)来说,若条件x==4满足,就觉得该判定为真,这时将不会再检查y>5。那么相同也无法发现这个条件中的错误。

组合覆盖

l  组合覆盖的目的是要使设计的測试用例能覆盖每个判定的全部可能的条件取值组合。

l  对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,第二个判定的取假分支

l  依据组合覆盖的基本思想,设计測试用比例如以下:

測试用例

运行路径

覆盖条件

覆盖组合号

x=4、y=6、z=5

abd

T1、T2、T3、T4

1和5

x=4、y=5、z=15

acd

T1、-T2、T3、-T4

2和6

x=2、y=6、z=5

acd

-T1、T2、-T3、T4

3和7

x=2、y=5、z=15

ace

-T1、-T2、-T3、-T4

4和8

l  分析:上面这组測试用例覆盖了全部8种条件取值的组合,覆盖了全部判定的真假分支。可是却丢失了一条路径abe。

路径覆盖

l  前面提到的5种逻辑覆盖都未涉及到路径的覆盖。其实,仅仅有当程序中的每一条路径都受到了检验,才干使程序受到全面检验。路径覆盖的目的就是要使设计的測试用例能覆盖被測程序中全部可能的路径。

l  依据路径覆盖的基本思想。在满足组合覆盖的測试用例中改动当中一个測试用例,则能够实现路径覆盖:

測试用例

运行路径

覆盖条件

x=4、y=6、z=5

abd

T1、T2、T3、T4

x=4、y=5、z=15

acd

T1、-T2、T3、-T4

x=2、y=5、z=15

ace

-T1、-T2、-T3、-T4

x=5、y=5、z=5

abe

T1、T2、-T3、-T4

l  分析:尽管前面一组測试用例满足了路径覆盖,但并没有覆盖程序中全部的条件组合(丢失了组合3和7),即满足路径覆盖的測试用例并不一定满足组合覆盖。

l  说明:

Ø  对于比較简单的小程序,实现路径覆盖是可能做到的。但假设程序中出现较多推断和较多循环,可能的路径数目将会急剧增长,要在測试中覆盖全部的路径是无法实现的。为了解决这个难题,仅仅有把覆盖路径数量压缩到一定的限度内。如程序中的循环体仅仅运行一次。

Ø  在实际測试中,即使对于路径数非常有限的程序已经做到路径覆盖,仍然不能保证被測试程序的正确性,还须要採用其它測试方法进行补充。

4.3.3  面向对象的覆盖

l  继承上下文覆盖

Ø  因为传统的结构化度量没有考虑面向对象的一些特性(如多态、继承和封装等),所以在面向对象领域,传统的结构化覆盖必须被加强。以满足面向对象特性。

Ø  继承上下文覆盖考虑在每一个类的上下文内获得的覆盖率级别。它是扩展到面向对象领域里的一种覆盖率度量方法。用于度量在系统中的多态调用被測试得多好。

Ø  继承上下文定义将基类上下文内例行程序的运行作为独立于继承类上下文内例行程序的运行。相同,它们在考虑继承类上下文内例行程序的运行也独立于基类上下文内例行程序的运行。为了获得100%继承上下文覆盖,代码必须在每一个适当的上下文内被全然运行。

l  基于状态的上下文覆盖

Ø  在绝大多数面向对象的系统中存在这种一些类:这些类的对象能够存在于众多不同状态中的不论什么一种,而且因为类的行为依赖于状态。每一个类的行为在每一个可能的状态中其性质是不同的。

Ø  基于状态的上下文覆盖相应于被測类对象的潜在状态。

Ø  这样基于状态的上下文覆盖把一个状态上下文内的一个例行程序的运行觉得是独立于还有一个状态内同例子行程序的运行。

为了达到100%的基于状态的上下文覆盖。例行程序必须在每一个适当的上下文(状态)内被运行。

4.3.4  測试覆盖准则

l  逻辑覆盖的出发点是合理的、完好的。所谓“覆盖”,就是想要做到全面而无遗漏。但逻辑覆盖并不能真正做到无遗漏。

l  比如:我们不小心将前面提到的程序段中的if (x>3 &&Z<10) { …… }错写成if (x>=3 &&Z<10) { …… }

依照我们前面设计的測试用例(x的值取2或4)来看。逻辑覆盖对这种小问题都无能为力。分析出现这一情况的原因在于:错误区域只在x=3这个点上。即仅当x的值取3时,測试才干发现错误。

面对这类情况,我们应该从中吸取的教训是測试工作要有重点。要多针对easy发生故障的地方设计測试用例。

l  ESTCA覆盖准则:在easy发生故障的地方设计測试用例,即重视程序中谓词(条件推断)的取值。

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

Ø  [规则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]  对外部输入变量赋值,使其在每个測试用例中均有不同的值与符号。并与同一组測试用例中其它变量的值与符号不同。

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

l  关于LCSAJ

Ø  LCSAJ (Linear CodeSequence and Jump) 的字面含义是线性代码序列与跳转。在程序中,一个LCSAJ是一组顺序运行的代码,以控制跳转为其结束点。

Ø  LCSAJ的起点是依据程序本身决定的。

它的起点能够是程序第一行或转移语句的入口点,或是控制流可跳达的点。

Ø  假设有几个LCSAJ首尾相接。且第一个LCSAJ起点为程序起点,最后一个LCSAJ终点为程序终点。这种LCSAJ串就组成了程序的一条路径(LCSAJ路径)。一条LCSAJ程序路径可能是由2个、3个或多个LCSAJ组成的。

l  基于LCSAJ与路径的关系,提出了层次LCSAJ覆盖准则。它是一个分层的覆盖准则,能够概括的描写叙述为:

Ø  第一层 — 语句覆盖。

Ø  第二层 — 分支覆盖。

Ø  第三层 — LCSAJ覆盖,即程序中的每个LCSAJ都至少在測试中经历过一次。

Ø  第四层 — 两两LCSAJ覆盖,即程序中的每两个相连的LCSAJ组合起来在測试中都要经历一次。

Ø  第n+2层 — 每n个首尾相连的LCSAJ组合在測试中都要经历一次。

l  在实施測试时,若要实现上述的层次LCSAJ覆盖。须要产生被測程序的全部LCSAJ。

l  例:找出前面DoWork函数的全部LCSAJ和LCSAJ路径。

Ø  LCSAJ(5个):

  (1)int k=0,j=0;      if ( (x>3)&&(z<10) )

  (2)k=x*y-1;   j=sqrt(k); if( (x==4)||(y>5) )

  (3)if ( (x==4)||(y>5) )

  (4)j=x*y+10; j=j%3

  (5)j=j%3

Ø  LCSAJ路径(4条):

(1)-(2)-(4)      (1)-(2)-(5)      (1)-(3)-(4)      (1)-(3)-(5)

4.4  路径測试

4.4.1  路径表达式

l  为了满足路径覆盖。必须首先确定详细的路径以及路径的个数。

我们通常採用控制流图的边(弧)序列和节点序列表示某一条详细路径。更为概括的表示方法为:

(1)弧a和弧b相乘。表示为ab。它表明路径是先经历弧a。接着再经历弧b。弧a和弧b是先后相接的。

(2)弧a和弧b相加。表示为a+b,它表明两条弧是“或”的关系,是并行的路段。

l  路径数的计算:

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

4.4.2  基本路径測试方法

l  路径測试就是从一个程序的入口開始,运行所经历的各个语句的完整过程。

从广义的角度讲,不论什么有关路径分析的測试都能够被称为路径測试。

l  完毕路径測试的理想情况是做到路径覆盖,但对于复杂性大的程序要做到全部路径覆盖(測试全部可运行路径)是不可能的。

l  在不能做到全部路径覆盖的前提下,假设某一程序的每个独立路径都被測试过,那么能够觉得程序中的每个语句都已经检验过了,即达到了语句覆盖。这样的測试方法就是通常所说的基本路径測试方法。

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

(1)画出程序的控制流图。

(2)计算程序的环形复杂度。导出程序基本路径集中的独立路径条数。这是确定程序中每一个可运行语句至少运行一次所必须的測试用例数目的上界。

(3)导出基本路径集。确定程序的独立路径。

(4)依据(3)中的独立路径,设计測试用例的输入数据和预期输出。

4.4.3  循环測试方法

l  从本质上说。循环測试的目的就是检查循环结构的有效性。

l  通常,循环能够划分为简单循环、嵌套循环、串接循环和 非结构循环4类。

(1)測试简单循环。

设其循环的最大次数为n ,可採用下面測试集:

Ø  跳过整个循环;

Ø  仅仅循环一次;

Ø  仅仅循环两次;

Ø  循环 m 次,当中m<n;

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

(2)測试嵌套循环。假设将简单循环的測试方法用于嵌套循环,可能的測试次数会随嵌套层数成几何级数添加。 此时可採用下面办法降低測试次数:

Ø  測试从最内层循环開始,全部外层循环次数设置为最小值;

Ø  对最内层循环依照简单循环的測试方法进行;

Ø  由内向外进行下一个循环的測试,本层循环的全部外层循环仍取最小值,而由本层循环嵌套的循环取某些“典型”值;

Ø  反复上一步的过程。直到測试全然部循环。

(3)測试串接循环。若串接的各个循环相互独立,则可分别採用简单循环的測试方法;否则採用嵌套循环的測试方法。

(4)对于非结构循环这样的情况,无法进行測试,须要按结构化程序设计的思想将程序结构化后。再进行測试。

Z路径覆盖下的循环測试方法

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

l  循环简化的目的是限制循环的次数,不管循环的形式和循环体实际运行的次数,简化后的循环測试仅仅考虑运行循环体一次和零次(不运行)两种情况,即考虑运行时进入循环体一次和跳过循环体这两种情况。

4.4.4  产生測试用例

l  在实践中,除了前面给出的各种方法外,通常还能够採用下面三种方法来补充设计測试用例:

(1)通过非路经分析得到測试用例

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

(2)寻找尚未測试过的路径并生成对应的測试用例

    ——这样的方法须要穷举被測程序的全部路径,并与前面已測试路径进行对照。

(3)通过指定特定路径并生成对应的測试用例

4.5  最少測试用例数计算

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

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

l  为了把问题化简,避免出现測试用例极多的组合爆炸,把构成循环操作的反复型结构用选择结构取代。

这样,任一循环便改造成进入循环体或不进入循环体的分支操作了。

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

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

Ø  图中的 (c) 和 (d) 两种反复型结构代表了两种循环。在做了简化循环的如果以后,对于一般的程序控制流,我们仅仅考虑选择型结构。

其实它已经能体现顺序型和反复型结构了。

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

l  显然,要測试这个小程序,须要至少提供4个測试用例才干作到逻辑覆盖。使得ac、ad、bc及bd操作均得到检验。

事实上,这里的4是图中的第1个分支谓词引出的两个操作,及第2个分支谓词引出的两个操作组合起来而得到的,即2×2=4。而且,这里的2是因为两个并列的操作。即1+1=2 而得到的。

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

Ø  假设在N-S图中存在有并列的层次A1、A2,A1和A2的最少測试用例个数分别为a1、a2,则由 A1、A2 两层所组合的 N-S图相应的最少測试用例数为a1×a2。

Ø  假设在N-S图中不存在有并列的层次,则相应的最少測试用例数由并列的操作数决定,即N-S图中除谓词之外的操作框的个数。

l  例:例如以下图所看到的的N-S图。至少须要多少个測试用例完毕逻辑覆盖?

Ø  因为图中并不存在并列的层次

Ø  最少測试用例数由并列的操作数决定

Ø  即为1+1+1=3。

Ø  因为图中没有包括并列的层次

Ø  最少測试用例数仍由并列的操作数决定

Ø  即为1+1+1+1+1=5。

Ø  图中的2345和67是并列的两层。

Ø  2345层相应的最少測试用例数为1+1+1+1+1=5

Ø  67层相应的測试用例数为1+1+1=3

Ø  2345和67这两层组合后相应的測试用例数为5×3=15

Ø  最后,因为两层组合后的部分是不满足谓词1时所要做的操作。还要加上满足谓字1做业务。因此,要求在整个程序的测试用例数15+1=16。

版权声明:本文博客原创文章,博客,未经同意,不得转载。

标签: 面向对象 角形