自动化测试最佳实践 连载三

第1章 敏捷团队的自动化测试之旅:第一年

  Lisa Crispin

  浏览“如何阅读本书”和“案例研究反思”,了解本书章节安排。

  Lisa Crispin以其特有的迷人方式描述了当一个敏捷团队决定实施自动化测试时所发生的事情。由于Lisa在敏捷技术方面的专业能力,当看到这支团队在实践中确实非常敏捷时,我们一点儿也没有感到惊讶。这个项目中一件有趣的事情就是:团队(小型团队)里面的每个人都参与了自动化。他们不仅擅长敏捷开发,而且非常敏捷地对其进行了自动化——并且他们成功了。实施敏捷开发并不是这支团队取得成功的唯一要素,其他要素也同等重要,其中包括通过良好的沟通建立稳固的管理关系,以及建立自动化平台来支持创造性的手动测试。另一个关键要素是在团队将过程改进嵌入到整个流程的决策力,包括一年两次的自动化重构的安排。毫无疑问,Lisa和她的团队在他们第一年的时间里所取得的成就是非常显著的。这个项目是为一家美国公司的财务部完成的,特征见表1-1。

  表1-1 案例研究特征

  (续)

  1.1 本案例研究的背景

  我们必须面对这样的事实:对于从未进行过自动化测试的人来说,自动化测试是具有一定难度的。本故事告诉我们,面对无任何自动化的测试和有着糟糕设计的遗留系统,这支团队通过一年多的努力,将所有的回归测试都实现了自动化。在接下来的几年时间里,我也与数十个其他面临同样困境并找到类似解决方案的团队进行了交谈。看看我们所遇到的这些困难是否与你所遇到的相似,并考虑用类似的方法进行尝试。

  1.1.1 问题

  从这里开始着手:每两周我们都需要把新的功能添加到产品中,但是代码bug成灾并且也没有自动化测试,更严重的是,产品中有大量随时会导致系统中断的bug。我们如何摆脱这种情况呢?

