软件测试和验证是细致活也是辛苦活,需要模仿最终用户尝试各种用法和输入场景、比较并断言所期望的行为。而这些细致的辛苦活是可以让计算机程序去做的。自动化测试套件中那些可编程部分对于大规模软件交付是非常有帮助的。在我做过的大部分项目里,有些测试是可以自动化的,也有些不能。不过,只要有自动化测试套件,我的团队都将倚重于它,而将精力集中在那些没有自动化的功能测试。而且,自动化测试还让我们能够满足客户快速变化的需求,并使我们达到了一个更高的层次,使得每次构建(即使只是微小变动)都是经过测试和验证的稳定版本。正如 Jez 有关持续交付的文章中所言,自动测试“让交付团队超越了基本的持续集成”并走上持续交付的康庄大道。实际上,我觉得自动化测试是非常重要的,如果你要实践持续交付,就必须在自动化测试上进行投入。本文解释了之所以我这么认为的原因。
时间周期 - 从最后一次代码提交到发布
当软件复杂度不断增长时,验证其变化部分和已构建部分的工作量都会随之增加,这种增长至少是线性的。这就意味着测试时间与需要验证正确性的测试用例数量是成比例的。因此,增加新特性即意味着从开发完成到交付软件的时间会拉长,如果投入更多测试人员来应对增加的工作量(假设所有测试任务是相互独立的),那么交付成本也会增加。很多团队通过保留一个测试人员池来应对这一问题,这票人马在整个发布版本验证期间都在做“回归”测试,以检查新变化是否破坏了已有功能,我待过的一些团队也是这么干的。但是这么做不仅成本高昂,而且效率低下、进展缓慢且容易出错。
在自动化测试场景下,你可以减少花在验证用户功能工作上的时间和金钱。我们不妨假设你的测试场景中有合理数量的测试用例是可以自动化的,比如 50%,这通常是软件项目可自动化测试用例的下限。如果你的团队能够自动化该数量的测试用例,那么人们就可以将把更多注意力集中于那些新近变化的特性上。假设跑一遍这些自动化测试需要 3 小时(时间越短越好,甚至少于 20 分钟),这一时间将直接影响将产品推出的时间。增加自动化测试的数量,并尽量减少测试运行的时间,那么你快速响应的能力将显著提升,同时成本得到缩减。下面我用一些简化数字(平均用例数)加以说明:
团队 A
- 需测试场景数量 - 1000 且在增加中。
- 建立构建环境所需的时间 - 10 分钟。
- 测试一个场景所需的时间 - 10 分钟。
- 团队中的测试人员数量 - 5。
- 假定不存在 blocker(阻塞)。
如果没有自动化测试,测试单次提交的时间总量为(以分钟计):
10 + (1000*10)/5 = 2010 分钟。
接近于 4 个工作日(每工作日 8 小时)。如此不仅成本高昂,而且开发人员在 4 天后才能得到反馈。这种设置日后还有可能在你的迭代中形成迷你瀑布。
团队 B
与团队 A 的情况相同,但是测试套件中有 50% 的测试用例自动化了。假设运行完这 500 个自动化测试用例需要 3 小时时间。
现在,测试单次提交所需的时间总量为(以分钟计):
任务 1(手工) - 10 + (500*10)/5 = 1010 分钟。
任务 2(自动) - 10 + 180 分钟。
接近 2 工作日。这虽不十分理想,但足以证明减少了成本,我们可以测试完一天之前的构建。测试开销减少了一半,我们还在 3 小时内完成了 50% 的测试用例。
接下来是更加理想且是可以达到的状况。
团队 C
与团队 B 的情况相同,但是我们把测试放在更好的机器上运行,这样速度更快(比方说 20 分钟),而且 80% 的测试都自动化了(10% 不能自动化,另 10% 是新功能)。
现在再来看,测试单次提交的时间总量为(以分钟计):
任务 1(手动) - 10 + (200*10)/5 = 410 分钟。
任务 2(自动) - 10 + 20 minutes = 30 分钟。
结果,我们在 30 分钟内就覆盖了 80% 的测试,大约 7 小时即可结束整个测试。更值一提的是,在 30 分钟内跑完 80% 的测试,可以让我们尽早发现 blocker,以便暂缓进一步手工测试。这样的话测试成本低、反馈快,在很大程度上改变了测试的过程,不是吗?
每次发布的测试成本
自动化不仅缩短了周期,还大大缩减了每次发布的成本。成本减少源自两个方面:
- 通过自动化测试尽早给开发人员反馈,提升了所测构建的质量,让他们得以收获“绿色”构建。
- 测试成本直接减少,因为反复运行相同测试的人员减少了。
测试成本直接减少比较容易解释清楚。以上面我们所提到的团队为例,下列图表显示了在运行所有测试时各个团队所花费的成本;这里假定每位测试人员每小时需花费 50 美元。
如你所见,对某一发布的候选构建做一次全面测试,团队 A 的花销(10 万美元之多)几乎是团队 C 的 5 倍。
如果周期更长的话,比如说 2 年,那节约下来的成本就相当可观了。如果目标是一天之内能够跑完一遍发布构建测试的话(这一目标不算过分),那么团队 C 已经达标。团队 A 需要 25 个测试人员才能达到该目标,而团队 B 则需要 15 人。下面,我还要增加进硬件和编写程序的成本,来说明自动化测试对于一个超过 2 年的发布周期的有何意义:
- 硬件成本 - 机器及其他共 5 万美元
- 编写程序成本 - 再投入 2 个开发人员,最初 2 个月编写自动化测试程序,剩余时间维护测试套件,那么团队 B 和团队 C 的人数现在是 7 个。
针对这一数字,为了达到每天测试一遍构建这一目标,在 2 年时间里团队 A 的成本有四百八十万美元之巨。相比之下,团队 C 的成本接近一百四十万美元,成本减少了 70%。从下面的图表可以更直观地看到这一点:
(单击放大)
除了在缩短周期和减少成本上发挥作用外,自动化测试还创造了很多间接价值,包括:
验证及时
如果要再 2 小时内完成一个构建的验证,前面提到的团队 A 需要 50 名测试人员,但客户不会对这块成本感兴趣。如果没有自动化测试,大多数情况下,一天之内完成验证到交付几乎是不可能的。之所以这么说,是因为这种情况下成本极其高昂。因此,如果我的团队没有自动化测试,也没有无限资金的话,即便开发人员只提交一行代码,我们完整验证一个构建的时间也会成小时甚至成天的增加。这样的话,管理人员对每次构建都完整运行测试的积极性就会下降,最终导致构建测试覆盖面下降,对系统中 bug 的测试时间减少。另外,我还遇到过因此而减少代码提交频率的情况,这样并不健康。
反馈频繁、快速
自动化最重要的一个方面是团队从构建过程中可以得到快速反馈。每次提交都进行了无预判测试,团队很快就能得到测试报告。反馈越快则意味着建立在有错代码之上的代码越少,进而提高了软件可靠性。仍以上面的团队 A、B、C 为例:
- 对于团队 A - 第一天发现 blocker 的概率是 1/2,这就意味着测试第二天找到 bug 的风险比较高,这样的话第一天的工作就全浪费了,因为这个 blocker 修正之后所有测试都需要重新验证一遍。最坏的情况是这个 bug 在代码提交两天之后才发现。
- 对于团队 B - 最坏的情况是在这一天最后几个小时才发现 blocker。这也比团队 A 的情况好得多。而且,由于 50% 的测试用例是自动化测试,在 3 小时之内发现 blocker 的几率非常高(50%)。这种快速反馈可以让你更快发现并修正 bug,因此响应客户需求的速度也非常快。
- 对团队 C - 这三个团队中情况最好的。最坏场景是团队 C 在 3 小时之后才知道他们是否提交了 blocker。因为 80% 的测试用例都进行了自动化,20 分钟他们就能知道是否有错误。从团队 A 到团队 C 有很长一段路要走,但 20 分钟比 2 天要好得多。
机会成本
经济学家使用一个贴切的术语 - 机会成本来定义在多种选项中选择其一时将会失去的东西。 对一个又一个构建反复验证那些乏味的测试用例,其机会成本是:失去了花在探索性测试上的时间。机会成本通常不在于一个bug 导致多个bug 的情况,而在于对手工测试投入过多精力,这样的话测试人员很难找到时间来创建新的测试场景并跟进问题。不仅如此,由于所有时间都集中在回归测试上,测试人员在新功能上投入时间不足,然而从这些新特性中找到bug 的概率却是比较高的。通过尽量自动化测试用例,可以释放测试人员的大部分精力,让他们做更具创造性的任务,并从“人的角度”去探索应用程序,以增加测试覆盖深度和质量。在我做过的项目中,只要有自动化测试辅助手工测试,测试得都比较深入,因而质量也比较高。
手工测试还包括乏味地、日复一日重复验证相同测试用例的工作,这是手工测试的另一个缺点。即便每天把测试分配给不同的人也是有创造性的活动,过一段时间之后,每轮测试也只是重复而已。测试人员鲜有时间去做创造性工作,因此他们对工作也缺乏满足感。测试人员是有创造性的人,他们的长项是以最终用户的角度去使用软件并找到新的方法来测试并发现应用程序的问题,而不是不断的重复一套过程。如果没有自动化测试,留住最好的测试人员并让他们满意的机会成本是非常巨大的。
减少人为出错
不管你信不信,最优秀的人同样也会在日常工作中犯错。工作做得好,犯错的机会就少一些,但是出错的机率还是大于0。在检验构建质量过程中,对人为出错的风险了然于胸是非常重要的。实际上,软件应用大部分bug 背后都隐藏着人为错误。相反,计算机做这些重复性任务效率极高 - 它们既勤奋又细心,通过自动化测试可以减少人为错误风险。
测试是可执行的文档
测试场景是应用程序状态一个极佳的知识来源。如果想了解应用程序能为最终用户做些什么,手工测试结果可以提供一个很好视图,并且告知开发团队其代码中哪些部分比较“古怪”。所记录的测试结果由两个部分组成 - 展示应用软件能做什;记录什么会出错,怎么出得错。有了这些信息,就很容易管理应用程序的异常举动。如果测试人员很勤奋,可以保证文档总是最新的(另一项开销),可能看一下测试结果就会知道软件的状态。但随着错误量的增大,工作量会大幅增加,作为测试人员需要记录操作步骤,抓取屏幕快照甚至是崩溃情况下的视频。如果在这些事情上花时间多了反而会增加变更的成本,实际上由于成本太高,人们不太愿意在每次发布时都记录状态。
有了自动化测试,通过选择正确的工具,记录应用程序状态的成本明显降低了。自动化测试工具提供了很好的方式来执行测试、按类别收集结果并把结果发布在Web 页面上,让你能够直观看到测试结果数据以监视测试进度并从测试结果数据中获取相关反馈。使用类似Twist,Concordian,Cucumber 等工具的话,给用户展示测试结果甚至让他们来编写测试都变得相当容易;这样既减少了信息传递过程中的损失,也让用户能更深地介入到应用开发过程中。对于测试失败的结果,多数测试工具都自动化了抓取屏幕快照及视频的过程,以更有意义的方式记录失败和错误。测试结果可以邮件方式发送给测试人员,还有更好的:每次构建都以RSS feed 的形式提供给感兴趣的人。
技术层面测试(Technology facing tests)
测试应用程序的非功能特性——比如响应用户动作的性能,测试网络延迟及其对最终用户与应用程序交互的影响等等,传统上都是部分自动化(尽管我早期曾经干过用秒表来手工测试性能的活,低保真但有效)。我们可以很容易利用自动化测试并重用它们来做非功能性测试。例如,多次重复运行一个自动化测试可以告诉你Web 页面上某个动作的平均性能 。该模型很容易建立,将功能性自动化测试的次数输入所选的框架内,那么在测试运行过程中你就可以建立并探测非功能性属性。要测试并监视例如基于较色的安全、延迟的影响、查询性能等,都可以通过重用已有的自动化测试来自动化,这是自动化测试额外的好处。
小结
在持续交付的过程中,不论大小,你都必须采取诸多步骤。其中最难逾越的障碍是在减少测试周期同时保持较低成本。自动化测试能帮你做到这些,同时让你建立起更加高效、快乐的团队,他们是在开发过程中进行测试。我的理解及建议是:从小处着手,充分投入以建立一套健壮的自动化测试套件,给它配备最优秀的人,培养团队尊重测试及结果的习惯,先建立起一个主干,然后逐步细化,平稳过渡。
关于作者
Ranjan D Sakalley 工作于 ThoughtWorks 工作室,首席顾问。曾在之前的公司及 ThoughtWorks 就职为开发人员,项目经理及敏捷教练。他热心于自动化测试,持续交付,编写好的代码及与人合作。他的爱好是阅读喜剧书籍,观看曼联队赛事。你可以 follow 他的 twitter rnjn 或他的博客
查看英文原文: Test automation and Continuous Delivery
给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家加入到 InfoQ 中文站用户讨论组中与我们的编辑和其他读者朋友交流。
评论