UML软件工程组织

迭代测试的谬论与事实
Laura Rose, Quality Engineering Manager, IBM

本文来自于 Rational Edge:软件测试专家Laura Rose将会质疑和揭穿一些广泛流传的关于迭代开发和迭代测试通常的一些荒谬的言论。她将解释迭代开发原则是如何解决这些通常的误解的,并会把你带到测试方法的真正道路上。
谬论的产生是由于缺乏直接的经验。在缺乏信息的情况下,我们根据自己的想法形成了一些信念,并且会抱着怀疑的态度去看待我们所不知道的事情。在软件开发领域,荒谬的想法将会给接近客观真实的问题带来困难,因此把预算和时间推到了风险上。

在我作为质量保证经理的时候,我从大量的软件开发实践中获得了经验,这种经验包括迭代开发和称作“瀑布式”的方法。前者模型通常会被认为比后者的方法更加现代。但是这往往是一个荒谬的想法:两种方法都是产生于60年代。另外一个荒谬的想法是认为瀑布方法盛行于70年代。被誉为瀑布方法之父的Winston Royce认为这实际上是一种误解。他建议单向的瀑布方法只是为了维护项目而存在的。Royce建议在第一次开发软件应用程序的时候一个迭代要“执行两次”。

从这种误解开始,软件开发领域产生了很多荒谬的言论。这篇文章将会质疑和揭穿一些广泛流传的关于迭代开发和迭代测试通常的一些荒谬的言论。包括迭代开发原则是如何解决这些通常的误解的,并会把你带到测试方法的真正道路上,这种方法将会减轻和避免很多软件开发过程中的缺陷,其中有很多是被我们坚信的“谬论”。

谬论:在多数的软件开发项目中,我们带着抛弃这个代码的想法,很快的编写一个原型应用程序,用来降低风险和证明概念的正确性。

事实:这个方法没有任何问题。但是,由于时间的压力或者是结果的奖励,我们并没有抛弃这个代码。事实就是:我们的原型实际上就是早期代码。那个代码就成为了我们新的应用程序的基础和框架。然而,由于它是在假设会被抛弃的情况下建立的,它会迂回于需求评审,设计评审,代码评审和单元测试之间。我们下一代的应用程序是建立在不确定的基础之上的。

在迭代开发周期中,持续的验证是一个好的方法,在每一个迭代开发早期的原型是被鼓励的。但是任何的代码在提交到产品前,都需要遵照最佳实践,来保证它的稳定性和可维护性。一种鼓励在项目最开始做正确软件开发实践的方法是使用初始代码来计划,检验和呈现你打算在软件开发阶段全程使用的过程。作为迭代测试方法的一部分,你可以使用早期代码周期来测试你产品的概念,同时可以清除开发过程中的小故障。

谬论:在开发周期中过早的开始测试活动会增加产品交付的时间,降低产品的特性。

事实:测试在开发周期中不是耗时的活动。诊断并修正错误才是耗时的工作,是开发过程中的瓶颈。

测试不是导致我们产品搁浅的障碍——相反它是避免我们撞上岩石的灯塔。无论我们是否寻找错误,它都存在于产品中。迭代测试会帮助你接近它们产生的地点。迭代测试最小化了纠正错误的花费。

谬论:如果你没有完成的产品那么你就不能做测试。

事实:迭代测试并不被限制必须测试代码。

你的小组生产出来的每一个产品都可以根据可交付性的成功标准进行验证。同样的,你用来生产可交付使用产品的每一个过程或者程序都可以用你的成功的质量标准来确认。这包括产品概念,体系架构,开发框架,设计,方法和你遵循的开发程序。

你可以从这个局部列表中看到,多数的条目没有包括代码。因此,当你在等待有可交付使用代码时,你已经错过了维护质量和降低风险的机会。我不同意这个广泛接受的观念:“你不能对产品进行质量测试”。你可以这么做,只要你开始的足够早。