1.1.2 目标

  我们决心尽自己所能编写出最高质量的代码,但是从哪里开始呢?作为一支自组织的敏捷开发团队,让我们感到欣慰的是整个团队的紧密协作。那是在2003年,我们中有些人在别的团队中曾有过良好的自动化测试经验,他们相信总是会有办法的。我们发现,一个安全的自动化回归测试网络可以让我们更快速地工作。如果我们知道是由于某段特殊的代码而引入的非预期的操作,那么我们能够立即稳定我们的代码库。通过充分的测试覆盖来不断进行集成,使我们每天都有一个稳定的构建过程。而在迭代的后期,现在很难得到稳定的集成,所以这个想法虽然并非那么容易实现,但听起来很不错!

  接下来,看看到底是什么帮助我们创建了一个成功的策略来实现自动化回归测试套件。

  1.2 整个团队的承诺

  我们是由多个程序员、一个测试人员、一个数据库管理人员、一个系统管理人员和一个敏捷教练所组成的团队。公司的业务专家可以随时协助我们。我们整个团队致力于在每次发布之前运行我们的手动回归测试脚本。因为我们每两周发布一次,这意味着两周的迭代周期中我们要花1 ~ 2天的时间进行手动测试。在最终用户使用之前,我们没有足够的时间来进行探索性测试,虽然这种测试可能会帮助我们找到严重的缺陷。

  【真知灼见】

  敏捷开发团队中的每个人都进行手动测试,所以他们更能体会到自动化测试的好处。

  我们都很关心质量,并且我们都致力于保证所有的测试活动都是有计划的且在每一次迭代中执行。这是一个好的开始!

  1.3 建立自动化策略

  我们需要在不破坏现有功能的前提下发布产品的新功能特性。而且,需要尽快知道一个新的代码变动是否会引起回归测试的失败。手动回归测试在每两周的迭代后期才能给予我们反馈,以至于没有时间进行充分的回归测试。

  我们中一些人曾经在其他敏捷团队中进行过测试驱动开发(Test-Driven Development, TDD)。我们发现TDD能帮助创建出设计良好的、健壮的代码。

  我们现有的回归测试是手动操作的,整个团队通过使用团队Wiki上所记录的脚本进行手动测试。在每两周的迭代周期中,这就花费了整个团队的20%的时间。这些测试仅仅为程序最核心的部分提供了最小程度的覆盖。产品中报告的缺陷表明,回归测试的失败仍有可能发生。在每次迭代周期中,我们至少要花20%的时间修复这些产品缺陷,从而限制了我们能开发的新功能的数量。

  自动化的回归测试会带来更高、更准确的覆盖率,这需要投入大量的时间、金钱和精力,我们可能需要硬件和软件来建立构建过程、持续运行测试所需要的环境,我们也需要使测试实现自动化的架构和驱动。然而,我们可以计算出这一自动化将会节省我们40%的时间,利用这些时间可以进行更多有价值的活动,比如进行新的开发,所以,其收益远大于成本。

  继续进行手动回归测试必将会失败,我们需要一个明确的决策来进行自动化。因为我们都在进行手动回归测试,每个人都感受到了没有自动化测试的痛苦。所以,我们有了解决这一问题的动力。首先,我们需要一个可测试的架构……

  1.3.1 一个可测试的架构

  TDD这条路是要走的,但是当前的代码在业务逻辑、数据库访问和UI等处相结合时,情况比较复杂,自动化单元测试也就变得很难了。往往很难隔离任何一个组件单独进行测试。

  这样看来,似乎找到一种把软件进行分层的新架构是非常明智的。我们开发出了这一新架构的所有新功能。

  【小窍门】

  不要尝试解决老问题,进行新的开发来开展更好的实践。

  如果进行自动化测试的成本比其收益高,那么进行自动化测试就没什么意义。我们研究图1-1所示的自动化测试金字塔(这一金字塔是由我们当时的经理Mike Cohn提出的)。单元级别的测试一般ROI最高。程序员可以很快写出它们并运行,而且测试可以根据需要进行更新。因此可以将单元级别的测试作为自动化回归测试的坚实基础。

 我们的业务逻辑相当复杂,而且新架构将这一逻辑从数据库和用户接口层中分离出来,这样就可以通过设置内存中数据并在其上运行产品代码来进行测试。这是金字塔的中间层———比底层运行的测试要少但是依然很重要。

  我们还需要测试UI,但是通过UI进行的自动化测试本身就非常脆弱、维护费用高且运行缓慢。因为最终想使UI测试所占的比例尽量最小,所以它就处在金字塔的最顶端。尽管如此,与其他团队一样,我们从图形用户界面(GUI)冒烟测试(smoke test)开始,来获取一些代码防护。所以,从这个角度,我们的金字塔是上下颠倒的,但是没关系———最终我们会将它翻转过来。(我们最终花了4年时间才获得为之努力的三角形形状!)

图1-1 自动化测试金字塔

  【小窍门】

  解决问题的最直接途径未必是最佳途径。

  我们现在明白了我们需要做什么,所以我们开始着手实施那个能给我们带来最大实惠的任务。

  1.3.2 建立构建过程

  我们只有4位程序员,但是他们会经常检查源代码控制系统中的变化。我们需要确保他们没有不小心修改别人的内容或者破坏现有的任何功能。同时,我(测试人员)有时候不得不等待好几天,部署在测试环境中的代码才能完成一次构建。一个自动化的构建过程(build process)将保证在每次检入后的几分钟内,最新代码的可部署版本就是可用的。

  管理层向我们强调了质量是我们的第一目标,他们乐意宽限一些时间来让我们搭建一个好的基础结构。

  【真知灼见】

  好的管理者会准许团队花时间去开发自动化的基础结构。

  我们停下正在做的事情,使用CruiseControl和一个新的Linux服务器建立了一个持续集成(Continuous Integration, CI)过程。因为我们还没有可以运行的任何测试实例,所以只是简单编译代码和构建可部署的二进制文件。我可以看到每次构建的检入文件并能够选择想部署到产品中的二进制文件。这很有用,但是还不够。

  1.3.3 获取测试的基准:GUI冒烟测试

  程序员正在学习如何使单元测试自动化并编写测试先行(test-first)的代码,但是要真正实施测试驱动开发需要花好几个月的时间。针对遗留代码,使用GUI冒烟测试可能是一个快速获得自动化测试覆盖的途径。但是使用什么工具最好呢?

  我们有购买一个付费工具的预算资金,但是团队里的程序员是Java程序员,他们万不得已是不愿意使用另一种脚本语言来进行测试的。捕获/回放并不适合我们,因为我们需要可维护的、稳定的测试脚本。我们选中了 Cannoo WebTest——一个可以让我们修改XML文件中的测试用例,并使用Ant运行它们的开源框架。而且它很容易与我们的构建过程集成。

