从测试工程师那里听到的最普遍的抱怨是直到过程中很晚的时候才能有效地参与到软件开发项目中。此外,测试通常是在开发人员在抗争损坏一个接一个版本候选的很晚出现的缺陷时所逼出的行为。到一个合适的候选版本出现的时候,测试人员已经成为瓶颈,显然,要对进一步的延迟负责。
Rational Unified Process®,或 RUP®,广泛地概括了测试规程(Test Discipline),并介绍了测试角色如何及早地参与项目生命周期。
我希望在本文中介绍另一种观点。代替由测试规程开始,我将依次考虑每个 RUP 阶段的风险管理原则,并询问经验丰富的测试人员,为了促进那些目标他们可能会做些什么。虽然测试工程师不能估算总的项目成本,但是他们的确可以评估对成本的测试贡献,并且提出测试风险和可行性。虽然他们不应该计划解决方案架构,但是他们可以帮忙度量。虽然测试人员不构建一系列可执行程序,但是他们可以评估每个可执行程序如何表示一个从前一个而来的进展。虽然测试人员不构建最终的候选版本,但是他们可以确保具有可接受的质量。
我相信在 RUP 的每个阶段,测试人员都有机会对项目做出大量贡献。该贡献远远地扩展了,例如,要求更早地测试交付内容 —— 或者更早地执行一组标准的测试 —— 比传统的瀑布驱动过程中。本文应作为面向开发团队中的测试人员的 RUP 原则的激励说明来阅读。它不应该作为 RUP 测试规程的概要或初级读物。虽然我相信许多测试人员会觉得该信息很有用,但是我还相信管理人员将会对看到测试人员的能力和经验如何在 RUP 项目的所有阶段中更有效地应用感兴趣。
初始(Inception)阶段:管理业务风险
RUP 的初始阶段是对准业务风险的管理。为了制定出自该阶段的可行或不可行的决策,我们需要了解
带着此信息,涉众被聚集到生命周期目标(Lifecycle Objectives,LCO)会议上。如果项目被视为是可行且值得做的,那么项目会继续进入精化阶段。
评估成本
可行性和成本是 LCO 会议上的重要因素,并且测试人员无疑可以为该决策贡献重要的数据。测试人员可以估算对成本的测试贡献,甚至有时候可以有助于可行性问题。记住,在初始阶段中,尽管我们只对球场的数字感兴趣。过高的精确度将给我们带来不真实精确度的不适当安全感。
也许有或也许没有实际的可执行程序作为 LCO 简报的一部分。这些可能由技术示范者、现有产品的快速出租,或者也许是更实质的东西组成。我的意见是在如此初步的阶段执行如此正式的操作是不适当的。
因为测试成本对总的开发成本做出贡献,所以我已经列出许多对测试成本做出贡献的行为。
精化(Elaboration)阶段:管理技术风险
RUP 的精化阶段是对准技术风险的管理的。为了制定出自该阶段的可行或不可行的决策,我们需要论证一个对每个鉴别出的技术风险的满意解决方案。通常,最糟的技术问题由非功能需求导致。非功能需求可以造成这样的有趣断言“系统将拥有 99.999% 的可用性,”或者“系统将支持 10,000 个同时发生的用户会话。”这些需求写起来便宜,但满足和测试起来昂贵。为了进行适当的评估,我们需要了解:
有了此数据,架构师可以选择最适当的架构,并且,当涉众面对他们需求的所有含意时,通常会更愿意调节他们的雄心,并且得到更多的回报。
因此,关键的评估需求是其中一个度量,并且这应该是此阶段测试人员主要的目标。
量度方法的评估
对于每个技术问题,架构团队将建立一个或多个具体表现一个解决方案方法的可执行系统。可能会有若干有竞争的解决方案(举例来说,通信中的 UDP 对 TCP)和大量的对于每个解决方案的可配置选择(举例来说,进程架构中的 10 线程 对 50 个线程)。测试人员执行对生成架构的度量所必需的步骤。
度量强调的是是否对解决方案有了成熟的考虑而不是功能是否被正确的实现了,因为没有人会期望生命周期中早期就实现完全正确的功能或者甚至花费大量的精力去雕琢还不成熟的系统的功能。初始阶段中指定的许多实验室环境将在精化阶段中被需要。我们将度量性能和可伸缩性,跨过通信链接和出自数据库的数据速率,随负载变化时的响应时间,并且我们将生成需求所要求的其他度量。根据所有的架构原型执行这些测试,并且测试团队将与架构师携手工作,共同设计确认或驳斥每个设计决策的测试。
当传统测试人员可能会参与整个基于文档的活动时,测试团队在此阶段的行为与瀑布过程中所做的惊人地不同。当项目从一个危机牵绊到下一个时,许多工作都不相关了。相反,在迭代的项目的精化阶段,测试人员在起劲的行动着,被闪光灯和不停的拨号所围绕。测试人员赞成相关的且实际的测试,使它们与架构师保持一致,并且评估并解释结果。
当然这是富有挑战的工作,但同时还是要大量参与的、有价值的,并令人满意的。如果对于小型的团队环境及上千行的代码的情况建立这些测试都是棘手的,那么设想一下对上百万行的代码项目的大型团队来说所受到的阻碍。
虽然这个阶段执行测试设计和实现,但是我们应该记住,重要的是测试结果而不是测试文档。由于将会抛弃许多架构的提议,所以相关的测试也一样。我们仅需要做足够的测试设计和实现,用以获得必需的度量。我们不像细化提议那样做太多测试,随着最主要的架构候选的出现,我们可以添加严密,如可溯性和其他文档。
测试设计
作为并行活动,精化阶段表现出一次方便的时机来考虑技术架构中的小变更如何能够更好的帮助测试设计和测试自动化。
通过测试自动化,我的意思是使用记录键盘和鼠标事件的 GUI 记录或回放工具,可以回放来重复测试。经验丰富的测试人员知道自动化尤其要求重要的脚本维护工作。值得考虑一下允许脚本构造的“测试架构”,这与设计人员创建“软件架构”来简化应用程序构造具有同样意义。
测试人员应该考虑解决方案,特别是测试可能参数化的方法或映射到需求所暗示的“组合爆炸”的结合方法的复杂性维度。例如,考虑一个指定某个需要支持的平台组合的非功能需求。根据一个平台撰写脚本,在所有平台上“回放”是有利的。这同样可以应用到数据库后端、应用程序服务器、Web 服务器和环境基础架构的其他元素,并且特别是对于这些的排列组合。手动测试每个组合将是不能忍受的痛苦。测试自动化是唯一经济的解决方案。
大多数应用程序为测试人员的专长提供许多应用程序专用的机会。设计人员将找到“用参数表示”问题领域的方法,并且这些经常成为类似地用参数表示测试所沿着的维度。例如,在我所工作过的一个应用程序中,有许多看起来一样的屏幕上的表格,因此设计人员将列参数化为通用的小部件,这给予测试人员类似的能力来用参数表示它们的测试。
针对测试的设计在精化阶段如此重要的一个原因是在构建阶段很难找出时间来适当处理这一活动。但是有一个甚至更好的理由:通过测试人员和设计人员之间的良好对话,架构中的小让步可以给测试设计添加一个大好处。总而言之,精化阶段是针对测试而设计的适当时机。
构建(Construction)阶段:管理进度风险
RUP 的构建阶段瞄准进度风险的管理。如果应用了 RUP 首选的基于用例的方法,就可以比利用传统的(瀑布)方法更快地集中于可用的(尽管不完全)系统。当达到这一可用地不完全层次,剩下的路也就不远了。
该方法生成了一系列客观的改进的可执行系统,并且拥有重要的优势:
在几个星期内,我们就会完成一个分析——设计——编码——测试的周期,这个给我们一种明显进展的感觉。这就是构建阶段的迭代的独特之处。测试活动评估进展并验证确实有了进展。
评估进展
RUP 提到的迭代节奏到构建阶段还是活跃着的,并且该频率与测试人员有特别的关系。测试人员的主要目标是能够客观地描述系统的当前状态,并且能够将该状态与以前的状态进行比较。这两个状态之间的区别,简单地说,就是进展。
测试人员的“节奏”源于以下活动。
针对进展的量度
我们已经回顾了测试人员在构建阶段所做的事情。我们如何将其转化为进展的量度呢?有多种描述恰当的技术, 3 以下的处理是可以借鉴的。
检查点 | 描述 |
---|---|
被识别的场景 | 放弃用例分析。被识别的可选流和例外流的有趣的组合。在精化阶段的末尾完成 80%。 |
详细的场景 | 使对象与所描述的事件顺序协作。 |
被识别的测试用例的数量 | 该数字经常是 1,但是每个场景有多个测试用例是可能的。应该包含每个测试用例的原因或目的。 |
定义的测试用例 | 测试用例与相关的文当工作一起产生。这包括到驱动需求的链接、测试方法、前置和后置条件、测试数据及可观察的结果。 |
实现的测试脚本 | 特定的初始条件,将应用程序导航到测试位置的指导,输入测试数据的顺序,观察结果的方法,结果值的设置。 |
执行的测试 | 至少已经执行一次测试脚本。 |
曾经通过的测试 | 先前测试执行已经通过了所有构建。可选择地,最近通过的时期。 |
通过的测试 | 测试执行通过了最近的迭代。 |
我们确定表 1 中每个场景和测试中所描述的每个检查点。不论完成或是没完成,它们的值都严格地报告为是或不是的值。我们合计每一层并将其表示为前一个层的某个百分比。目标是达到每一层的 100% 覆盖。总的结果相当粗略,但针对达到最高百分比的工作带来了提前测试工作的非常有意义的副加作用。
我们还能够通过余下的迭代的数量和平均的缺陷分辨工作来增加每个迭代的预期缺陷。这指示了显著的缺陷负担,包括在还没撰写的代码中没有发现的缺陷!这些是粗略的数字,但是是要求全部的完成百分比的重要基础。
这些量度证明测试人员应该看作是项目经理重要的数据来源。
构建迭代测试优先级
用例驱动的迭代方法生成了新的机会和新的负担。因为我们将已经限制阻碍完全测试的资源,所以我们应该根据以下优先级顺序执行测试:
上面的三项应看作是绝对极小值,并且不能实现它们的应该看作是测试过程的主要失败。我们应该继续三个步骤:
当然,应该优先选择不需要维护当前连编的自动化测试。随着时间的推移,我们应该能够收集从中可以预计测试工作的量度,例如,维护自动化测试要多少工作,运行手动测试要多少工作,等等。
每个项目团队必须分辨的一个问题是测试活动与开发活动并行的方式。从某种意义上讲,一旦对开发人员来说迭代结束了,对于测试人员迭代就开始了。
测试优先的方法
测试优先的方法在最近五年内受到了相当大的推动。简单地说,开发人员在撰写代码之前要撰写一个测试。每个分支、循环,或其他逻辑在加入源代码之前都要写出将要执行结果的自动化测试。
测试优先主要在构建阶段,主要由开发人员执行,而不是测试人员。可以将其尽早地引入精化阶段,但如您所见到的,强调的不是功能的完整性。
产品化(Transition)阶段:管理可接受的风险
验收测试应该已经是所有测试人员都熟悉的,因此此讨论将只涵盖验收的重点。
总体上我将定义验收活动包含部署,以及因此发现的所有问题和缺陷。这是 RUP 在产品化阶段所描述的内容,并且测试人员将其理解为验收的评估。
测试人员在支持项目经理达到项目阶段目标上起着关键作用。无疑会有大量增加的请求以及低优先级的缺陷,无论哪里,只要可能,这些都应当延迟到新的维护项目中。
评估可接受性
产品化阶段中强调的是分辨缺陷并停止项目。不允许新的功能。开发人员有时候称项目中这一点为“代码烂泥” —— 换句话说,还没有“代码冻结”,因为某些类型的变更还允许出现。
测试人员在发布计划中起很大作用。这包括测试工作和进度(应该源于最近的构建迭代中获得的测试工作量度)。预先应该已经确定了,构成缺陷级别和其他量度的可接收的门限是什么。这可能意味着(例如),零关键缺陷,只有一个工作区至多一个“高优先级”缺陷,五个“中等”,及许多“低级”的。因此,测试人员可以指定并跟踪版本候选是否具有适当的质量。
产品化阶段将构建阶段“开发的”缺陷跟踪与外部的面对客户的及服务台的缺陷跟踪连结起来。测试版程序的许多优势之一是该支持及跟踪机制可以实行。
从理论上讲,如果对可交付内容做出了任何变更,都应该执行完整的测试集合。在安全至上的系统中,这很可能成为一个需求,甚至是一个规章。在一般的商业环境中,测试人员可以帮助项目经理决定运行哪个测试子集。这可能包含所有自动化测试、一些手动测试,再加上,比方说,在“实验室”中的五天时间(也就是,在 MTBF 环境中)。测试人员将使用在其上测试最可能产生失败的量度。当创建软件“补丁”时,测试人员履行类似的职责。
数据格式支持、数据转换,及数据迁移是产品化阶段和客户部署中的重要活动。这些都在测试人员的职责范围内。有时候,测试人员回顾用户指导和其他文档。技术作者执行此任务。
测试、编码、迭代,和量度
量度已经在我们的讨论中表现显著。测试是量度重要的来源和用户。当测试进展量度结合开发进展量度时,我们获得项目状态及其可能道路的引人注目的全面指示。这些客观的预测是管理用户期望,及能够精确地估算、请求,并防御额外的进度或资源所必要的。
像这些量度在传统的瀑布过程中是很难收集的。它是迭代生命周期与使收集和应用成为可能的适当测试过程的交汇点。
总结:摇尾巴的狗是好狗
在传统的开发模型中,直到预定的交付之前的最后“失败”时刻,测试人员经常作为二等公民。然后,他们成为关键的瓶颈,在其中会出现无休止的挑挑拣拣。
RUP 为测试人员提供了另一种观点。您在其中可以在整个项目中立即做作出贡献,并且减轻每个人的负担。
注释
1 ISO 是国际标准组织(International Organization for Standardization)的名称,SEI 是卡内基梅隆大学的软件工程学院,IEEE 是电子及电气工程师协会,它为计算行业颁布了多种标准。
2 参看 COCOMO II,了解在估算中应用系数的技术。
3参见 Walker Royce,Software Project Management: A Unified Perspective,Addison-Wesley 1998 年。