软件测试的目的是为了发现软件设计和实现过程中的疏忽所造成的错误。测试是可以事先计划并可以系统的进行一系列活动。
软件测试的策略性方法
软件测试策略为开发人员提供了测试模板,且具备以下特征:
为完成有效的测试,软件团队应该进行有效的,正式的技术评审。通过评审,许多错误可以在测试开始之前排除;
测试开始于构件层,然后向外延伸到整个基于计算机系统的集成;
不同的测试技术适用于不同的时间点;
测试由软件开发人员和(对大型项目而言)独立的测试组执行;
测试和调度是不同的活动,但任何测试策略中都必须包括调试。
(1)验证与确认
软件测试是通常所讲的更广泛主题——验证与确认,Verification and Validation,V&V的一部分。
验证:指确保软件正确的实现某一特定功能的一系列活动。它确定的是,我们在正确的构造产品吗?
确认:指确保开发的软件可追溯到用户需求的另外一系列活动。它确定的是,我们在构造正确的产品吗?
验证与确认包含了广泛的SQA活动,software Quality Assurance,软件质量保证。包括:正式技术评审,质量和配置审核,性能监控,仿真,可行性研究,文档评审,数据库评审,算法分析,开发测试,易用性测试,合格性测试以及安装测试。
(2)软件测试组织
软件开发人员认为自己的程序是正确的,测试是破坏性的。开发者设计和执行测试,试图证明的不是发现其中的错误,而是证明程序的正确性,但往往错误是存在的。开发人员与测试人员有一种对立关系存在。人们对软件开发人员产生一些误解:
软件开发人员根本不应该做测试;应当让爱挑毛病的陌生人进行软件测试;测试人员仅在测试步骤即将开始时参与项目。
软件开发人员总是要负责程序的个别单元(构件)测试,确保每个单元完成其功能或显示出被设计的行为。多数情况下,开发者也进行集成测试。在软件体系结构完成后,独立的测试组才开始介入。
独立测试组,Independent Test Group,ITG,的作用是为了避免开发人员进行测试所引发的固有问题,它可以消除可能存在认识差异。在独立测试时,开发人员和测试组密切配合以确保测试严格的进行。从分析与设计开始到计划和制定测试规程,ITG参与整个项目过程。从这种意义上讲,ITG是大型软件开发项目组的一部分。
(3)传统软件体系结构的测试策略
软件过程如以上图螺旋所示.开始时系统工程定义软件角色,从而引出需求分析,在需求分析中建立软件的信息域,功能,行为,性能,约束和确认标准。沿螺旋向内,经过设计阶段,最后到达编码阶段,每走一圈都会降低软件的抽象层次。
软件测试策略也可以放在螺旋模型中进行考虑。单元测试起始于螺旋中心,侧重于以源码形式实现的每个单元(构件)。沿螺旋向外,是集成测试,此时的测试重点在于软件体系结构的设计和构造。再向外一圈,是确认测试,这个阶段,依据已经建立的软件对需求进行确认。最后到达系统测试阶段,将软件与系统的其他部分作为一个整体来测试,从内到外,每一圈都拓宽了测试范围。
从过程的角度考虑整个测试过程,软件工程环境中的测试实际上按顺序实现四个步骤:
最初,测试侧重于单个构件,确保它完全作为一个单元来起作用,因此称为单元测试。单元测试充分利用测试技术,检查构件中的每个控制结构的特定路径以确保完全覆盖,并最大可能的发现错误。
然后,组装或集成各个构件以形成完整的软件包。集成测试处理并验证与程序构造相关的问题。在集成过程中,普遍使用关注输入和输出的测试作例设计技术。
集成完成后,要执行一系列的高阶测试,必须评估确认准则。确认测试为软件满足所有功能,行为,性能需求提供最后的保证。
最后,高阶测试已经超出软件工程的边界,进入更广泛的计算机系统工程范围,软件一旦确认,就必须和其它系统成分结合在一起。系统测试验证所有的成分能合适地结合在一起,且能满足整个系统的功能和性能需求。
(4)面向对象软件体系结构的测试策略
面向对象软件测试的总体策略在思想上与用于传统体系结构的策略是一致的,但测试方法是不同的。进行小型测试时,重点由传统意义上的单个模块测试变换为包含属性和操作且隐含着通信与协作的类的测试。随着类集成为一个面向对象体系结构,运行一系列的集成测试以发现由于类间的通信与协作产生的错误以及新类加入而引起的副作用。最后作为一个整体来测试系统,以确保发现需求中的错误。
策略问题
如果要实现一个成功的软件测试策略,须解决以下问题:
早在开始测试之前,就要以量化的方式规定产品需求。测试主要目的用于找错,但也能评估其他质量特性。
显式地陈述测试目标。测试的特定目标应该用可测量的术语进行陈述。
了解软件的用户并为每类用户建立用户轮廓。为每类用户描述交互场景用例,侧重于测试产品的实际使用,可以减少整个测试的工作量。
建立强调快速周期测试的测试计划。
建立能够测试自身的健壮软件。
测试之前,利用有效的正式技术评审作为过滤器。
实施正式技术评审以评估测试策略和测试用例本身。
为测试过程建立一种持续的改进方法。
传统软件的测试策略
(1)单元测试
单元测试侧重于软件设计的最小单元的验证工作。这里的单元指软件构件或模块。
单元测试考虑:测试模块的接口为了保证被测试程序单元的信息能正常的流入和流出;检查局部数据结构以确保临时存储的数据在算法的整个执行过程中能维护其完整性;遍历控制结构中所有独立路径以确保模块中的所有语句至少被执行一次;测试边界条件以确保模块在到达边界值的极限或受限处理的情形下仍能正确执行。
在单元测试期间,选择测试的执行路径是最基本的任务。计算中常见的错误有:
被误解的或不正确的算术优先级;混合模式操作;不正确的初始化;不精确的精度;表达式有不正确的符号表示;
测试用例应能发现以下错误:
不同数据类型的比较;不正确逻辑运算符或不正确的优先级;应该相等但因精度错误而不相等;不正确的变量比较;不正确的循环或死循环;遇到分支循环时不能退出;对循环变量的不适当修改。
设置异常处理路径以便当错误出现时重定路径或彻底中断处理。这种方法叫防错技术。在评估异常处理时,应该测试以下潜在的错误:
错误难以理解;记录的错误与真正遇到的错误不一致;在异常处理之前,错误条件就引起了操作系统的干预;不正确的异常条件处理;错误描述未提供充足的信息以便于找到错误产生的原因。
单元测试规程
单元测试的设计可以在编码之前,敏捷方法中以测试驱动进行。另一种是在源码生成之后。
(2)集成测试
如果单元测试完成后,那么当它们放在一起工作时,可以会存在一些问题,例如,数据在通过接口时可能丢失,一个模块可能对另一模块产生负面影响,子功能合在一起不能达到预期功能等等。
集成测试是构造软件体系结构的系统化技术,同时也是进行一些旨在发现与接口相关的错误的测试。其目标是利用已通过单元测试的构件建立设计中描述的程序结构。
自顶向下集成测试是一种构造软件体系结构的增量方法。模块的集成顺序从主控模块开始,沿着控制层次结构逐步向下,利用深度优先或广度优先方式将从属于或间接从属于主控模块集成到结构中。
深度优先集成步骤:
主控模块用作测试驱动程序,所有的桩模块替换为直接从属于主控模块的模块;
依靠所选择的集成方法,用实际模块一次一个的替换从属桩模块;每个模块集成时都执行测试;在完成每个测试集之后,用实际模块替换另一个桩模块;可以执行回归测试以确保没有引入新的错误。整个过程从第二步循环进行,直到整个程序构造完成。
自底向上集成。从原子模块开始进行构造和测试。在处理时所需要的从属于给定层次的模块总是存在,所以,没有必要使用桩模块。自底向上集成策略可利用以下步骤实现:
连接低层构件以构成完成特定子功能的簇;写驱动程序以协调测试用例的输入和输出;测试簇;去掉驱动程序,沿着程序结构向上逐步连接簇。
回归测试
当软件发生变更时,建立了新的数据流路径,出现新的IO,以及调用了新的控制逻辑。这些变更可能使本来可正常工作的功能产生问题。在集成测试策略环境下,回归测试是重新执行已经进行测试的某个子集,以确保变更没有传播不期望的副作用。
回归测试可以通过重新执行所有测试用例的子集手工进行,也可以利用捕捉/回放工具进行自动化测试。回录测试套件即将要执行的测试子集包含三种测试用例:
能够测试软件所有功能的有代表性的测试样本;额外测试,侧重于可能会受变更影响的软件功能;侧重于已被改变的软件构件测试。
冒烟测试,相关活动包括:
将已经转换为代码的软件构件集成为簇(build)。一个簇包括所有的数据文件,库,可复用的模块以及实现一个或多个产品功能所需的工程化构件;设计一系列测试以暴露影响簇正确的完成其功能的错误。其目的是为了发现极有可能造成项目延迟的业务阻塞错误;每天该簇与其他簇及整个软件产品集成起来进行冒烟测试。
冒烟测试应用于复杂的,时间关键的软件工程项目时,提供了以下好处:
降低了集成风险,较早发现不相容性和业务阻塞错误,降低了对项目进度造成严重影响的可能性;提高最终产品的质量,这种测试是面向构造的,可能发现功能性错误,也可能发现体系结构和构件级设计错误;简化错误的诊断和修正;易于评估进展状况,随着时间的推移,更多软件被集成,展示出软件工作情况。
策略的选择
自顶向下,自底向上各有优缺点。自顶向下方法的主要缺点是需要桩以及桩带来的测试难题。自底向上集成测试方法主要缺点在于:直到加入最后一个模块,一直没有一个作为实体的程序。
集成测试文档
软件集成的总体计划和特定的测试描述应该在测试规格说明中文档化。这个文档包含测试计划和测试规程,它是软件过程的工作产品,也是软件配置的一部分。
面向对象软件测试策略
(1)面向对象环境中的单元测试
在考虑面向对象软件时,单元的概念发生了变化。封装的类是单元测试的重点。
(2)面向对象环境中的集成测试
两种不同的策略:一是基于线程的测试,thread-based testing,集成响应系统的一个输入或事件所需的一组类。另一方法是基于使用的测试,use-based testing,通过测试很少的使用服务类(如果有)的那些类开始构造系统,独立类测试完后,利用独立类测试下一层的类(依赖类)。继续依赖类的测试直到完成整个系统。
簇测试,cluster testing,利用试图发现协作中的错误的测试用例来测试协作的类簇。
确认测试
确认测试始于集成测试的结束,那时已经测试完单个构件,软件已经组装成完整的软件包,且接口错误已被发现和改正。在确认测试或系统级测试时,传统软件与面向对象软件的差别已经消失,测试便集中于用户可见的动作和用户可识别的系统输出。
(1)确认测试准则
软件确认是通过一系列表明已经符合软件需求的测试而获得的。执行每个确认测试用例之后,存在两种可能条件之一:功能或性能特征符合需求规格说明;发现了与规格说明的偏差,创建缺陷列表。
(2)配置评审
评审的目的是确保所有的软件配置元素已正确开发,编目,且具有支持软件生命周期支持阶段的必要细节。有时称之为审核。
(3)阿尔法测试与贝塔测试
阿尔法测试由最终用户在开发者的场所进行,它在受控环境下进行。开发者在现场。
贝塔测试在最终用户场所进行。开发者不在现场。接到贝塔测试问题报告后,进行修改,然后准备向最终用户发布软件产品。
系统测试
系统测试实际上是对整个基于计算机的系统进行一系列不同考验的测试。
(1)恢复测试
通过各种方式强制地让系统发生故障并验证其能适当恢复的一种系统测试,如果是自动的,则对重新初始化,检查点机制,数据恢复,重新启动都要进行正确性评估;如果要人工干预,则要估算平均恢复时间,以确定其是否在可接受的范围之内。
(2)安全测试
安全测试验证建立在系统内的保护机制是否能够实际保护系统不受非法入侵。在测试过程中,测试者扮演攻击系统的角色。
(3)压力测试
压力测试是以一种要求反常数据,频率或容量的方式执行系统。它另一个变体称为敏感性测试。
(4)性能测试