谬论:如果在每一个开发部分都有一名开发人员(或者一个单独的资源),那么你的工作将会更加有效率。在这个简单的论点中,如果你拥有30名开发人员,那么2人一队进行开发,你可以同时开发15个部分。如果你只给一个部分分配一名开发人员,那么你可以同时开发30个部分。这样会使你的产品完成度更高。

事实:一个部分只用一名开发人员完成有很大的风险:没有第二个人可以维护和理解这个部分的内容。这个策略产生了瓶颈和延迟。缺点,增加的需求或者修改会全部压在这个开发人员身上。为了按时完成工作,你的开发人员不得不为延长的产品周期而付出在周末加班的代价,因为他是这个部分唯一可以继续新特性开发和修正错误的人员。现在你的整个项目时间表都由这个英雄般的“单个开发人员” 1 负责。一旦这个人离开了小组,去度假或者出现一些不可控的情况,那么你的时间表将延期。由于你选择了这种执行和管理的开发策略,你现在不能对你的小组作出调整。

成对的开发,测试,代码评审和设计评审听起来更加有实际效果,它不但能增加产品的质量,还可以训练其他部分的人员,它能够增加你资源共享和维护项目代码的能力。一队中的两个人员不必要都是这个领域的专家。他们只要拥有可以消除先前讨论过的瓶颈问题的能力就可以了。

此外,把开发小组分成合理的更小的独立小组,能够使得拥有不同技术能力的开发人员在不同的方面更加有效的工作。一个小组分配多个人员,就可以避免把不同的任务分配给一个特定的开发人员。当你拥有多个资源可以分配的时侯,把一个任务分配给单个的开发人员会产生错误的依靠性。类似于银行的多个出纳员服务一条等待的客户队伍,当开发人员完成一个任务准备进入下一个任务的时候他们的效率会有所改进。

谬论:编写代码是开发人员的主要任务。

事实:在开发小组中每个人员的主要任务是生产符合客户需要的产品。这就意味着当你做需求评审活动时,开发人员的主要工作就是“需求的评审”。当你做设计活动时,开发人员的主要任务就是建立和评审设计文档。当你做代码活动时,开发人员的主要任务就是产生没有漏洞并且满足客户需求的代码。当你做文档评审活动时,开发人员的主要任务就是确保用户的辅助原料和错误信息能够使得客户的知识曲线变得平缓。当你做安装和设置工作的时候,开发人员的主要工作就是确保客户可以很轻松的设定和配置你的产品,这样他们就可以尽可能高效的完成他们“真正的”工作。越是需要更大的努力来使用软件完成任务,客户的投资回报率就会越低,应用程序失败的机率就会越高。

谬论:软件开发和测试的需求需要很稳定并且尽早的定义好,这样才最有效率。

事实:如果我们最终的目标是“有效率的软件开发和测试”,那么稳定和定义良好的需求在最开始是必须的。但是我们实际的目标是生产一个客户承认的产品。我们大部分人都承认我们往往不知道什么才满足客户需求的。因为在现今的市场情况下,需求是经常变化的,例如新的产品和选择,我们经常要在被介绍新概念和信息之后改变我们的主意。如果你承认上面的情况,那么一个主要的原因就是为什么我们不能有效地保证需求的稳定性。在开发过程中频繁的和产品交互会不断暴露客户的需求,使得我们变更我们的过程来更好的达到客户的变化需求和价值。

谬论:当代码设计的时间超过了时间表的计划,降低测试的时间可以帮助我们重新回到时间表的计划上。

事实:一般情况代码设计的延误是由于未预料到的困难或者没有按照最开始的设计工作。当我们发现我们低估了项目的复杂性的时候,缩短测试时间是一个糟糕的决定。相反,我们应该保证测试的执行,因为测试的结果是建立在我们低估代码设计的情况上的,测试的效果或许也会被低估。因此我们需要定制更多的测试时间来更正开始的判断,而不是减少测试时间。