【真知灼见】

  昂贵的商业工具不一定是最好的选择。

  我让业务专家把需要用冒烟测试来保护的系统核心区域按优先等级进行划分。每个冲刺时间段里,都安排了时间让我用WebTest工具自动运行测试脚本。我们首先追求的是“快赢”,针对系统中每个用户角色的基本功能实现自动测试。

  首先, CI构建过程只运行了少量单元测试和一些覆盖系统高得分点的GUI冒烟测试。随着在这两个级别引入更多测试,我们将GUI测试移到单独的构建过程中并只在晚上运行,这样,我们可以更快得到的反馈信息。

  与此同时,我们将单元测试和每个新用户故事(user story)的GUI冒烟测试都放在迭代中完成。新的功能将会在自动化的单元测试和GUI测试中被覆盖。一旦程序员能够熟练使用TDD,我们就将进入金字塔的中间层。

  1.3.4 在单元级别驱动开发

  我们的程序员中只有一人曾经实施过TDD,但每个人都支持这种理念。我们根据别人的介绍,找到了我们能找到的最好的顾问来帮助我们学习如何实施TDD,很多时候我们都是自带午餐以便挤出时间来进行TDD试验。但是很遗憾的是:它很难学!我们团队需要时间来掌握它。

  我们的管理层知道这个道理:目标是写出优美的代码,优美到可以拿回家给妈妈,当做冰箱贴。我们的公司——一个刚刚成立3年的商业公司,因为网络应用问题和无能力及时发布新功能而面临倒闭。我们的商业合作伙伴也准备放弃我们了,但自从我们实施敏捷开发(Scrum)以后,他们看到了我们为提高稳定性和响应能力所做的努力。我们的执行者致力于具有长远收益的投资。

  【经验教训】

  一个迫在眉睫的灾难可能是巨大进步的推动力。

  我们知道这些单元级别的测试具有最好ROI。我们也理解TDD事实上是代码设计,而不是测试。考虑“代码是用来做什么的”可以帮助程序员写出正确的代码,而快速实施测试,才能及时地提供重要的反馈信息。

  单元级别测试的最大好处就是能够提供最快速的反馈。在研究一些好的实践之后,我们决定将代码构建过程的时间控制在10分钟内。这需要单元测试的随机重构。早些时候,单元测试需要访问数据库,之后,程序员掌握了如何构造、模拟它,以及消除它的影响,使测试快速运行又能提供正确的测试覆盖。

  1.4 利用验收测试驱动开发,使用FitNesse测试GUI

  现在已经是我们自动化之旅的第8个月了,程序员已经建立了一个自动化单元测试的实用库。对于应用程序的核心区域我们已经进行了冒烟测试,覆盖微量代码的大约100个JUnit测试已经完成了。但是中间层还什么都没有,TDD此时变成了一个空壳。现在我们开始对自动化测试金字塔的中间层进行填充。

  1.4.1 内存内测试

  我们的金融理财产品有许多复杂的算法,这可以通过在内存中提供输入来进行测试。与单元测试相比,这种测试的级别要高很多,但我们还是不想通过GUI来进行测试,因为其速度慢、成本高。我们发现可以很迅速、方便地编写FitNesse夹具(fixture)来自动进行这类测试。在客户测试层次,我们开始用FitNesse测试来驱动新的用户故事的开发。这些测试使用夹具在内存中构建测试输入,并把这些输入发送到应用层代码,就如同产品在实际使用时进行的输入一样。然后夹具会返回代码的实际输出,并把它与FitNesse表中的期望结果进行对比。

  测试人员和客户填写FitNesse测试用例,之后程序员用夹具来自动运行它们。这意味着我们需要交流!提高团队的交流能力是使用这种工具进行自动化测试的最大好处之一。我们测试人员与产品所有者和其他利益相关者坐在一起分析每个用户故事预期的和非预期的行为。我们将这些用户故事转化为FitNesse测试用例表,并与客户核对以保证当测试用例通过测试的时候能够满足客户的要求。我们与开发人员核对测试,以保证我们清楚需求并保证测试设计与代码设计兼容。开发人员编写夹具来自动运行测试。这一过程在单个用户故事的很多小的迭代中不断重复,直到开发和测试都完成。 1.4.2 使用数据库的测试

  我们的应用是数据密集型应用,我们想自动运行更加端到端(end-to-end)的测试。我们也可以使用FitNesse在数据库中构建测试数据,并使用遗留代码在它上面运行,以此来测试遗留代码。

  这种类型的测试脚本编写和维护都更加昂贵。作为FitNesse的初学者,我们犯了一些错误,如,不知道将测试组件模块化,而这可以通过FitNesse中现有的部件来完成。我们彻底违反了代码设计中的“不要重复自我”准则。例如,在几十个不同的测试页面中,有包含同样员工信息的表,如果又有一列新数据需要添加到员工信息表中,那么在每个测试页面中都要加进去,这很糟糕。等到我们知道如何正确去做的时候,又遇到了一个更难以处理的麻烦。

  【经验教训】

  在前期进行工具使用的培训,之后就可以避免因工具使用不熟练而造成的巨大的时间浪费。

  我们将每个能想到的测试用例都进行了自动化,包括发生几率低、影响小的边缘测试用例,并把它们都放在自动回归测试套件(test suite)里面。上述过程花费的时间并不长,但是接下来,这个测试套件要花费大量时间和主机功率(machine power)来运行,维护成本也随之提高了。所以,我们要学会慎重选择测试用例,确保它们能提供充分的测试覆盖,并只将这些测试用例放在回归测试套件中。

  【小窍门】

  精化回归测试套件可以在保证收益的同时降低维护费用。

  正如在产品应用代码中所做的那样,我们现在不断地重复访问和重构FitNesse测试用例,以保证我们所需要的测试覆盖,同时不会过多地延长反馈周期或者花费太多时间维护测试。

  【真知灼见】

  经常检查自动化测试用例以保证它们是有效的。

  1.4.3 使用FitNesse测试的好处

  我们的FitNesse测试提供了比GUI测试套件更快的反馈,尽管比JUnit测试要慢很多。FitNesse测试套件需要60 ~ 90分钟来运行,而JUnit测试的运行时间仅仅只需要不到8分钟。像GUI测试脚本那样,我们将FitNesse测试集成到构建过程中,并且在其中运行。一开始,我们只在晚上运行这种“完全构建”(full build),但这无法提供及时的反馈,并且如果测试失败的话,我们只有在第二个晚上才能知道问题是否修复了。我们投入了更多的硬件,这样我们就可以“连续地”运行单元级别上的所有测试的完全构建。如同运行单元级别测试的构建一样,这是为了使源代码控制每接收到一次检入就能运行。大概需要90分钟运行一次,所以经常同时测试几个新的检入。

  (未完待续...)

