
1.7 软件测试的过程
无论是传统的软件测试,还是敏捷软件测试,软件测试的一些基本活动是相同的,只是和看问题的角度有关系,不同的维度有不同的结果。
从项目管理角度看,软件测试分为测试计划、测试实施与监控;如果再进一步分解,可以分为测试计划、测试设计、测试执行、测试结果分析与评估、测试报告。
如果从软件工程维度看,软件测试活动主要有:需求评审、设计评审、单元测试、集成测试、系统测试和验收测试等。但传统的软件测试和敏捷软件测试,其测试活动的介入时间、活动形式,甚至测试的对象、测试依据等都存在着较大差异。例如,传统的软件测试对规范的需求文档进行评审,而敏捷测试是对用户故事(user story)进行评审,而且传统软件测试具有明显的阶段性,而在敏捷测试中,测试的阶段性不够显著,更强调“持续测试”。下面,我们就详细来讨论传统的测试过程和敏捷测试过程。
1.7.1 传统的软件测试过程
在传统的瀑布模型中,软件测试只是作为一个阶段性工作,处于编程之后。而正确的软件工程思想是将软件测试看作是贯穿整个软件生命周期的软件质量保证的重要手段之一,而不是编程之后的一个阶段。在编程中免不了要进行单元测试,写代码和单元测试同步进行,效果更好。更何况,缺陷在早期更容易被发现,且缺陷发现越早,返工的周期越短,给企业带来的劣质成本就越低,这些都需要我们从需求评审、设计评审开始,才能更好地确保软件产品的质量,更好地介入到软件产品的开发活动或软件项目实施中。软件测试从开发生命周期的阶段来划分,如图1-6所示,可以分为需求评审、设计评审、单元测试、集成测试、系统测试、验收测试等。不同阶段的输入和输出标准见表1-1。即使从项目管理角度来看,其测试计划、测试设计、测试执行、测试结果分析和评估、测试报告等活动的阶段性也是显著的。

图1-6 传统的软件测试过程
表1-1 软件测试阶段的输入和输出标准

从快速开发模型(V模型)出发,对V模型进行改进,就可以得到W模型,如图1-7所示。W模型能更准确地描地述软件测试和软件开发之间的关系,更好地展示贯穿整个生命周期的测试。

图1-7 软件测试和软件开发之间的关系
测试的活动建立在软件开发的成果之上,即测试的对象就是软件开发的阶段性成果,如设计文档、程序代码和可执行的程序。而软件开发的进一步活动依赖于测试的结果,如果测试结果反映开发成果正确、良好,开发活动可以快速地进入下一个阶段,否则,开发活动需要修正当前阶段所存在的缺陷,不能进入下一个阶段。在前期,软件过程的活动主要集中在设计、实现阶段,设计和实现能力决定整个软件过程的进展状态。自然,测试过程前期更多地依赖于开发过程。在后期,测试策略和能力会直接影响测试效率,测试效率高就能更快地发现缺陷,缺陷就能更快地被修正,所以开发过程后期更多地依赖于测试过程。
(1)在需求阶段,测试人员参与需求分析、需求定义和需求评审,不仅能发现需求定义的问题,而且可以深入了解产品的设计特性、用户的真实需求,确定测试目标,开始制定测试计划。
(2)在软件设计阶段,测试人员可以了解系统是如何实现的、系统架构的构成等各类问题,对系统设计进行评审,并可以提前准备系统的测试环境,着手研究如何测试系统。还可以开展其他一些测试活动,如系统测试用例设计、测试工具的选型或启动测试工具的开发、进一步完善测试计划等。
(3)在做详细设计时,测试人员可以直接参与具体的设计和设计的评审,找出设计的缺陷。同时,完成功能特性方面的测试用例,并基于这些测试用例开发测试脚本。
(4)在编程阶段,单元测试是不可缺少的,更容易、更快地发现程序当中所存在的缺陷,充分的单元测试是集成测试、系统测试的基础。
1.7.2 敏捷测试过程
敏捷测试是符合敏捷测试宣言的思想、遵守敏捷开发原则,在敏捷开发环境下能够很好地和其整体开发流程融合的一系列的测试实践。敏捷测试作为敏捷开发的组成部分,能够适应敏捷开发的流程,具有鲜明的敏捷开发的特征,如测试驱动开发(TDD)、验收测试驱动开发(ATDD)。

究竟什么是敏捷测试