迭代测试增加了测试时间但是并没有延误整个的时间进度,因为在每一个迭代过程中测试过程都是提前开始的。同样,产品的质量决定了需要测试的数量——而不是由时间决定的。例如,如果产品是可靠的,在很多领域都没有发现缺陷,并且测试进行的十分顺利,那么你可以在保证测试数量和测试覆盖率的前提下降低测试的时间。如果产品不够稳定,发现了很多缺陷,那么你需要增加测试的周期直到达到质量标准。请记住,测试并不是项目最耗时的工作。

谬论:找到并修正所有的缺陷将会建立一个高质量的产品。

事实:近来的研究显示,只有10%软件开发活动,例如建立客户需求特性,能够实际增加客户的价值。开发过程中加入一定比例的特性能够增加产品在市场中的竞争力,但是它们往往不是客户要求或者期望的。查找和修正这些缺陷不会增加客户的价值,因为客户可能永远也不会遇到这类的错误。

从另一个角度讲,迭代测试实际上会减少缺陷的数量和客户等待的时间,当然这是基于客户价值考虑的。在迭代过程中引入客户意见,迭代测试压缩对客户的交付周期,从而最大化应用程序对于这个客户的价值。

谬论:不断的回归测试每一件我们更改的代码是十分冗余和费时的工作,只有在理想化的世界中才会这么做。

事实:回归测试并不意味着“每次测试每件事”。

迭代回归测试的意思是测试每个阶段中敏感的部分。它也意味着基于改动效果,产品历史和早期测试结果而更改我们的测试覆盖率。

如果你的回归测试是自动执行的,那么你可以在同时运行所有测试。如果不是,那么请选择你想要完成测试的部分进行测试。例如,你可以在“验收”产品之前之前运行一个“完整的回归套件”或者“一系列验收测试”f。由于每一个回归过程都不是必须相同的,测试不需要每一次都相同。把精力集中在特性和测试上面对于即将到来的交付阶段是十分有意义的。例如,如果你使用第三方的组件,比如一个承包商或者开源的产品,完整的回归套件将会把焦点集中在外部和内部组件的集合点上。如果在你初始化第三方模块完整回归测试时,发现了缺陷或者回归,那么你可以选择添加基于早期结果的额外测试来改变你的回归套件。

换句话说,如果你在你的控制之下在整个产品开发中进行一系列的缺陷修复工作,那么完整的回归套件应该被完全聚焦并构建在你的端到端,高概括的客户用例上。如果更改被限制在一个领域,并且产品拥有一个稳定的质量追踪记录,那么你可以把精力全部集中在这个回归套件中。同样,在最后阶段,你或许需要一个非常小的能够覆盖介质安装的完整回归套件,但并不是深层次的或者端到端的测试。完整或者验收回归套件的重点依赖于在前一个周期测试了什么,产品的一般稳定性和下一个迭代的重点。

谬论:这不是一个缺陷——特性随着设计而出现。

事实:过多的解释为什么产品会做它现在正在做的事情是一个普遍的陷阱。有时候我们知道的太多了。当缺陷被修复和评审的时候,我们经常为缺陷自圆其说。有时候我们把缺陷标志成为“伴随设计更正”或者“不计划修复”,因为应用程序实际上是伴随着设计工作的,更改设计将是过于昂贵和具有风险的。同样的,我们解释了很多关于“它是一个外部组件”或者“它是一个钟表或者汽笛”的可用性。我们的窗口小部件或者 UI 控件将会受到限制。或者我们告诉我们自己“一旦用户知道要这么做,他们将会很好”。

总而言之:我们了解了代码的输入和输出,以及他们为什么这么工作。在这个部件层次上,我们做了非常合理和明智的决定。但是我们缺少对整个客户经验的整体观。我们没有给我们编码平衡和工作区带来最终效果增值。我们的主要聚焦点是使重要的代码按时完成。通过聚焦于个别的特性或者组件,我们不经意的做了一些代码的决定,这对产品的全面流程和可用性产生了消极的影响。毕竟,最大限度影响客户效率的是可用性。而驱使用户放弃一定数量功能的也是可用性。