最新内容请见作者的GitHub页:http://qaseven.github.io/

时间: 2024-11-08 19:23:56

自动化测试最佳实践 连载三的相关文章

自动化测试最佳实践 连载一

<自动化测试最佳实践:来自全球的经典自动化测试案例解析>第0章案例研究反思,本章高度总结了现有经验中需要吸取的最重要的教训.本节为大家介绍自动化测试目标. 第0章 案例研究反思 成功的自动化测试需要智慧和毅力.你的经验可能和本书所描述的有一些相似之处,但每个人的故事都是独一无二的.通向成功的道路并不简单,但是正如书中案例研究所描述的那样,自动化测试已经在各种应用领域.各种环境和项目的各个生命周期中取得了成功. 通过思考,我们根据书中出现的案例和奇闻轶事总结出了一些方法.本章高度总结了现有经验中

自动化测试最佳实践 连载二

0.2 技术因素 在我们看来,最重要的技术因素是测试件架构以及多个层次上的抽象.测试件(testware)是所有创建的用于测试的事物,包括脚本.数据.文档.文件.环境信息等.测试件架构就是这些事物是如何组织的,以及它们彼此之间是如何依赖的--例如,高层次的脚本使用了低层次的脚本用来与被测软件进行交互. 0.2.1 抽象.抽象.再抽象:测试件架构 在最初得到了一个测试执行工具后,通常会期望测试人员开始使用这个工具.当这名测试人员不是开发人员时会发生什么?现在突然需要他们成为程序员,去学习工具的脚本

自动化测试最佳实践 连载四