TDD
敏捷测试与传统测试的区别如下。
(1)传统测试更强调测试的独立性,将“开发人员”和“测试人员”角色分得比较清楚。敏捷测试强调整个团队对质量、对软件测试负责,可以没有专职的测试人员。
(2)传统测试更具有阶段性,从需求评审、设计评审、单元测试到集成测试、系统测试等。例如,传统开发中,先让产品人员去写需求,需求文档写好之后,测试人员再参加评审。但敏捷测试团队每一天都在一起工作,一起讨论需求,一起评审需求,更强调持续测试、持续的质量反馈,测试的持续性更为显著。
(3)传统测试强调测试的计划性,认为没有良好的测试计划和不按计划执行测试就难以控制和管理,而敏捷测试更强调测试的速度和适应性,侧重计划的不断调整以适应需求的变化。
(4)传统测试强调测试是由“验证”和“确认”两种活动构成的,而敏捷测试没有这种区分,始终以用户需求为中心,每时每刻不离用户需求,将验证和确认统一起来。
(5)传统测试强调任何发现的缺陷都要记录下来,以便进行缺陷根本原因分析,达到缺陷预防的目的,并强调缺陷跟踪和处理的流程,区分测试人员和开发人员的各自不同的责任。而敏捷测试强调面对面的沟通、协作,强调团队的责任,不太关注对缺陷的记录与跟踪。

ATDD

Web应用ATDD
(6)传统测试更关注缺陷,围绕缺陷开展一系列的活动,如缺陷跟踪、缺陷度量、缺陷分析、缺陷报告质量检查等,而敏捷测试更关注产品本身,关注可以交付的客户价值。在快速交付的敏捷开发模式下,缺陷修复的成本很低。
(7)传统测试鼓励自动化测试,但由于传统开发的周期比较长(几个月到几年),即使没有自动化测试也是可以应付的。一般来说,回归测试能够获得几周时间,甚至1~2个月的时间,自动化测试的成功与否对测试没有致命的影响。敏捷测试的持续性迫切要求测试的高度自动化,在1~3天内就要完成整个的验收测试(包括回归测试)。没有自动化,就没有敏捷,自动化测试是敏捷测试的基础。

ATDD实战
在敏捷测试流程中,参与单元测试,关注持续迭代的新功能,针对这些新功能进行足够的验收测试,而对原有功能的回归测试则依赖于自动化测试。由于敏捷方法中迭代周期短,测试人员尽早开始测试,包括及时对需求、开发设计的评审,更重要的是能够及时、持续地对软件产品的质量进行反馈。如果再具体一些,使流程更具可操作性,需要以敏捷Scrum为例,来介绍敏捷测试的流程。先看看Scrum流程,从图1-8中可以看出,除了最后“验收测试”阶段,其他过程似乎没有显著的测试特征,但隐含的测试需求和特征还是存在的。

图1-8 Scrum流程示意图
(1)Product Backlog(需求定义阶段),在定义用户需求时测试要做什么?测试除需要考虑客户的价值大小(优先级)、工作量基本估算之外,还需要认真研究与产品相关的用户的行为模式(如BDD)、产品的质量需求,哪些质量特性是我们需要考虑的?有哪些竞争产品?这些竞争产品有什么特点(优点、缺点等)?
(2)Sprint Backlog(阶段性任务划分和安排),这时候需要明确具体要实现的功能特性和任务,作为测试,这时候要特别关注“Definition of Done”,即每项任务结束的要求,也就是任务完成的验收标准,特别是功能特性的设计和代码实现的验收标准。ATDD的关键一步也体现在这里,在设计、写代码之前,就要将验收标准确定下来。一方面符合测试驱动开发思想,第一次就要把事情做对,预防缺陷;另一方面持续测试和验收测试的依据也清楚了,可以快速做出测试通过与否的判断。
(3)在每个迭代(Sprint)实施阶段,主要完成Sprint Backlog所定义的任务,这时除了TDD或单元测试之外,应该进行持续集成测试或通常说的BVT(build verification test)。而且开发人员在设计、写代码时都会认真考虑每一组件或每一代码块都具有可测试性,因为测试任务可能由他们自己来完成。如果有专职的测试人员角色,一方面可以完善单元测试、集成测试框架,协助开发人员进行单元测试;另一方面可以针对新实现的功能特性进行更多的探索式测试,同时开发验收测试的脚本。如果没有专职的测试人员角色,这些事情也要完成,只是由整个团队共同完成。虽没有工种的分工,但也存在任务的分工。
(4)验收测试可以由自动化测试工具完成,但一般情况下,不可能做到百分之百的自动化测试。例如易用性测试就很难由工具完成。即使对性能测试是由工具完成的,还需要人来设计测试场景,包括关键业务选择、负载模式等。敏捷的验收测试与传统的验收测试不同,侧重对“Definition of Done”的验证,但基本的思想和传统开发是一致的,任何没有经过验证的产品特性是不能直接发布出去的。