超过上面的细节层次提升我们对于项目的见解,会允许我们以客户期待的视角看待我们的产品——通过全局的层面,而不是单个的组件。这种提高后的视角帮助我们忽略了对于产品为什么这么工作的所有原因的探究。客户不会关心给定的设计是否会加快代码的设计。对于客户来说用户界面是否与你特定开发任务外的组件X的API冲突与他们无关。他们只关心这个产品在他们完成自己的目标时是否会协助或者阻碍他们的工作。

表1:举例说明当我们测试应用程序的时候我们以客户视角所提倡的一些做法。
 
 谬论:一个测试人员的唯一任务就是找到程序缺陷。

事实:关于测试人员的作用的这个观点是非常有局限性的,并且对于客户没有增加价值。测试人员都是被测试系统,应用软件或产品的专家。不象负责一个特殊功能或组件的开发人员,测试人员懂得系统作为一个整体是如何工作的来达到客户的目标。测试人员懂得由产品增加的价值,关于产品效率的环境的影响,以及从产品得到最多输出的最好方法。

通过这个产品知识扩展了我们测试人员的价值和作用。扩展测试人员的作用(诸如技巧,技术,指导方针,以及为使用而进行的最佳练习)最终减少了客户所有权的成本和增加了测试人员的商业价值。

谬论:我们没有足够的资源和时间来全面测试产品。

事实:你不需要全面测试产品——你需要充分测试产品来减少一个客户将被消极地影响的风险。

变化市场的事实通常要求在给定的时间框架中详尽地测试一个产品,但事实上是不可能的。这就是我们需要测试的一个实用方法的原因。关注于你的客户的商业过程来确定你的测试优先级。联合系统的内部客户来测试你的产品。当提供真实世界可用性的反馈时,这些步骤增加了你的测试资源。同时你也可以在一个外部客户实验室中来做你的系统测试,来增长你的真实世界环境的经验而不用增加你的维护或系统管理活动。

谬论:测试应当发生在一个被控制的环境中。

事实:测试环境越象最终产品环境,测试越可靠。如果客户环境被严格控制,那么你可以在一个被控制的环境中做你所有的测试。但是如果最终产品环境没有被控制,那么你在一个被控制的环境中做你测试的100%的工作将会使你错过一些重要的情况。

尽管难以预测的事件和不同的环境难以效仿,但它们是十分常见的,因此也是值得期待的。在我们当前的全球市场能够中,你的应用软件将被用于灵活的,分布的,和多变的情况是十分可能的。在迭代测试中,我们因此根据处于不同环境中的客户来同时确定商业使用模型检查和系统测试活动的时间进度。早期的商业使用检查确定目标客户市场的差异性,优先于编码。在客户现场进行系统测试是在真实世界中运用了我们的产品。尽管产品的这些“预发布”版本仍然在我们开发人员的手中,并运行于我们的工作站上,但它们已经在客户真实世界的办公室(或实验室)的环境和应用软件中被测试。尽管这个策略不能覆盖每一个可能性,但它承认不可预知性的存在。

谬论:所有的客户有着同等的重要性。

事实:一些客户要比其他客户更加重要,这是基于一个特殊发布的目标。例如,如果一月发布的发布定义特性是将传统MyWidget数据转变为MyPalmPilot的特性,那么我们的用户使用MyWidget和MyPalmPilot的反应对于这个特殊的发布来说,要比其他客户的输入更加重要。

所有我们的客户当然都是重要的。但是迭代测试的目标是关注于这个特殊迭代法的最重要特性。如果我们正在将特性XYZ输送到这个迭代法中,我们需要来自于熟悉优先的XYZ功能的使用者的专家对XYZ的评价。就象我们欢迎其它反馈一样,诸如新使用者的印象,XYZ特性的优先考虑。在开发的这个阶段,刚刚接触市场的使用者不能帮助我们设计“正确的XYZ特性”。

谬论:如果我们正在寻找很多程序缺陷,我们正在做重要的测试。

