如果能够提升抽象层级,测试设计师会更加有效和有效率。
完全改正软件是不可能到达的,其原因是可以以形式化的方式来表述的而且是富有哲理的。聪明的软件工程师不再追求软件的完全正确,而是试着评判软件的行为来决定其是否为可接受的。**包括可靠性、安全性、可维护性、安保性、还有效率。**这比验证软件是正确的要复杂的多。
模型驱动测试设计 MDTD过程把测试分成一系列的小任务,从而简化测试用例的生成。然后测试设计师在高层次的抽象等级上使用数学化的工程结构来设计测试用例,这样做可以独立于软件内部细节、独立于设计所基于的软件工件、也独立于测试自动化和测试执行。
MDTD中需要思考的关键一步是设计测试用例,测试用例设计是能否成功发现软件失败的决定性因素。我们可以使用一种基于人工的方法来设计测试用例,测试工程师使用软件应用领域的专业知识还有他们的经验来设计有效的能找到软件故障的测试用例。还有另一种方法就是使之满足具有明确定义的工程目标,比如覆盖准则。
2.1 软件测试基础
一个最重要的事实之一是,测试只能说明失败的存在,而不能说明已经找到了所有失败,这是基础理论上的限制。 具体来说,找到程序里的所有失败是一个不可判定的问题,测试者通常认为如果一个测试用例运行失败,那么这个测试用例就是成功的。
前面关于故障和失败的定义让我们发展出了可达性,影响,传播和揭示性模型(RIPR),首先区分一下测试和调试。
测试: 通过观察软件的执行以评估软件。
测试失败: 执行一个测试用例后给出软件失败的结果。
调试: 在软件失败的前提下找故障的过程。
这里的核心问题是给定一个故障,不是所有的输入都能够触发那个故障,从而导致不正确额输出。同样,将观察到的失败和软件内部对应的故障相关联也是非常困难的。从对这些问题的分析引导出了故障/失败模型。这四个条件一起被称为 故障/失败模型,或是RIPR模型 。也就是 测试 到达 有故障的程序位置影响 不正确的程序状态传播到 程序最终状态不正确的部分。
2.2 软件测试活动
测试工程师是一名信息技术的专业人士,他负责一项或多项技术性的测试活动,包括设计测试输入、生成测试用例、执行测试脚本、分析测试结果、向开发人员和上级经理汇报结果。
测试经理管理一名或多名测试工程师,测试经理制定测试规章和进程与项目中别的经理进行交流,除此之外,还要帮助组内工程师有效地有效率的测试软件。
测试工程师最强有力的工具是形式化的覆盖准则。使用形式化的覆盖准则可以决定使用什么样的测试输入更有可能找到程序中的问题,这也就更好地保证了软件的质量及其可靠性。覆盖准则还为工程师提供了测试停止原则。
2.3 基于软件活动的测试级别
测试用例可以来自需求,规范,设计工件或是源代码。在传统的教科书中,不同的测试层级伴随着不同的软件开发活动。
验收测试: 根据需求和用户需要来评估软件。
系统测试: 根据体系结构的设计和系统整体的行为来评估软件。
集成测试: 根据子系统的设计来评估软件。
模块测试: 根据详细设计来评估软件。
单元测试: 根据代码实现来评估软件。
上图是v字模型,展示测试等级的一种典型划分,以及这些测试等级是如何分别和软件开发活动一一对应。每个测试等级的信息通常由相对应的软件开发活动推导出来。即使软件在代码实现之前都是不可执行的,这里也强烈建议设计测试用例应与相对应的软件开发活动对应。因为及早发现缺陷是降低成本的最好方式。
1、软件开发过程中的需求分析阶段需要抓住客户的需求。设计验收测试是检验全部完成软件是否在实际上满足这些要求。
2、软件开发过程中的体系结构设计阶段负责选取组件和用于组件间通信的连接器,二者结合起来完成系统的实现以保证系统的规范满足之前所确定的需求。系统测试是为了确认集成后的系统是否满足其规范。
3、软件开发过程中的子系统设计阶段指定了各个子系统的结构和行为,每个子系统负责整体体系结构中的一些功能,子系统通常会在以前软件的基础上继续开发。设计集成测试是为了评估子系统模块之间的接口是否一致,以及通信是否正确,其前提就是各个模块之间工作正常。
4、软件开发过程中详细设计阶段决定着单独模块的结构和行为,一个模块是相关单元的集合,这些集合组成一个文件,包,或是类。设计模块测试是为了单独评估各个独立的模块,包括单元之间的交互还有单元和相关数据结构之间的交互。又因为经常由开发人员负责的,通常又被称为开发人员测试。
5、软件开发过程中的实现阶段的内容就是生成代码。一个程序单元或一个过程是由一个或多个连续的语句外加一个名字构成的。单元测试是最低等级的测试,其目的是评估实现阶段产生的单元。
前面没有提到回归测试,这是软件开发过程维护阶段中必不可少的。当更新软件时,执行回归测试来确保软件更新后和更新前保持相同的功能。
虽然大多数文献强调什么时候应用这些测试级别,但更重要的区别是不同测试级别所能检测到的故障类型。故障存在于待测的软件工件中,而能否找到故障取决于推到出测试用例的软件工件。
面向对象的软件改变着测试层级,面向对象的软件使得单元和模块的界限变得模糊,随意面向对象软件的测试研究发展出了上述测试等级的一些变种。
方法内测试评估单个的方法,方法间测试评估的是一个类的一组方法,类间测试检测的是一个完整的类。通常是一个类中一系列方法调用。最后类间测试同时检测多个类。前2个是单元测试和模块测试的变种,而类间测试时集成测试的一种。
2.4 覆盖准则
测试的核心问题是数字,甚至一个很小的程序都会由非常多的输入,所以无论是做什么测试,我们都不可能用所有可能的输入值来进行测试。从任何一个实用的角度来说,输入空间都是无限的。使用覆盖准则让我们以结构化和实用化的方法来搜索输入空间。满足一个覆盖准则能在两个关键目标上给予测试者一定的信心:
1、已经检查了输入空间的很多角落
2、测试用例之间只有很小的重叠。
覆盖准则在提高质量和减少测试数据生成成本方面有很大的优势,覆盖准则能够最大化投入产出,即用更少的测试用例来有效的找出更多的故障。
2.5 模型驱动测试设计
开发测试用例的工作可以划分成四个不相重叠的步骤:测试设计,测试自动化,测试执行和测试评估。
测试设计
测试设计是一个生成输入值以有效的测试软件的过程,实际上工程师通过两种通用的方法来设计测试用例。
在基于准则和测试设计中,要求测试值满足工程上的目标,比如覆盖准则。
在基于人工的测试设计中,我们基于程序应用领域的专业知识和对测试的人为理解来设计测试值。
测试自动化
测试设计的最终结果是软件的测试输入值。测试自动化是把测试值加载到可执行脚本中的过程。注意支持测试设计的自动化工具不被认为是测试自动化。测试自动化对有效和高频率地执行测试用例是很有必要的。
测试执行
测试执行是在软件上运行测试用例并记录测试结果的过程。这只需要测试者具备基本的计算机技术。
测试评估
测试评估是评价测试结果然后汇报给开发者的过程。实际上这个比看起来要难得多。
测试者和抽象
前面四个任务关注设计、实现和执行测试用例。这样的分类忽略了一些重要的任务,比如测试管理,维护和文档。MDTD让测试设计师提升了抽象的级别,以至于只需要很少的测试者就可以完成设计和开发测试用例中数学应用的部分。在测试设计创建之后,传统的测试者和开发者完成他们的任务:生成测试值、自动化测试用例、执行和评估测试用例。
2.6 MDTD为什么重要
MDTD代表的软件测试含义,是测试准测的定义和应用是独立与测试级别(单元、集成、系统和其他级别的)。
将测试设计和测试用例构建与执行分离开的好处。
第一、在多个方面测试活动。
第二、同时将这些活动组合成一个有效率的过程。
故障与失败和测试与调试的联系是:
故障一般不是测试到的,而且发生故障一定是某个最根本的功能首先失败,然后引发后续反应。而失败专指某一次目标未达成的情况。测试的目的是在不知道有问题存在的情况下来寻找和发现问题,而调试是在已经知道问题存在的情况下来定位问题根源