1.5 使用增量方法 与很多团队一样,我们发现在每两周的迭代后期都有未完成的测试任务.有时候用户故事未完成.比如,我们从一个包含5页向导程序的UI开始一个故事(story),其中只有4页完成了. 有一位程序员提议用一个"强线程"(steel thread)来标识复杂故事--一个将功能点从不同终端隔离开来的小的功能点.我们为它编写测试.写出代码,然后将测试自动化然后转移到下一个线程.那样的话,测试自动化即便在GUI层面,也能与开发保持一致.第一个自动化的测试可能会过于简单,但可以逐步进行

自动化测试最佳实践 连载五

第2章 终极数据库自动化 Henri van de Scheur Henri van de Scheur讲述了一个跨越6年的故事,是有关他和他的同事在开发一款适用于多个环境的测试数据库工具时所发生的事情.他们为自己的自动化测试设定了良好的目标,并为测试工具搭建了一个良好的架构.他们使很多测试实现了自动化,从而为自动化测试构建了一个完整的生命周期,包括周期性的bug清理.测试是每晚.每周运行的,或者根据特殊的时间表来安排执行.虽然取得了巨大的成功,但他们也遭遇过一系列的问题,Henri都如实地进行

《 自动化测试最佳实践:来自全球的经典自动化测试案例解析》一一 1.10 持续改进

1.10 持续改进 2011年是我们自动化测试之旅的第8年,总是要面临新的挑战.正如本章所述,我们的GUI测试套件已经增长到需要2个多小时来运行.这个时间太长了,所以我们将它划分为两个测试套件,并在两个从属机器上并行运行.这需要进行大量的工作,因为有些测试依赖于其他测试,过去没有好好实施而是采取了折中的方法,现在要为此付出代价.我们有超过5400(这个数字还在增长)个JUnit,并且重构的FitNesse测试套件在30分钟内完成. 我们知道在单元级别中的测试覆盖率,但是并不知道在功能性或GUI级

权限管理最佳实践:三&amp;amp;amp;四,数据级权限管理方案探讨

问题描述 内容比较多,也有不少代码,粘贴过来太累了.感兴趣的点击下面链接: 解决方案 解决方案二:感谢分享!解决方案三:好东西...解决方案四:lz大哥,给我介绍一下,你推荐的这个都有哪些优点,缺点,这个目前怎么样,火不,用的人多吗?解决方案五:我点击超链为啥是404呢真相呢天理呢?解决方案六:我点击后的效果和4楼的效果是一样一样的!解决方案七:我和5楼一样解决方案八:demo好像特别卡解决方案九:点击看不了,什么原因?

VPC最佳实践(三):如何选择公网类产品?

目前阿里云虚拟网络为用户提供了以下几种不同形态的公网类产品:负载均衡 (SLB),弹性公网IP (EIP),NAT网关.这几种产品分别适用于不同的场景,用户可通过这几种产品实现VPC资源与公网的互通. 产品使用场景核心关键词       产品 场景关键词 计量计费特性   SLB DNAT + 负载均衡 七层转发/四层转发 健康检查/高可用 预付费:按带宽 后付费:按带宽/按流量 NAT网关 DNAT(IP映射/端口映射) SNAT(ECS访问互联网) 共享带宽 后付费:按带宽   EIP 最简

本节书摘来自华章出版社《 自动化测试最佳实践:来自全球的经典自动化测试案例解析 》一 2.2 测试中的软件

2.2 测试中的软件 该项目中要测试的软件是比较特殊的,因为它仅仅只包含数据库.虽然有一些现存的测试套件可用于测试数据库,例如测试多个数据库API和查询语言之间兼容性的测试套件,包括JDK(Java Development Kit).JDBC.ODBC(Open DataBase Connectivity)和SQL,但是这些工具的使用并不广泛,并且(或者)它们仅仅只是为使用它们的数据库量身定做的.所以本案例研究中的测试和测试工具都是内部开发的. 我们定义了一个操作系统组合而成的平台,包括它的品牌

Web前端优化最佳实践之Cookie篇

Web 前端优化最佳实践第三部分面向 Cookie .目前只有 2 条实践规则. 1. 缩小 Cookie (Reduce Cookie Size) Cookie 是个很有趣的话题.根据 RFC 2109 的描述,每个客户端最多保持 300 个 Cookie,针对每个域名最多 20 个 Cookie (实际上多数浏览器现在都比这个多,比如 Firefox 是 50 个) ,每个 Cookie 最多 4K,注意这里的 4K 根据不同的浏览器可能不是严格的 4096 .别扯远了,对于 Cookie