事实:找到很多程序缺陷的唯一好处就是告诉我们产品存在很多程序缺陷。它没有告诉我们测试覆盖的质量,程序缺陷的严重性,或是客户将在实际中碰到它们的频率。同样它也没有告诉我们遗留下多少程序缺陷。

停止找到程序缺陷的唯一确定方法就是停止测试。它看起来是荒谬的,但这个想法是有价值的。这个难题的症结在于指出产品的什么特性确实需要研究。我已经提到产品中的许多工作流实际没有被使用——并且如果它们没有被使用,它们就不需要被研究。直接在你的测试计划中合并客户使用知识以及缺点筛余机制提高了你预测客户影响和与缺点相关的风险概率。在你的测试计划解决中合并基于风险和客户分析将产生一个更加实际和实用的测试计划。一旦你对你的测试计划有信心,你可以在你已经执行计划之后停止测试。

你如何建立那种信心?开始你的测试计划时要确定你需要测试的所有区域。让客户检查和评价商业过程并使用实例以便你懂得每一个被提议的测试实例的频率和重要性。要特别注意检查测试漏洞。对每一个迭代要持续更新和检查你的测试计划和测试实例。你的目标是找到什么没有被覆盖到。做到这个的一种方法是通过软件区域和测试种类来映射程序缺陷计数。如果一个软件区域没有被记录缺点,它可能意味着这个区域是十分有效的或者它还没有被测试。看缺陷文件的时间戳。如果最后的缺陷是去年公布的,可能它暂时不用被测试。找到错过的程序错误的模式是检查测试覆盖的一个重要技术。

谬论:完全的测试意味着测试 100% 的需求。

事实:测试需求是重要的,但是不是充分的。你还需要测试那些遗漏的事情。有什么重要需求的没有被列出?

找到没有被列出的是一个有趣的挑战。 迭代测试很早就使客户客户参与进来。客户懂得他们的业务如何进行和他们如何工作。他们可以告诉你你的应用软件中错过了什么,并且提出什么妨碍了他们需要完成的任务。

谬论:它是一个间歇的程序错误。

事实:不存在间歇的程序错误。问题是一直存在的——你只是没有指出正确的条件来复制它。提供可用的工具来持续监控执行,应用软件降级开始的自动校准,以及在降级的时候自动发出适当的数据(优先于应用软件实际崩溃)减少内部故障诊断时间和客户停工时间。迭代测试和迭代可用性活动都可以减少没有被发现的程序错误对商业的影响。

更加实用和好用的诊断程序增加了你的产品的客户价值。当你的产品开始升级时,通过前摄的监控环境,你可以减少分析时间甚至可以避免由于开始各种自动更正校准和工作区的例行程序而导致的停工。自治服务例行程序的这些类型增加了你的产品的可靠性,耐久性,和运行持续时间,甚至如果程序缺陷复制品的条件是未知的。

在某种意义上,自治的恢复例行程序提供了一个标准的持续的技术支持。环境记录和处理跟踪信息被自动收集并被发送,以用于更进一步缺点分析的开发,同时也提供了关于你的产品是如何被实际使用的重要数据。

如果我们承认程序缺陷是不可避免的,我们同样需要认识到适当有用的例行程序的重要性。这些自诊断和自行监控功能在增加客户价值和满意度中是有效的,因为它们减少了客户受程序缺陷消极影响的风险。然而即使这些例行程序增加了客户价值,只有少数几个开发周期被用于将这些过程归位。

谬论:产品应当在压力下被测试以验证性能、可伸缩性和耐久性。

事实:上面是正确的。但它的反面也是正确的。使一个应用软件保持在空闲,或长期处于暂停的状态来仿效客户去吃午饭或使应用软件在周末暂停,并经常暴露一些问题。

我推荐在你的功能测试方法中包括睡觉,暂停,中止,中断和睡眠状态恢复。仿效一个地理分布式工作环境,当你的应用软件处于中止或暂停状态,而其中的共享工件和数据库正在变化(正如同事们在其他人的业余时间在一个偏僻的地点工作)。测试当使用者“唤醒它”时发生了什么,这与他们被挂起的环境是不同的。然而更好的是将你的产品放到一个真实的客户环境中并运行仿效上面的一些场景的系统测试。

谬论:客户总是正确的。

事实:可能他不是一个正确的客户。你不可能使用一个发布来使每一个人都满意。因此,要在你的发布定义特性设置中有选择性。瞄准一个特殊的,高度概括的测试场作为用户的一种类型目标。然后对于下一个发布或迭代,选择一个不同的人群。你将更有效地测试;当你的产品成熟的时候,你将通过在不同阶段中增加满意的客户来增加你的客户基础。

谬论:自动化!自动化!自动化!

事实:在脑海中客观的看待自动化,并考虑 ROI。测试环境越象最终产品环境,测试的可靠性越高。如果客户的产品是100%自动化的,那么自动化!自动化!自动化!如果你的产品不打算在客户环境中实现自动化,那么你需要将自动化的,特殊化的,探查的以及客户场景的测试进行合并。

它同时对于扩展你的自动化定义有所帮助。自动化测试实例可以重复测试你已经手工测试过的区域。但是那不能增加你的测试覆盖或你对使用者对于应用软件是如何反应的理解。相反,创建自动化实际上允许你投入更多的精力在创造性的手工测试上。使事情自动化是你经常需要做的并且那将使你花费很长的时间来完成,象:

  • 分解和建立原始环境来测试每一个构建。
  • 对每一个构建,集成点,或迭代的全面验收测试。
  • 跨越各种平台,操作系统和语言测试相同的套件,。
  • 低级别组件的单元和命令行测试。
 为了得到更多关于增加你的对自动化投资回报的信息,访问http://www-128.ibm.com/developerworks/rational/library/may05/rose/。

谬论:迭代开发行不通。

事实:它是人类对于未知和未尝试的领域怀疑的天然属性。在迭代开发经验中,每一个成功阶段的好处逐渐增加。因此,迭代方法的所有好处是只有在开发周期的末尾才被重视。对于第一个吃螃蟹的人来说,那个推迟的满意可以真正地成为信念的行为。我们没有使用方法的经验,并且所以我们不太信任即将使用的方法。当我们认识到时间正在流逝,我们放弃了信念并抛弃了迭代过程。在恐慌状态中,我们又回到了我们的老习惯。迭代开发多半没有实际失败。我们只是没有给它一个成功的机会。

迭代测试在迭代开发的累积好处的每一个迭代中提供了可见的记号。当团队共享增加的成功标准(例如,每一个迭代的进入和退出标准)时,站在正确的方向上是更加容易的。

因为我们根据出口标准持续监控结果,我们可以更容易地在迭代中调整我们的测试来达到我们的最终目标。例如,在中间迭代中,我们可以观察我们关键的和高缺陷计数在增长,并且我们可以比修正它们更快地找到它们。因为我们早已经认识到这个趋势,我们可以重新分配资源来加深对于关键路径活动的关注。我们可以再分配研究“乐意拥有” 特性的开发人员来修正“发布定义” 特性中的缺陷,或者删除与高缺陷计数有关的乐意拥有特性。

结论

我只接触到了我们假设每天都会遇到的软件开发的谬论中的少数一部分。如果我们假设做得越多,我们就会越少发现不可预知的事情——所有关于软件测试的。

不幸的是,我们提到的谬论是非常诱人的。它们被伪装成答案,并且它们方便地结束了对话。当我们人员不足并承受压力时,接受假设作为事实是非常诱人的。

因为我们经常难以分辨谬论和事实,我们需要检查我们的答案。这个简单而有效的颂歌,总结了我已经在这篇文章中论述的所有东西,将有助于你保持在正确的轨道上:迭代测试从来都没有满意的正确答案。

 注解

1 在能力成熟度模型 (CMM,或CMMI)中,通过依靠少数几个个人英雄主义的劳动典型的是成熟度 1 级的水平,也就是众所周知的混乱级别。

 

版权所有:UML软件工程组织