谷歌如何测试软件

James Whittaker 整理:徐荣中

组织架构

经常有人问“谷歌如何测试?” 本博之前有零零碎碎的介绍,现在我们来做一个系统的介绍。 在谷歌测试策略从来没有改变,但在战术方面随着公司也不断发展而发展。我们现在有搜索,应用服务,广告,手机,操作系统等业务。 这些特定领域有我们必须解决相关的问题。当我们添加新的业务或壮大现有的业务时,我们的测试也得到了扩大和提高。 这个系列文章记录是我们今天所做的和在可预见的未来前进的方向。

我们从组织结构开始讲起,它可能会让你大吃一惊。 在谷歌没有实际的测试部门。测试存在于关注区域,称为工程效率。工程效率拥有很多纵向和横向的工程部门,测试是其中最大的。概括地说,工程效率的组成如下:

  • 产品团队:开发内部和开源工具,供公司所有工程师使用。我们建立和维护的代码分析器,集成开发环境,测试用例管理系统,自动化测试工具,编译系统,源代码控制系统,代码审查系统,bug数据库。旨在通过工具使工程更加有效率,工具是防止错误战略目标非常大的一部分。

  • 服务团队,为产品团队提供专业知识,包括工具,文档,测试,发布管理,培训等等。 我们的专长包括可靠性,安全,国际化等,以及产品的具体功能问题。

  • 嵌入工程师,进驻到谷歌产品团队提供支持。有些工程师可能会伴随同一产品团队多年,有些则在最需要他们的地方周转。谷歌鼓励其所有工程师改变产品团队以保持新鲜、忙碌和有目标。产品知识和新鲜事业的平衡是测试经理必须密切关注的。

因此,这意味着测试人员要向工程效率经理汇报,同时还要关注自己的产品团队,例如搜索,Gmail或浏览器。 在组织上,他们是两支球队的一部分。他们和产品团队一起,参与其规划,与他们共进午餐,分享奖金并得到产品团队正式成员对待。 该独立报告结构的好处是,它提供了分享信息测试环境。良好的测试理念易于在工程效率的所有测试时人员中传播,不管他们的从事什么产品,都获得了公司内最好的技术。

项目和汇报结构的分离也有其挑战。迄今为止最大的是,测试人员是外部资源。产品团队不能过分依赖测试,必须自己保证质量。是的,这是正确的:在谷歌的团队把握自己的产品质量,而不是测试人员。每一个开发应该做自己的测试。测试人员的职责是确保他们有自动化平台和可靠的流程,使开发可以自力更生进行测试。

我喜欢这个策略,它使开发和测试像两只平衡的脚。它使开发和测试称为真正的伙伴,质量应该由开发来负责。它让我们可以开发多于测试。开发越擅长测试,人员就比测试更多。 产品团队应该为一个高开发测试比例自豪!

以上内容节选自:https://googletesting.blogspot.com/2011/01/how-google-tests-software.html

参考资料:


  • python中文库参考项目: https://bitbucket.org/china-testing/python-chinese-library

  • python中文库参考项目文档:https://bitbucket.org/china-testing/python-chinese-library/wiki/browse/

  • 技术支持 (可以加钉钉pythontesting邀请加入) qq群:144081101 591302926 567351477

  • 道家技术-手相手诊看相中医等钉钉群21734177 qq群:391441566 184175668 338228106 看手相、面相、舌相、抽签、体质识别。服务费50元每人次起。请联系钉钉或者微信pythontesting

接口自动化性能测试数据分析人工智能从业专家一对一线上培训大纲

角色

为了做到“you build it, you break it”这句名言所说的那样,有必要在传统的开发人员之上再增加几个工作角色。因为懂技术,开发人员做测试工作就更合适、更有效。在Google,我们新增的工作角色是来让技术人员负责去提高其他人的效率。这些技术人员通常把自己看作是测试人员,但他们真正的使命是提高生产率。他们的存在可以使开发人员更高效,产品更有质量,这些都是生产率最重要的部分。下面是对这些角色的一些概述:  

  • SWE(Software Engineer)

软件工程师是传统的开发角色。SWE编写需要提交给客户使用的程序功能代码。他们编写设计文档,设计数据结构,以及整个架构,他们主要的时间是花在开发和检查程序代码。SWE会写出大量的测试程序,包括测试驱动设计,单元测试,以及我在下一部分里将会提到的整个开发工程中的小规模(small),中等(medium),大规模(large)的测试程序。SWE对他动过的任何程序的质量负责 —— 不论是自己开发的、还是改过bug的,或完善过的程序。  

  • SET(Software Engineer in Test)

测试开发工程师同样也是开发人员,只不过他们更侧重于测试相关的东西。他们审查设计,发现里面的代码质量问题和风险。他们精炼代码,让程序更容易测试。SET编写单元测试/自动化测试框架。他们是SWE开发的程序的共同创造者,但更关注于提高质量和测试覆盖率,而不是增加新功能和提高程序性能。  

  • TE(Test Engineer)

TE正好和SET反过来。这个角色是以测试第一,开发放在第二。很多Google的测试工程师的大部分时间都是在写自动化测试脚本之类的代码,用来驱动测试用例或模拟一个用户。他们同时也负责组织SWE和SET的测试工作,解释测试结果和驱动测试执行,特别是在项目开发的晚期推动产品正式发布的重要角色。测试工程师是产品专家,质量顾问,风险分析师。

从质量的角度看,软件工程师对产品功能和产品质量负有完全独立的职责。他们负责产品对错误的忍耐度的设计,错误恢复,测试驱动设计,单元测试,以及和SET开发那些用来测试这些程序的测试代码。

测试软件工程师是编写测试功能的开发人员。他们提供一种框架,通过模拟器(桩、mock、fake)来模拟程序依赖,使开发出的新代码单独运行并测试他们的特性。负责管理代码的提交(check-in)。换句话说,测试软件工程师编写编码以便软件工程师可以大部分的实际的测试活动都是软件工程师执行的,测试开发工程师只是来确保程序的各项功能都可测试,软工实际参与测试用例的编写。

很显然,测试开发工程师主要是为开发人员服务的。确保每个功能的质量是他们的目标,他们使开发人员能够容易的测试自己开发出的程序。我相信有人肯定已经看出,在这个开发过程中,存在一个巨大的漏洞:怎么没有用户?

用户测试是Google的测试工程师的工作。假设SWE和SET的测试充分的话,下一步的工作就是看看这一堆的可执行代码和数据集成起来是否满足用户的需求。测试工程师在开发人员的工作基础上做双重检查。任何明显的bug的存在都会说明前期开发测试工作的不充分或者草率。当这种问题很少时,工程师会将主要精力放在软件在用户场景中运行时的性能效率、安全性、国际化等问题上。测试工程部要做大量的测试,并且要在工程师和签约测试人员,目标集体测试者,crowd sourced testers,beta用户,前期用户之间配合测试。他们会同遇到基础设计上、功能复杂度和错误避免方法上的问题的用户进行交流。测试工程部一旦插手,事情就永远没个完了。  

以上内容节选自:https://googletesting.blogspot.com/2011/02/how-google-tests-software-part-two.html

开发和测试融合

在Google,质量并不等于测试。我相信在任何一个地方都是如此。“质量不是被测试出来的”这句老话是再正确不过了。从汽车到软件,如果它们起初制造的就有问题,那它们永远都不会没问题。试问任何一个曾经被迫大量召回的汽车公司,掩盖质量问题的代价有多大。

然而,事实情况并不是像这句话那样既简单又精确。虽然质量并不是测试出来的,但我们有同样的证据表明,没有测试,你不可能开发出任何有质量的东西。一个人怎么可能在没有测试的情况下认定你的构建具有高质量?

对于这种难题,最简单的解决办法就是:不要分隔开发和测试。开发和测试携手合作。编写一点,测试一点。再编写一点,再测试一点。更好的方法是制定测试计划,或者你开发之前先把计划做好。测试并不是一个独立的工作,它是开发工作的一部分,伴随着整个开发过程。质量不等于测试;为了质量,需要你把开发工作和测试结合到一起,搅拌它们,直到分不清你我为止。

在Google,这是我们明确的目标:把开发和测试融合,你不能单独进行任何一项工作。做一点,测试一点。再做一点,再测试一点。关键就是看谁在做测试。因为在Google,专职测试人员是出奇的少,所以唯一可行的方法就是使用开发人员。还有比这些实际开发了这些程序的人员更合适做测试的吗?还有比程序的作者更适合去发现bug的吗?是谁具有更多的愿望在程序第一次写出时避免bug?Google之所以安排这么少的专职测试人员的原因就是,开发者负责质量。事实上,坚持使用大型测试机构的团队通常会开发出有问题的东西。测试机构庞大,这是一个信号表明编码/测试工作的融和有问题。增加测试人员并不能解决任何问题。

这就是说相对于检测,质量措施更多的应该是一种预防行为。质量属于开发问题,而不是测试问题。通过把测试工作一定程度的融合到开发过程中,我们创建了一个渐进的流程:如果增加bug过多,可以回滚。我们不仅避免了大量的客户方的问题,也减少了处理找回bug的测试人员的数量。在Google,测试工作的目标就是检查这些预防工作是否在有效的运行。测试工程师一直在寻找这种作为bug创造者的软件工程师和作为bug预防者的测试软件工程师之间的联合能达到的效果的证据,一旦这个方法出现问题,他们就会拉响警笛。

这种开发和测试的结合随处可见,从代码审查注释上写的“你的测试呢?”到厕所里的给开发者的最好的测试实践方法的宣传画——这是我们臭名昭著的厕所测试指导方针。测试是开发工作中是必不可少的,开发和测试的联姻是孕育质量的过程。SWE就是测试者,测试开发就是测试者,测试工程师就是测试者。

如果你的企业也有这种类型的结合,请分享出你们成功的经验与挑战。如果没有,那么这是一个给你的企业带来好处的机会:在开发人员和质量之间画上全等号。你们都听过这样一个老故事:小鸡很高兴能为一顿咸猪腿加鸡蛋早餐奉献自己的力量,可猪究竟做错了什么?的确是 … 去对你的开发人员哼哼两声,看能不能得到他们哼哼回应。如果他们发出的是咯咯哒的声音,那说明你们之间存在问题。

以上内容节选自:https://googletesting.blogspot.com/2011/02/how-google-tests-software-part-three.html

版本管理

谷歌实现比许多公司更少的测试人员而达到良好的结果关键方法之一是,我们很少尝试一次组装大量的功能。事实上,目标往往正好相反,我们打造产品的核心并立即发给尽可能多的用户,然后得到他们的反馈并进行迭代。Gmail就是这样开发的,它Beta了四年。我们去掉了beta的标记当我们达到了可以99.99%的处理一个真实的用户的电子邮件数据。显然,质量是一项正在进行的工作!

事实上为了达到测试channel,产品必须经过其他一些channel,以证明它的价值。比如Chrome,我刚进goolge 2年工作的产品,使用了多种channel,并最大限度利用了用户反馈。具体过程如下:

  • 金丝雀Channel是用于我们怀疑是不适合发布的代码。 就像在煤矿的金丝雀,如果它不能再生存下去,我们有工作要做。金丝雀通道适用于超宽容的实验性用户,而不是靠应用来完成实际工作的用户。-类似大陆所称的冒烟测试。

  • 开发Channel是开发人员的每天都要使用。产品的所有工程师,把这个版本使用实际工作中。

  • 测试Channel适用于内部。

  • Beta Channel或发布Channel版本是首次对外曝光。

这种爬行,走路,跑步的方式除了可以使用自动化每一轮channel外,还可以使我们有机会来更早的执行测试和实验应用以及收集用户反馈。

该过程也利于分析。如果现场发现bug,测试人员可以在每个channel执行来检验是否修复。

https://googletesting.blogspot.com/2011/03/how-google-tests-software-part-four.html

测试规模

Google不使用代码,集成和系统测试等概念,谷歌使用了小型,中型和大型等强调范围的概念。

  • 小型测试

通常是自动化了的针对单个函数或者模块的测试。一般由软件工程师或者测试软件工程师书写,需要mocks和faked的环境。测试工程师诊断特定的故障时也可以使用到这些测试。 小型测试一般关注典型的功能问题,如数据损坏,错误条件等,它检验了代码是否做了该做的事情。

  • 中型测试

以自动化或者手工方式执行,一般包含了2个或者多个特性以及特性间的交互。一些测试开发工程师这样描述中型测试:测试一个功能及其最近的功能。当产品开发早期单个特性完成的时候,测试开发工程师驱动开发这些测试,开发工程师书写,调试和维护测试。如果测试失败或者终端,开发独立处理。产品开发后期,测试工程师可能执行中型测试。中型测试试图解答:相邻特性写作是否正常。

  • 大型测试

包括三个大型以上(通常更多)功能并且尽可能接近用户场景。这涉及所有特性的集成,不过大型测试更倾向于结果导向,即软件是否是用户希望的?

小型,中型和大型的表达方式并不重要。 重要的是,谷歌测试人员都有一个共同的语言。要尽量多使用自动化,涉及到主观判断和隐私的,可以不自动化。

以上内容节选自:https://googletesting.blogspot.com/2011/03/how-google-tests-software-part-five.html

SET的职业生涯

SET是测试方面的软件工程师,他书写测试功能。首先SET是开发,在招聘和内部晋升资料中被我们奉为100%的编码角色。当在招聘面试软件测试开发工程师的时候,对于编码的要求几乎和对软件开发工程师的要求是一模一样的,而且更强调如何去测试自己写的代码。换句话说,软件开发工程师和SET都需要回答编码问题,而且SET会被问到一系列测试相关的问题。

正如你可能想到的,这是一个很难满足的角色。SET的数量如此之少的最有可能的原因是具备所需技能的人非常难找。

通常SET不会在早期设计阶段就介入。不是故意这样做,而是和多数谷歌的产品是如何诞生的有关。一个常见的新产品诞生是已有的谷歌产品的员工会投入20%时间来开始新的产品。Gmail和Chrome OS这2个产品,从一个简单的想法开始,并非正式地由谷歌授权去做的,慢慢地随着时间的推移,越来越多的开发和测试加入进来并把产品发布。在这种情况下,早期的开发要关注的重心并不是质量,更关注提供一些理念,在解决了扩展性和性能的问题之后,再更多地关注质量。如果你还不能创建可扩展的web servic时,测试并不是你最大的问题。

你可以想象这样一个过程,某人有了一个好主意,他开始思考并写了一些试验性质的代码,从其他人那里获取一些建议然后对这些代码做了改进,并劝说更多的人加入,写了越来越多的代码,然后意识到他们做的事情很重要,通过更多的代码把这个想法变成可以呈现给他人并得到反馈的模型… ?这个项目在谷歌的项目库中就创建了,这个项目慢慢地转正。

所有正式项目都有专职的测试人员么? 默认是没有的。小型项软件测试开发工程师目和用户数有限的项目一般由开发人员自试。其他的一些对个人或者企业用户有潜在风险的项目测试才会介入。

当开发团队寻求测试团队参与并帮助他们时,他们有责任使测试人员相信他们的项目是令人兴奋并充满潜力的。开发总监会给测试总监解释他们的项目、进度、发布计划,一起讨论测试工作如何划分,并就开发需要满足的单元测试水平及开发参与测试工作程度上达成一致,发布流程中开发与测试的责任也需要明确。SET在项目初期可能不会参与进来,但项目转正后他会对运作发挥巨大的影响力。

当我说“测试”时,并不是仅仅意味着单纯的检查验证代码路径。测试人员不是从开始就参与进来的,但“测试”却至始至终都有。实际上开发上传代码或者之前,SET的影响力已经显现。

参考资料:

https://googletesting.blogspot.com/2011/05/how-google-tests-software-part-six.html

https://googletesting.blogspot.com/2011/04/set-career-path.html

软件测试工程师的职业生涯

相比SWE和SET而言,软件测试工程师(Software Test Engineer TE)是一个较新的角色,甚至这个角色本身目前还在定义完善之中。当前谷歌测试工程师们正在对未来这一角色的定义上进行 实践尝试中。在这里,我们讲述的这个角色的定义过程,是正在进行中的,也是我们认为最适宜谷歌的。

策略上讲,项目配备多少测试资源,是和项目风险、投资回报率息息相关的。如果对用户(不管是个人还是企业用户)的风险较大,则意味着在测试上 要投入较多的资源,需要更多的测试工程师。但投入的资源需要和其潜在的回报成正比。我们需要在合适的时间,投入合适数量的测试工程师,并得到合适的收益。

当测试工程师,进入产品的时候,并不需要一切重头开始。在项目最开始的时候,开发工程师和测试开发工程师已经在测试工程和质量方面做了大量工作。测试工程师在进入产品时,需要考虑以下一些问题:

  • 当前软件的薄弱点在哪里?
  • 从安全、隐私、性能、稳定性这几个角度出发都关注哪些内容?
  • 对于主流用户来说,是否可以满足他们的预期?对于全球所有的用户也是这样么?
  • 这个产品是否需要和其他产品交互(软件和硬件上)?
  • 当发生问题的时候,诊断工具是否很好地使用?

上面所有问题,都会被当做软件发布过程中的风险进行讨论。测试工程师并不需要自己去解决所有这些问题,但必须保证这些问题被解决掉,这就需要去评估 其他人的工作来看还有多少工作需要去做。其实,测试工程师之所以被雇佣,就是为了保护软件的最终个人企业用户的利益,使之不受糟糕的设计、令人疑惑的用户交互界面、功能缺陷、安全和隐私等问题带来的不良影响。在谷歌,测试工程师是团队中唯一全职对整体产品弱点关注的角色。和SET相比, TE的工作并不是那么清晰和一致。测试工程师会被要求在项目的各个阶段都提供援助,无论产品是一个想法的时候,还是产品已经到了第八个版本,甚至需要为一些已经过时封存已久的项目提供支持。有些测试工程师,比如在安全的,通常会同时负责多个项目。

显然,不同项目中的测试工程师的工作内容也会不同。一些TE像SET一样编码为主,但更多关注端对端的用户使用场景。其他TE利用已有的代码和设计来验证失败的场景。TE必须对测试计划及测试完成做系统全面的考虑, 特别是在真实使用方式和系统体验上。在需求不明确的情况下,测试工程师善于对一些说不清的问题上做原因分析和沟通处理。

考虑到测试工程师需要的技术技能、领导力、对产品的深厚理解力等多方面要求,其职位描述会是令人恐惧的,如果没有正确的指导,这个角色会很难去做。 幸运的是,在谷歌,一个由测试工程师们组成的强大社区的出现解决了这个问题。在所有的工作角色中,测试工程师可能是最好可以相互提供帮助的角色,这个角色需要敏锐的洞察力和领导力,因此谷歌的许多高级测试经理从测试工程师起步的。

测试工程师的工作经常需要去打破常规。在任何时刻,一旦测试工程师进入项目,他就需要去评估项目、代码、设计、用户的当前状态,并决定当前需要去首 先关注些什么。如果进入项目的时候,项目刚刚开始,这个时候测试计划会是第一优先级要解决的问题。有些时候测试在产品的晚期才进入,这个时候需要去评估这 个项目是否已久为产品发布做好了准备,或者在“beta”版本发布之前还需要解决哪些主要的问题。如果测试工程师进入了一个新的产品,或者他对这样产品中 有较少经验的时候,通常情况下会先去做一些不需要测试计划的探索性测试工作。在另外一些时候,项目已经很久没有发布了,只是需要去做一些修饰或者安全方面 的修复,或者用户交互方面的更新,这需要测试工程师针对不同阶段的项目使用不同的方法。谷歌的测试工程师需要在不同的项目做不同的事情,并且他们很少做相同的事情。

参考资料:https://googletesting.blogspot.com/2011/05/how-google-tests-software-part-seven.html

后记

谷歌的测试方式成为业界的标杆之一,上述文章很受欢迎。为此谷歌相关测试人员后面整理了一本书:

How Google Tests Software - 2012.pdf

中英文下载地址:qq群:144081101

第一章:Google软件测试介绍 基本及时上述内容。

第2章软件测试开发工程师

前言

  • Alberto Savoia 谷歌工程总监

互联网的出现急剧地改变了许多软件设计、开发和发布的方式。很多曾经红极一时的测试书籍里提及的最佳测试实践,在当前的环境下效率会大大下降,或者毫无效果,甚而在某些情况下会事与愿违地起反作用。在互联网和软件产业,一切变化都如此迅速,以至于许多最近几年才出版的软件测试方面的书籍都已陈腐过时。

我于2001年以工程总监的身份加入Google。当时,Google大概有200名开发人员,但只有区区3位测试人员!那个时候,开发人员已经开始做自己代码的测试了,但由于测试驱动开发的模式才刚刚开始,而且像JUnit这样的测试框架也没有大规模使用。当时的测试主要是在做一些随机测试(ad-hoc testing),其好坏取决于编写代码的开发者的责任心。但即使那样也是可以接受的,因为,当时正处在创业阶段,必须快速前进并勇于冒险,否则就无法和那个时代已经非常强大的对手竞争。

然而,当Google逐渐成长变大,Google的一些产品对于最终用户和客户来说开始变得至关重要(例如,竞价广告产品,我曾经负责的产品,很快变成许多网站的主要收入来源),我们清晰地认识到必须加大对测试的关注和投入。但只有3个测试工程师,别无选择,只能让开发来做更多的测试。与其他的几个Googler(译注:Google员工,本书中一般指Google工程师)一起,我们介绍、培训、推行单元测试,我们鼓励开发人员把测试作为优先级较高的事去做,并建议使用一些工具,如JUnit,把测试做成自动化的。但是进展缓慢.

开发人员发现,为了测试充分,他们不得不针对每一行功能代码,写两到三行的单元测试代码,而且这些测试代码和功能代码一样都需要维护,且有着相同的出错概率。而且大家也意识到,仅做单元测试是不够的,仍然需要集成测试、系统测试、用户界面等方面的测试。当真正开始要去做测试的时候,会发现测试工作量变得非常大(且需要很多知识的学习),并要求在很短的时间内完成测试,要以"迅雷不及掩耳"之势完成。

我们为什么要在很短的时间内迅速地完成测试呢? 我一直这么认为,对于一个坏点子或考虑欠周的产品,即便再多的测试,也无法把它变成一个成功的产品。但如果测试方法不当,却会扼杀一个本来有机会成功的产品或公司,至少会拖慢这个产品的速度,让竞争对手有机可乘。

  • Patrick Copeland 谷歌测试和部署技术的架构师

我在Google的旅程始于2005年3月。Alberto在前面的序中也介绍了一些当时Google的状况:虽然公司规模还比较小,但已开始感受到成长带来的烦恼。当时适逢快速的技术变革之际,Web世界正在迎接动态内容的到来,而云计算也正在逐渐成为一种新的选择,取代当时还占统治地位的客户机-服务器架构

我加入Google的时候,工程团队还不足1000人。测试团队大概有50名全职人员和一些临时工,具体数量我一直没搞清楚。测试团队当时的称谓是"测试服务",工作重点在UI的验证上,随时响应不同项目的测试需求。可以想象,这并不是Google最闪耀的团队。

但这在当时已经足够了。Google当时的主要业务是搜索和广告,规模要比今天小得多,一次彻底的探索式测试足以发现绝大多数的质量问题。然而,世界在变,Web点击量开始史无前例地爆发性增长,文档化的Web正在让位于应用化的Web。你可以感觉到势不可挡的成长和变化,在这种情况下,规模化和快速进入市场的能力变得至关重要和生死攸关。

在Google内部,规模和问题的复杂性给测试服务团队带来了巨大的压力。在之前小型的、类同的项目里的一些可行做法,现在却让优秀的测试人员感到筋疲力尽,疲于奔命在多个急需救火的项目之间。更加火上浇油的是,Google在项目快速发布方面的坚持。是时候采取措施了,我面临两个选择,要么沿用这种劳动密集型的流程增加更多的人手,要么改变整个游戏规则。为了适应业界和Google发生的巨变,测试服务团队需要根本性的变革。

我也很想说自己是借助于丰富的经验构思出了完美的测试组织模型,但实事求是地讲,我从过去的经历中,学到的只不过是一些过时的做法。我所工作或领导过的每个测试组织都有这样或那样的问题。有问题是常态,代码质量很糟糕,测试用例很差劲,团队也问题多多。我完全清楚那种被技术质量债压得喘不过气来的感受,在那种状态下,一切创新性的想法都会被遏制,以免不小心破坏了脆弱的产品。如果说我在以往的经历中有所收获的话,那就是经历了各种错误的测试实践。

那个时候,以我对Google的了解,有一件事情是确定无疑的,那就是Google对于计算机科学和编程能力非常重视。从根本上说,如果测试人员想加入这个俱乐部,就必须具备良好的计算机科学基础和编程能力。

变革Google测试的首要问题是重新定位身为测试人员的意义所在。我过去经常在头脑中想象理想团队的模型,想象这样的团队是如何肩负起质量重任的,每次我都会得到相同的结论:一个团队能编写出高质量软件的唯一途径是全体成员共同对质量负责,包括产品经理、开发人员、测试人员等所有人。我认为,达到此目标的最好方式是使测试人员有能力将测试变成代码库的一个实际功能,而测试功能的地位应该与真实客户看到的任何其他功能同等重要。我所需要的能够实现测试功能的技能,也正是开发人员需要具备的技能。

招聘具备开发能力的测试人员很难,找到懂测试的开发人员就更难,但是维持现状更要命,我只能往前走。我希望测试人员能为他们的产品做更多的事情,同时,我希望演变测试工作的性质和从属,要求开发团队更大地投入。这种组织结构在当时的业界尚未实现,但我坚信它非常适合Google,我相信在这家公司,时机到了。

不幸的是,这种如此深刻、根本性的变革在公司里极度缺乏认同,极少有人能分享我的激情。当我开始推销这种关于软件测试角色的地位平等而作用不同的愿景时,我发现竟然难以找到一个人一起共享午餐!开发工程师们好像被他们将要在测试上发挥更大的作用这个想法吓着了,他们指出"这是测试人员的职责"。而测试人员也不买账,因为很多人已经习惯了当前的角色,维持现状的惯性导致任何变革都变得非常困难。

我毫不松懈地继续努力着,主要是出于对Google的研发过程深陷技术和质量债的困境的恐惧,一旦如此,长达5年的开发周期又会成为现实,而我本来已经很高兴地把它们留在客户机-服务器的世界里了。Google是一家由天才组成的公司,以创新为灵魂,这种企业文化与冗长的开发周期是不相容的。这是一场值得打的战斗,我说服自己,一旦这些天才理解了这种旨在打造一个生产线式的、可重复的"技术工厂"的开发和测试实践 ,他们就会改变看法。他们就会理解我们不再是一个初创公司,快速成长的用户群、不断累积的bug和糟糕结构的代码形成的技术债将会导致开发过程的崩溃。

我逐个接触各产品团队,寻找优秀的案例,试图为我的立论找到比较容易的切入点。在开发人员面前,我描绘了一个持续构建、快速部署的蓝图,一个行动敏捷、省下更多时间用于创新的开发过程;在测试人员面前,我激发他们对于成为同等技能、同等贡献和同等薪酬的完全的工程合作伙伴的渴望。

开发人员的态度是,如果我们招聘到有能力做功能开发的人,那么,我们应当让他们做功能开发。其中一些人对我的想法非常反感,甚至发信给我的主管,非常直率地建议如何来处理我的疯狂之举,这些信塞满了我的主管的邮箱。幸运的是,我的主管并没有采纳那些建议。

令我吃惊的是,测试人员的反应竟然与开发人员类似。他们沉湎于老的做事方式,抱怨自己在开发面前的地位,但又不想去改变。

我的主管对这些抱怨只有一句话:"这里是Google,如果你有想法,尽管去做就是。"

于是我开始付诸行动。我召集了一批志同道合的骨干分子,组成了一个面试团队,开始招聘。事情进行得比较艰难,我们寻找的人要兼具开发人员的技能和测试人员的思维,他们必须会编程,能实现工具、平台和测试自动化。我们必须对招聘和面试的标准与流程做出一些调整,并向已经习惯了既有模式的招聘委员会做出合理解释。

最初的几个季度进行得异常艰难。好的候选人经常在面试过程中失利,也许是因为他们没能很快地解决一些奇怪的编程问题,或是在某些人认为很重要的方面表现得不够好(然而这些方面其实与测试技能毫不相干)。我预料到了招聘过程的困难,每周都要抽出大量时间写辩词。这些辩词最终会到达Google联合创始人Larry Page手里(他一直是招聘的最终批准者)。他批准了足够多的候选人,我的团队开始稳步增长。直到现在,我猜每次Larry听到我的名字时想到的一定是:"招聘测试的!"

当然,到这个时候,我已经做了大量的宣传和鼓动工作,来说服大家这是唯一的选择。整个公司都在看着我们,一旦失败,后果将是灾难性的。对于一个混合了很多不断变化的外包人员和临时人员的小测试团队而言,期望显得如此之高。然而,即使是在我们艰难的招聘进行中同时减少了临时人员的数量时,我已经注意到了变化在发生。测试资源越稀缺,给开发人员留下的测试工作就越多。很多团队都勇敢地接受了挑战。我感觉,如果技术保持不变的话,这个时候的状态已经在接近我们的目标了。

然而,技术不是静止不动的,开发和测试实践处于飞速的变化之中。静态Web应用的时代已经成为过去,浏览器还在努力追赶之中,围绕浏览器的自动化技术比已经迟缓的浏览器还要落后一年。开发人员正面临着巨大的技术变革,在这个时候,把测试交给开发人员,这看上去是徒劳的。我们甚至还不太会手工测试这些应用,更不用提自动化测试了。

开发团队身上的压力也同样巨大。当时Google 开始收购拥有富含动态Web应用的公司。YouTube、Google Docs等后继产品的融入,延展了我们内部的基础设施。开发团队在编写功能代码的过程中,要面临很多问题,与我们测试人员在测试过程中要面临的问题一样,令人生畏!测试人员面对的测试问题无法孤立地解决。把测试和开发割裂开来,看成两个单独的环节,甚至是两类截然不同的问题,这种做法是错误的,沿着这条路走下去意味着什么问题也解决不了。解决测试团队的问题,只是我们前进路上的其中一步而已。

进展在继续。雇佣优秀的人是一件很有意思的事情,他们会推动进展的发生!到了2007年,测试团队有了更好的定位。我们能够很好地处理发布周期的最后环节。开发团队已经视我们为顺利上线的可靠合作伙伴。不过我们仍然是在发布过程的后期才介入的支持团队,局限于传统QA模型。尽管有了优秀的执行能力,我们还没达到我设想的目标。我解决了招聘方面的问题,测试也向着正确的方向发展,但是我们还是在整个流程中介入太晚。

我们在一个被称作"测试认证"(本书后面的章节会详细介绍)的事情上取得了不少进展。我们向开发团队提供咨询,帮助他们改善代码质量并尽早进行单元测试。我们开发工具并指导团队进行持续集成,使产品一直保持可测试的状态。我们进行了无数的改进和调整,从而消除了之前的很多质疑,本书详细介绍了其中的很多方法。但是,在那个时候,还是感觉缺乏整体感,开发依旧是开发,测试依旧是测试。虽然很多文化变革的因素已经存在,但是,我们还需要一个催化剂把它们聚合成一体。

自从根据我的想法开始招聘担当测试角色的开发人员以来,测试组织在不断壮大。基于对这个团队的思考,我意识到测试仅仅是我们所负责的工作的一部分。我们的工具团队开发了从源代码库到编译框架,再到缺陷数据库的各种工具。我们是测试工程师、发布工程师、工具开发工程师和咨询师。触动我的是,我们所做的非测试的工作对生产力的提升产生了巨大的影响力。我们的名称是测试服务,但是我们的职责已经远大于此。

因此,我决定正式把团队名称改为工程生产力(Engineering Productivity)团队。伴随着称谓的改变,随之而来的是文化的革新。人们开始更多地谈论生产力而不是测试和质量。生产力是我们的工作,测试和质量是开发过程里每个人都要承担的工作。这意味着开发人员负责测试,开发人员负责质量。生产力团队负责帮助开发团队搞定这两项任务。

开始的时候,这个观点还只是一种梦想和志向,我们提出的"给Google加速"的口号听起来也很空洞,但是,随着时间的推移和我们的努力,我们实现了这些诺言。我们的工具让开发的动作更快,我们帮助开发人员扫清了一个又一个障碍,消除了一个又一个瓶颈。我们的工具还使开发人员能够编写测试用例,并在每次构建时看到这些测试的结果反馈。测试用例不再只是隔离地运行在某些测试人员的机器上。测试结果会在仪表盘上显示,并把成功的版本积累下来,作为应用发布健康性的公开数据。我们并不是仅仅要求开发人员对测试和质量负责,我们还提供帮助让他们可以轻松地达到这些要求。生产力和测试的区别最终变成了现实--Google的创新能够更为顺畅,技术债也不会累积了。

最终结果如何呢?我可不愿这么早就交了底,因为这本书就是要详细讲述这个问题的。作者们花费了巨大精力,根据自身和其他Googler的经历,把我们的秘诀浓缩成了一套核心实践。但其实,我们的成功有很多方面,从将构建次数以数量级式地降低,到"跑完即忘"式的测试自动化,再到开源一些非常新颖的测试工具。在我写这篇序的时候,生产力团队已经拥有1200名工程师,这个数量比我在2005年加入Google时整个工程部门的工程师的数量还要多。生产力品牌的影响力已经相当大,我们加速Google的使命已经作为工程文化的一部分,被广泛接受。从我困惑、迷茫地坐在TGIF会议上的第一天到现在,这个团队已经走过了漫长的征途。这期间唯一没变的是我那顶三色螺旋桨帽,我把它放在我的桌上,作为我们一路走来的见证。

Patrick Copeland是Google工程生产力部门的高级总监,处于Google整个测试链的最顶端。公司里所有的测试人员都最终汇报给Patrick(而他恰好跨级汇报给Larry Page,Google的联合创始人和CEO)。Patrick加入Google之前是微软的测试总监,并在那里工作了近10年。他经常公开演讲,在Google内部被公认为Google软件快速开发、测试和部署技术的架构师。

Google软件测试介绍

  • 质量不等于测试

有时,测试和开发互相交织在一起,达到了无法区分彼此的程度,而在另外一些时候,测试和开发又是完全分离的,甚至开发人员都不知道测试在做些什么

质量不等于测试。当你把开发过程和测试放到一起,就像在搅拌机里混合搅拌那样,直到不能区分彼此的时候,你就得到了质量。

  • 角色

软件开发工程师(译注:software engineer,后文简称SWE)是一个传统上的开发角色,他们的工作是实现最终用户使用的功能代码。他们创建设计文档、选择最优的数据结构和整体架构,并且花费大量时间在代码实现与代码审查上。SWE需要编写与测试代码,包括测试驱动的设计、单元测试、参与构建各种规模的测试等,这些测试会在本章的后面做详细解释。SWE会对他们编写、修复以及修改的代码承担质量责任。如果一个开发者不得不修改一个函数,或者这次修改导致已有测试用例运行失败,或者需要增加一个新的测试用例,他就必须去实现这个测试用例的代码。开发工程师几乎将所有的时间都花费在了代码编写上。

软件测试开发工程师(译注:software engineer in test,后文简称SET)也是一个开发角色,只是工作重心在可测试性和通用测试基础框架上。他们参与设计评审,非常近距离地观察代码质量与风险。为了增加可测试性,他们甚至会对代码进行重构,并编写单元测试框架和自动化测试框架。SET是SWE在代码库上的合作伙伴,相比较SWE是在增加功能性代码或是提高性能的代码,SET更加关注于质量提升和测试覆盖率的增加。SET同样会花费近百分之百的时间在编写代码上,他们这样做的目的是为质量服务,而SWE则更关注在客户使用功能开发的实现上。

测试工程师(译注:test engineer,后文简称TE)是一个和SET关系密切的角色,有自己不同的关注点--把用户放在第一位来思考,代表用户的利益。一些Google的TE会花费大量时间在模拟用户的使用场景和自动化脚本或代码上。同时,他们会把开发工程师和SET编写的测试分门别类地组织起来,分析、解释、测试运行结果,驱动测试执行,特别是在项目的最后阶段,推进产品发布。TE是真正的产品专家、质量顾问和风险分析师。某些TE需要编写大量的代码,而另外一些TE则只用编写少量的代码。

  • 组织结构

测试是独立存在的部门,是与专注领域部门平行的部门(横跨各个产品专注领域),我们称之为工程生产力团队。测试人员基本上以租借的方式进入到产品团队,去做提高质量相关的事情,寻找一些测试不足的地方,或者公开一些不可接受的缺陷率数据。由于测试人员并不是直接向产品团队进行汇报,因此我们并不是简单地被告之某个项目急需发布就可以通过测试。我们有自己选择决定的优先级,在可靠性、安全性等问题上都不会妥协,除非碰到更重要的事情。如果开发团队想要我们在测试上放他们一马,他们必须事先和我们协商,但一般情况下都会被拒绝。

注意 工程生产力团队会根据不同产品团队的优先级、复杂度和其他产品的实际比较后,再来分配测试人员。显然,有时候我们可能搞错,实际上也确实出过错,但总体上来说,这样会保持实际的需求与不明确的需求之间的某种平衡。

这种测试人员在不同项目之间的借调模式,可以让SET和TE时刻保持新鲜感并且总是很忙碌,另外还能保证一个好的测试想法可以快速在公司内部蔓延。一个在Geo产品上运用很好的测试技术或工具,很有可能在Chrome产品中也得到使用。推广测试技术方面创新的最佳方式,莫过于把这个创新的发明者直接借调过来。

在拥有如此少量测试人员的情况下,Google还可以取得不错的成果,核心原因在于Google从来不会在一次发布的产品中包含大量功能。

  • 版本管理

金丝雀版本、开发版本、测试版本、beta或发布版本、

  • 测试类型

小型测试 一般来说(但也并非所有)都是自动化实现的,用于验证一个单独函数或独立功能模块的代码是否按照预期工作,着重于典型功能性问题、数据损坏、错误条件和大小差一错误等方面的验证。小型测试的运行时间一般比较短,通常是在几秒或更短的时间内就可以运行完毕。通常,小型测试是由SWE来实现,也会有少量的SET参与,TE几乎不参与小型测试。小型测试一般需要使用mock和fake(译注:mock fake环境是实际依赖系统的替代者,会提供相应的功能,但这些系统可能不存在,或者缺陷太多不可靠,或者是一些很难模拟的错误条件)才能运行。TE几乎不编写小型测试代码,但会参与运行这些测试,来诊断一些特定错误。小型测试主要尝试解决的问题是"这些代码是否按照预期的方式运行"。

中型测试 通常也都是自动化实现的。该测试一般会涉及两个或两个以上,甚至更多模块之间的交互。测试重点在于验证这些"功能近邻区"之间的交互,以及彼此调用时的功能是否正确(我们称功能交互区域为"功能近邻区")。在产品早期开发过程中,在独立模块功能被开发完毕之后,SET会驱动这些测试的实现及运行,SWE会深度参与,一起编码、调试和维护这些测试。如果一个中型测试运行失败,SWE会自觉地去查看分析原因。在开发过程的后期,TE会通过手动的方式(如果比较难去实现自动化或实现的代价较大时),或者自动化地执行这些用例。中型测试尝试去解决的问题是,一系列临近的模块互相交互的时候,是否如我们预期的那样工作。

大型测试 涵盖三个或以上(通常更多)的功能模块,使用真实用户使用场景和实际用户数据,一般可能需要消耗数个小时或更长的时间才能运行完成。大型测试关注的是所有模块的集成,但更倾向于结果驱动,验证软件是否满足最终用户的需求。所有的三种工程师角色都会参与到大型测试之中,或是通过自动化测试,或是探索式测试。大型测试尝试去解决的问题是,这个产品操作运行方式是否和用户的期望相同,并产生预期的结果。这种端到端的使用场景以及在整体产品或服务之上的操作行为,即是大型测试关注的重点。

关于自动化测试和手动测试的比例,对于所有的三种类型测试,当然更倾向于前者。如果能够自动化,并不需要人脑的智睿与直觉来判断,那就应该以自动化的方式实现。但在一些情况下需要人类智慧的判断,如用户界面是否漂亮、保留的数据是否包含隐私等方面,这些还是需要手动测试来完成。

软件测试开发工程师

对于功能代码而言,思维模式是创建,重点在考虑用户、使用场景和数据流程上;而对于测试代码来说,主要思路是去破坏,怎样写测试代码用以扰乱分离用户及其数据。由于我们假设的前提是在一个童话般的理想开发过程里,所以我们或许可以分别雇佣不同的开发工程师:一个写功能代码,而另一个思考如何破坏这些功能(译注:两种开发工程师,分别是功能开发人员和测试开发人员)。

功能开发人员在编写功能代码的时候,测试开发人员编写测试代码,但我们还需要第三种角色,一个关心真正用户的角色。显然在我们理想化的乌托邦测试世界里,这个工作应该由第三种工程师来完成,既不是功能开发人员,也不是测试开发人员。我们把这个新角色称为用户开发人员(译注:user developer)。他们需要解决的主要问题是面向用户的任务,包括用例(use case)、用户故事、用户场景、探索式测试等。用户开发人员关心这些功能模块如何集成在一起成为一个完整的整体,他们主要考虑系统级别的问题,通常情况下都会从用户角度出发,验证独立模块集成在一起之后是否对最终用户产生价值。

SET的工作

  • 开发和测试流程

工程师团队的交付物就是即将发布的代码。代码的组织形式、开发过程、维护是日常工作重点。

公开的代码库、和谐的工程工具、公司范围内的资源共享,成就了丰富的Google内部共享代码库与公共服务。这些共享的代码运行依赖于Google的基础设施产品,它们在加速项目完成与减少项目失败上发挥了很大作用。

工程师们对这些共享的基础代码做了特殊处理,形成了一套不成文但却非常重要的实践规则,工程师在维护修改这些代码的时候都要遵守这些规则。

* 所有的工程师必须复用已经存在的公共库,除非在项目特定需求方面有很好的理由。
* 对于公共的共享代码,首先要考虑的是能否可以容易地被找到,并具有良好的可读性。代码必须存储在代码库的共享区域,以便查找。由于共享代码会被不同的工程师使用,这些代码应该容易理解。所有的代码都要考虑到未来会被其他人阅读或修改。
* 公共代码必须尽可能地被复用且相对独立。如果一个工程师提供的服务被许多团队使用,这将为他带来很高的信誉。与功能的复杂性或设计的巧妙性相比,可复用性带来的价值更大。
* 所有依赖必须明确指出,不可被忽视。如果一个项目依赖一些公用共享代码,在项目工程师不知情的前提下,这些共享代码是不允许被修改的。
* 如果一个工程师对共享代码库在某些地方有更好的解决方案,他需要去重构已有的代码,并协助依赖在这个公用代码库之上的应用项目迁移到新的代码库上。这种乐善好施的社区工作是值得鼓励的(译注:这是Google经常提及的“同僚奖金(peer bonus)”。任何工程师如果受到其他工程师正面的影响,就可以送出“同僚奖金”作为感谢。除此之外,经理还有权使用其他奖励手段。这样做的目的就是让这种正向团队合作形成一种良性循环,并持续下去。当然,另外还有同事之间私下里的感谢)。 
* Google非常重视代码审核,特别是公共通用模块的代码必须经过审核。开发人员必须通过相关语言的可读性审核。在开发人员拥有按照代码风格编写出干净代码的记录之后,委员会会授予这名开发人员一个“良好可读性”的证书。Google的四大主要开发语言:C++、Java、Python和JavaScript都有可读性方面的代码风格指南。
* 在共享代码库里的代码,对测试有更高的要求(在后面部分会做讨论)。

最小化对平台的依赖。所有工程师都有一台桌面工作机器,且操作系统都尽可能地与Google生产环境的操作系统保持一致。为了减少对平台的依赖,Google对Linux发行版本的管理也十分谨慎,这样开发人员在自己工作机器上测试的结果,与生产系统里的测试结果会保持一致。从桌面到数据中心,CPU和OS的变化尽可能小(注:唯一不在Google通用测试平台里的本地测试实验室,是Android和Chrome OS。这些类目不同的硬件必须在手边进行测试)如果一个bug在测试机器上出现,那么在开发机器上和生产环境的机器上也都应该能够复现。

所有对平台有依赖的代码,都会强制要求使用公共的底层库。维护Linux发行版本的团队同时也在维护这个底层平台相关的公共库。还有一点,对于Google使用的每个编程语言,都要求使用统一的编译器,这个编译器被很好地维护着,针对不同的Linux发行版本都会有持续的测试。这样做本身其实并没有什么神奇之处,但限制运行环境可以节省大量下游的测试工作,也可以避免许多与环境相关且难以调试的问题,能把开发人员的重心转移到新功能开发上。保持简单,也就相对会安全。

Google在平台方面有特定的目标,就是保持简单且统一。开发工作机和生产环境的机器都保持统一的Linux发行版本;一套集中控制的通用核心库;一套统一的通用代码、构建和测试基础设施;每个核心语言只有一个编译器;与语言无关的通用打包规范;文化上对这些共享资源的维护表示尊重且有激励。

使用统一的运行平台和相同的代码库,持续不断地在构建系统中打包(译注:打包是一个过程,包括将源代码编译成二进制文件,然后再把二进制文件统一封装在一个linux rpm包里面),这可以简化共享代码的维护工作。构建系统要求使用统一的打包规范,这个打包规范与项目特定的编程语言无关,与团队是否使用C++、Python或Java也都无关。大家使用同样的“构建文件”来打包生成二进制文件。

一个版本在构建的时候需要指定构建目标,这个构建目标(可以是公共库、二进制文件或测试套件)由许多源文件编译链接产生。下面是整体流程。

* (1)针对某个服务,在一个或多个源代码文件中编写一类或一系列功能函数,并保证所有代码可以编译通过。

* (2)把这个新服务的构建目标设定为公共库。

* (3)通过调用这个库的方式编写一套单元测试用例,把外部重要依赖通过mock模拟实现。对于需要关注的代码路径,使用最常见的输入参数来验证。

* (4)为单元测试创建一个测试构建目标。

* (5)构建并运行测试目标,做适当的修改调整,直到所有的测试都运行成功。

* (6)按要求运行静态代码分析工具,确保遵守统一的代码风格,且通过一系列常见问题的静态扫描检测。

* (7)提交代码申请代码审核(后面对代码审核会做更多详细说明),根据反馈再做适当的修改,然后运行所有的单元测试并保证顺利通过。

产出将是两个配套的构建目标:库构建目标和测试构建目标。库构建目标是需要新发布的公共库、测试构建目标用以验证新发布的公共库是否满足需求。注意:在Google许多开发人员使用“测试驱动开发”的模式,这意味着步骤(3)会在步骤(1)和步骤(2)之前进行。

对于规模更大的服务,通过链接编译持续新增的代码,构建目标也会逐渐变大,直到整个服务全部构建完成。在这个时候,会产生二进制构建目标,其由包含主入口main函数文件和服务库链接在一起构成。现在,你完成了一个Google产品,它由三部分组成:一个经过良好测试的独立库、一个在可读性与可复用性方面都不错的公共服务库(这个服务库中还包含另外一套支持库,可以用来创建其他的服务)、一套覆盖所有重要构建目标的单元测试套件。

一个典型的Google产品由许多服务组成,所有产品团队都希望一个SWE负责对应一个服务。这意味着每个服务都可以并行地构建、打包和测试,一旦所有的服务都完成了,他们会在一个最终的构建目标里一起集成。为了保证单独的服务可以并行地开发,服务之间的接口需要在项目的早期就确定下来。这样,开发者会依赖在协商好的接口上,而不是依赖在需要开发的特定库上。为了不耽搁服务级别之间的早期测试,这些接口一般都不会真正实现,而只是做一个虚假的实现。

SET会参与到许多测试目标的构建之中,并指出哪些地方需要小型测试。在多个构建目标集成在一起,形成规模更大应用程序的构建目标时,SET需要加速他们的工作,开始做一些更大规模的集成测试。在一个单独的库构建目标中,需要运行几乎所有的小型测试(由SWE编写,所有支持这个项目的SET都会给予帮助)。当构建目标日益增大时,SET也会参与到中大型测试的编写之中去。

  • SET是什么?

SET是开发,主要做可测试性方面的工作。

SET首先是工程师角色,他使得测试存活于先前讨论的所有Google开发过程之中。SET(software engineer in test)是软件测试开发工程师。最重要的一点,SET是软件工程师,正如我们招聘宣传海报和内部晋升体系中所说的那样,是一个100%的编码角色。这种测试方式的有趣之处在于它使测试人员能尽早介入到开发流程中去,但不是通过“质量模型”和“测试计划”的方式,而是通过参与设计和代码开发的方式。这会使得功能的开发工程师和测试的开发工程师处于相同的地位,SET积极参与各种测试,使测试富有效率,包括手动测试和探索式测试,而这些测试后期会由其他工程师负责。

  • SET的介入时机

在项目早期,Google一般不会让测试介入进来。实际上,即使SET在早期参与进来,也不是从事测试工作,而是去做开发。绝非有意忽视测试,当然也不是说早期产品的质量就不重要。这是受Google非正式创新驱动产品的流程所约束。Google很少在项目创建初期就投入一大帮人来做计划(包括质量与测试计划),然后再让一大群开发参与进来。Google项目的诞生从来没有如此正式过。

  • 团队结构

Google产品团队最初是由一个技术负责人(tech lead)和一个或更多的项目发起人组成。在Google,技术负责人这个非正式的岗位一般由工程师担任,负责设定技术方向、开展合作、充当与其他团队沟通的项目接口人。他知道关于项目的任何问题,或者能够指出谁知道这些问题的细节。技术负责人通常是一名SWE,或者由一名具备SWE能力的工程师来担任。

  • 设计文档

所有Google项目都有设计文档。这是一个动态的文档,随着项目的演化也在不断地保持更新。最早期的项目设计文档,主要包括项目的目标、背景、团队成员、系统设计。在初期阶段,团队成员一起协同完成设计文档的不同部分。对于一些规模足够大的项目来说,需要针对主要子系统也创建相应的设计文档,并在项目设计文档中增加子系统设计文档的链接。在初期版本完成后,里面会囊括所有将来需要完成的工作清单,这也可以作为项目前进的路标。从这一点上讲,设计文档必须要经过相关技术负责人的审核。在项目设计文档得到足够的评审与反馈之后,初期版本的设计文档就接近尾声了,接下来项目就正式进入实施阶段。

作为SET,比较幸运的是在初期阶段就加入了项目,会有一些重要且有影响力的工作急需完成。如果能够合理地谋划策略,我们在加速项目进度的同时,也可以做到简化项目相关人员的工作。实际上,作为工程师,SET在团队中有一个巨大的优势,就是拥有产品方面最广阔的视野。一个好的SET会把非常专业的广阔视野转化成影响力,在开发人员所编写的代码上产生深远的影响力。通常来说,代码复用和模块交互方面的设计会由SET来做,而不是SWE。后面会着重介绍SET在项目的初期阶段是如何发挥作用的。

SET需要熟悉了解所负责的系统设计(阅读所有的设计文档是一个途径),SET和SWE都期望如此。 SET早期提出的建议会反馈在文档和代码里,这样也增加了SET的整体影响力。 作为第一个审阅所有设计文档的人(也因此了解所有迭代过程),SET对项目的整体了解程度超过了技术负责人。 对于SET来说,这也是一个非常好的机会,可以在项目初期就与相应开发工程师一起建立良好的工作关系。

审阅设计文档的时候应该有一定的目的性,而不是像读报纸那样随便看两眼就算了。优秀的SET在审阅过程中始终保持强烈的目的性。下面是一些我们推荐的一些要点。

1
2
3
4
5
6
    完整性:找出文档中残缺不全或一些需要特殊背景知识的地方。通常情况下团队里没人会了解这些知识,特别是对新人而言。鼓励文档作者在这方面添加更多细节,或增加一些外部文档链接,用以补充这部分背景知识。
    正确性:看一下是否有语法、拼写、标点符号等方面的错误,这一般是马虎大意造成的,并不意味着他们以后编写的代码也是这样。但也不能为这种错误而破坏规矩。
    一致性:确保配图和文字描述一致。确保文档中没有出现与其他文档中截然相反的观点和主张。
    设计:文档中的一些设计要经过深思熟虑。考虑到可用的资源,目标是否可以顺利达成?要使用何种基础的技术框架(读一读框架文档并了解他们的不足)?期望的设计在框架方面使用方法上是否正确?设计是否太过复杂?有可能简化吗?还是太简单了?这个设计还需要增加什么内容?
    接口与协议:文档中是否对所使用的协议有清晰的定义?是否完整地描述了产品对外的接口与协议?这些接口协议的实现是否与他们期望的那样一致?对于其他的Google产品是否满足统一的标准?是否鼓励开发人员自定义Protocol buffer数据格式(后面会讨论Protocol buffer)?
    测试:系统或文档中描述的整套系统的可测试性怎样?是否需要新增测试钩子(译注:testing hook,这里指为了测试而增加一些接口,用以显示系统内部状态信息)?如果需要,确保他们也被添加到文档之中。系统的设计是否考虑到易测试性,而为之也做了一些调整?是否可以使用已有的测试框架?预估一下在测试方面我们都需要做哪些工作,并把这部分内容也增加到设计文档中去。

google的代码评审工具 https://github.com/rietveld-codereview/rietveld

  • 接口协议

Google protocol buffer语言(注:Google protocol buffers 是开源的,参见http://code.google.com/apis/protocolbuffers)

为了能够尽早可以运行集成测试,针对依赖服务,SET提供了mock与fake。

  • 自动化计划

我们首先把容易出错的接口做隔离,并针对它们创建mock和fake(在之前的章节中做过介绍),这样我们可以控制这些接口之间的交互,确保良好的测试覆盖率。

接下来构建一个轻量级的自动化框架,控制mock系统的创建和执行。这样的话,写代码的SWE可以使用这些mock接口来做一个私有构建。在他们把修改的代码提交到代码服务器之前运行相应的自动化测试,可以确保只有经过良好测试的代码才能被提交到代码库中。这是自动化测试擅长的地方,保证生态系统远离糟糕代码,并确保代码库永远处于一个时刻干净的状态。

SET除了在这个计划中涵盖自动化(mock、fake和框架)之外,还要包括如何公开产品质量方面的信息给所有关心的人。在Google,SET使用报表和仪表盘(译注:dashboard)来展示收集到的测试结果以及测试进度。通过将整个过程简化和信息公开透明化,获取高质量代码的概率会大大增加。

  • 可测试性

为了使SET也成为源码的拥有者之一,Google把代码审查作为开发流程的中心。相比较编写代码而言,代码审查更值得炫耀。

在CL提交审查之前,会经过一系列的自动化检查。这种自动化静态检查所使用的规则包含一些简单的确认,例如是否遵循Google的代码风格指南、提交CL相关的测试用例是否执行通过(原则上所有的测试必须全部通过)等。CL里面一般总是包含针对这个CL的测试代码,测试代码总是和功能代码在一起。在检查完成之后,Mondrian会给相应的CL审阅者发送一封包含这个CL链接的通知邮件。随后审阅者会进行代码审查,并把修改建议发回给SWE去处理。这个过程会反复进行,直到提交者和审阅者都满意为止。

提交队列(译注:submit queue)的主要功能是保持“绿色”的构建,这意味着所有测试必须全部通过。这是构建系统和版本控制系统之间的最后一道防线。通过在干净环境中编译代码并运行测试,提交队列系统可以捕获在开发机器上无法发现的环境错误,但这会导致构建失败,甚至是导致版本控制系统中的代码处于不可编译的状态。

规模较大的团队可以利用提交队列在同一个代码分支上进行开发。如果没有提交队列,通常在代码集成或每轮测试时都会把代码冻结,使用提交队列就可以避免这个问题。在这种模式下,提交队列可以使得规模较大团队就像小团队一样,高效且独立。由于这样增加了开发提交代码的频率,势必给SET的工作带来了较大难度,这可能是唯一的弊端。

  • SET的工作流程:一个实例:

略,可以参考具体语言的单元测试。

  • 测试执行

做代码编译、测试执行、结果分析、数据存储、报表展示的通用的测试框架

  • 测试规模

小型测试是为了验证一个代码单元的功能,一般与运行环境隔离,例如针对一个独立的类或一组相关函数的测试。小型测试的运行不需要外部依赖。在Google之外,小型测试通常就是单元测试。

中型测试是验证两个或多个模块应用之间的交互。和小型测试相比,中型测试有着更大的范畴且运行所需要的时间也更久。小型测试会尝试走遍单独函数的所有路径,而中型测试的主要目标是验证指定模块之间的交互。在Google之外,中型测试经常被称为“集成测试”。

在Google之外通常被称为“系统测试”或“端到端测试”。大型测试在一个较高层次上运行,验证系统作为一个整体是如何工作的。这涉及应用系统的一个或所有子系统,从前端界面到后端数据储存。该测试也可能会依赖外部资源,如数据库、文件系统、网络服务等。

小型测试是为了验证一个代码单元的功能。中型测试验证两个或多个模块应用之间的交互。大型测试是为了验证整个系统作为一个整体是如何工作的。

  • 测试平台对测试规模的调度

使用Google测试执行平台运行的一些通用任务如下。

1
2
3
4
5
6
7
    开发人员编译和运行小型测试,希望立刻就能知道运行结果。
    开发人员希望运行一个项目的所有小型测试,并能够快速知道运行结果。
    开发人员只有在变更代码出现时,才希望去编译运行相关的项目测试,并即刻得到运行结果。
    工程师希望能够知道一个项目的测试覆盖率并查看结果。
    对项目的每次代码变更(CL),都能够运行这个项目的小型测试,并将运行结果发送给团队成员以辅助进行代码审查。
    在代码变更(CL)提交到版本控制系统之后,自动运行项目的所有测试。
    团队希望每周都能得到代码覆盖率,并实时跟踪覆盖率的变化。

上面提及的所有任务,有可能同时并发提交到Google测试执行系统。一些测试可能极度消耗资源,使得公用测试机器处于不可用状态达数小时。另外一些测试可能只需几毫秒,而且可以和其他几百个任务同时在一台机器上并发运行。当每一个测试都被标记为小型、中型、大型的时候,调度运行这些测试任务就会变得相对简单一些,因为调度器已经知道每个任务需要运行的时间,这样可以优化任务队列,达到合理利用的目的。

Google测试执行系统利用了测试规模的定义,把运行较快的任务从较慢的任务中挑选出来。测试规模在测试运行时间上规定了一个最大值,如表2.1所示;同时测试规模在测试运行消耗资源上也做了要求,如表2.2所示。Google测试执行系统在发现任何测试超时,或是消耗的资源超过这个测试规模应该使用的资源时,会把这个测试任务取消掉并报告这个错误。这会迫使工程师提供合适的测试规模标签。精准的测试规模,可以使Google测试执行系统在调度时做出明智的决定。

类别 | 小型测试 | 中型测试 | 大型测试 | 超大型测试 :---- ---:|:---- ---:|:---------------------:|:---------------------: 时间目标(每个函数)| 10毫秒以内 | 1秒以内 | 尽可能快 | 尽可能快 强制时间限制 | 1分钟之后强制结束 | 5分钟之后强制结束 | 15分钟之后强制结束 | 1小时之后强制结束

资源使用

类别 | 大型测试 | 中型测试 | 小型测试 :---- ---:|:---- ---:|:---------------------: 网络服务(建立一个链接)| 是 | 仅本地 | 模拟 数据库 | 是 | 仅本地 | 模拟 访问文件系统 | 是 | 是 | 模拟 访问用户界面系统 | 是 | 不鼓励 | 模拟 系统调用 | 是 | 不鼓励 | 否 多线程 | 是 | 是 | 不鼓励 睡眠状态 | 是 | 是 | 否 系统属性 | 是 | 是 | 否

  • 测试规模的优缺点

大型测试

1
2
3
4
5
    测试最根本最重要的:在考虑外部系统的情况下应用系统是如何工作的。
    由于对外部系统有依赖,因此它们是非确定性的。
    很宽的测试范畴意味着如果测试运行失败,寻找精准失败根源就会比较困难。
    测试数据的准备工作会非常耗时。
    大型测试是较高层次的操作,如果想要走到特定的代码路径区域是不切实际的,而这一部分却是小型测试的专长。

中型测试

1
2
3
4
5
6
    由于不需要使用mock技术,且不受运行时刻的限制,因此该测试是从大型测试到小型测试之间的一个过渡。
    因为它们运行速度相对较快,所以可以频繁地运行它们。
    它们可以在标准的开发环境中运行,因此开发人员也可以很容易运行它们。
    它们依赖外部系统。
    由于对外部系统有依赖,因此它们本身就有不确定性。
    它们的运行速度没有小型测试快。

小型测试

1
2
3
4
5
6
7
8
    为了更容易地就被测试到,代码应清晰干净、函数规模较小且重点集中。为了方便模拟,系统之间的接口需要有良好的定义。
    由于它们可以很快运行完毕,因此在有代码变更发生的时候就可以立刻运行,从而可以较早地发现缺陷并提供及时的反馈。
    在所有的环境下它们都可以可靠地运行。
    它们有较小的测试范围,这样可以很容易地做边界场景与错误条件的测试,例如一个空指针。
    它们有特定的范畴,可以很容易地隔离错误。
    不要做模块之间的集成测试,这是其他类型的测试要做的事情(中型测试)。
    有时候对子系统的模拟是有难度的。
    使用mock或fake环境,可以不与真实的环境同步。

小型测试带来优秀的代码质量、良好的异常处理、优雅的错误报告;大中型测试会带来整体产品质量和数据验证。

检验一个项目里小型测试、中型测试和大型测试之间的比率是否健康,一个好办法是使用代码覆盖率。测试代码覆盖率可以针对小型测试、中大型测试分别单独产生报告。覆盖率报告会针对不同的项目展示一个可被接受的覆盖率结果。如果中大型测试只有20%的代码覆盖率,而小型测试有近100%的覆盖率,则说明这个项目缺乏端到端的功能验证。如果结果数字反过来了,则说明这个项目很难去做升级扩展和维护,由于小型测试较少,就需要大量的时间消耗在底层代码调试查错上。

Google有许多不同类型的项目,这些项目对测试的需求也不同,小型测试、中型测试和大型测试之间的比例随着项目团队的不同而不同。这个比例并不是固定的,总体上有一个经验法则,即70/20/10原则:70%是小型测试,20%是中型测试,10%是大型测试。如果一个项目是面向用户的,拥有较高的集成度,或者用户接口比较复杂,他们就应该有更多的中型和大型测试;如果是基础平台或者面向数据的项目,例如索引或网络爬虫,则最好有大量的小型测试,中型测试和大型测试的数量要求会少很多。

另外有一个用来监视测试覆盖率的内部工具是Harvester。Harvester是一个可视化的工具,可以记录所有项目的CL历史,并以图形化的方式展示,例如测试代码和CL中新增代码的比率、代码变更的多少、按时间的变化频率、按照开发人员的变化次数,等等。这些图形的目的是展示随着时间的变化,测试的变化趋势是怎样的。

  • 测试运行要求
1
2
    每个测试和其他测试之间都是独立的,使它们就能够以任意顺序来执行。
    测试不做任何数据持久化方面的工作。在这些测试用例离开测试环境的时候,要保证测试环境的状态与测试用例开始执行之前的状态是一样的。

对于冲突:

1
2
3
    两个测试都要绑定同一个端口,用以接收来自网络的数据。
    两个测试需要在同一个路径下创建相同的目录。
    一个测试希望创建并使用一个数据库表,而另外一个测试想删除这个数据库表。

解决方案

1
2
3
    在测试执行系统中,让每个测试用例获取一个未被使用的端口,并让被测系统动态地绑定到这个端口上。
    在测试执行之前,为每一个测试用例在临时目录下创建目录和文件,并使用独一无二的目录名。
    每个测试运行在自己的数据库实例之上,使用与环境隔离的目录和端口。这些都由测试执行系统来控制。

Google全力维护其测试执行系统,甚至文档也非常详尽。这些文档存放在Google的“测试百科全书”中,这里有对其运行使用的资源所做的最终解释。“测试百科全书”有点像IEEE RFC(译注:IEEE定义的正式标准,RFC是Request for Comment的简写),明确使用“必须”或“应该”这样的字样,并在其中详细解释了角色、测试用例职责、测试执行者、集群系统、运行时刻的libc、文件系统等。

构建系统能定位到错误由哪个提交引起,同时还保存了构建依赖图。

测试认证

招聘到技术能力强的测试人员只是刚刚开始的第一步,我们依然需要开发人员参与进来一起做测试。其中我们使用的一个关键方法就是被称为“测试认证”。

测试认证级别摘要

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
级别1

    使用测试覆盖率工具。
    使用持续集成。
    测试分级为小型、中型、大型。
    明确标记哪些测试是非确定性的测试。
    创建冒烟测试集合。

级别2

    如果有测试运行结果为红色就不会做发布。
    在每次代码提交之前都要求通过冒烟测试。
    各种类型测试的整体增量覆盖率要大于50%
    小型测试的增量覆盖率要大于10%
    每一个功能特性至少有一个与之对应的集成测试用例。

级别3

    所有重要的代码变更都要经过测试。
    小型测试的增量覆盖率要大于50%
    新增的重要功能都要经过集成测试的验证。

级别4

    在提交任何新代码之前都会自动运行冒烟测试。
    冒烟测试必须在30分钟内运行完毕。
    没有不确定性的测试。
    总体测试覆盖率应该不小于40%
    小型测试的代码覆盖率应该不小于25%
    所有重要的功能都应该被集成测试验证到。

级别5

    对每一个重要的缺陷修复都要增加一个测试用例与之对应。
    积极使用可用的代码分析工具。
    总体测试覆盖率不低于60%
    小型测试的代码覆盖率应该不小于40%

最初这个计划在一些测试意识较高的团队中缓慢试水,这些团队成员热衷于改进他们的测试实践。经过在这几个团队的成功试验之后,一个规模更大的、公司级别的认证竞赛开始推行起来了,然后在新加入的团队中再推行这个计划就变得容易的多。

1
2
3
4
    开发团队得到许多优秀测试人员的关注,这些测试人员一般都报名成为测试认证教练。在一个测试资源稀缺的文化氛围里,注册参加这个项目会吸引到比一般团队更多的测试人员的加入。
    他们获得专家的指导,并学习到如何更好地编写小型测试。
    他们知道哪个团队在测试上做的比较好,并向这个团队学习。
    他们能够向其他的认证级别较低的团队进行炫耀。

经过公司级别的推进,绝大多数团队都在不断向前进步,并意识到这个计划的重要性。一些在这个计划中表现不错的开发总监会得到工程生产力团队的优秀反馈,而嘲笑这个计划的团队也会置自身于危险之中。换句话说,在一个测试资源相对稀缺的公司里,哪个团队会舍得与工程生产力团队疏远呢?但并非哪里都是鲜花与掌声,让运行这个计划的负责人来给我们讲述完整的故事吧。

试点团队::① 足够感兴趣;② 没有太多的冗余代码;③ 在团队中有一个测试战神(对测试足够的了解的人)。

我们宣布测试认证计划“正式启动”的时候,有15个试点团队在这个计划的不同级别上运行着。在正式宣布之前,我们在山景城、纽约和其他地点的所有办公大楼上张贴“神秘的测试认证”的大海报,每个海报上用图片印着各个试点团队名字,使用的是内部项目名称,如Rubix、Bounty、Mondrian和Red Tape。海报上唯一的文字是“未来就是现在”和“至关重要,莫被遗弃”,还有一个链接。从喜爱猜谜的Google同事那里,我们得到了大量点击访问,多数人想去一探究竟,还有一些人想去验证自己的猜测是否正确。同时我们也使用ToTT来宣传这个新计划,并把读者指引到他们能够得到信息的地方。这是一个信息闪电战。

宣传网站上有一些信息,包括为什么测试认证对于团队很重要,以及用户可以得到怎样的帮助。里面强调指出,参与团队会从一个很大的测试专家社区里得到一个测试认证教练,同时还会得到两个礼物——一个表示构建状态的发光魔法球,可以告诉团队他们的(一般是新的)持续集成是通过(绿色)还是失败(红色);另外一个是一个漂亮的星球大战土豆头工具包。这个被称为达斯土豆工具包里有三个逐渐变大的格子,每当团队达到新的测试认证级别时我们都会给予奖励。各个团队展示他们的魔法球和土豆头,为这个计划吸引来更多好奇的团队和带来更好的口碑。

测试圈子里的成员是这个项目的第一批教练和发言人。随着越来越多团队的加入,有许多热情的工程师帮助造势,自己也成为其他团队的教练。

每次我们尝试说服更多的团队加入这个计划的时候,都会与他们逐一讨论理由和原因。一些团队是由于你能使他们信服每一个级别和教练都会帮助团队在这个领域有所提高而加入的。一些团队认为他们会有所改善,并坚信这种“官方”级别评定会使他们因为当前正在做的工作得到好评。另外的一些团队,他们本身的测试成熟度已经很高了,但加入这个计划,会给其他的团队发出一种信号,表示他们已经很重视测试了。

  • SET的招聘(暂略)

测试工程师

软件测试开发工程师(SET)负责可测试性和测试自动化体系的长期有效性。测试工程师(Test Engineer,后文简写TE)的职责与之有所不同,TE的重点在于评估对用户的影响以及软件产品整体目标上的风险。与Google的其他大多数技术岗位一样,TE的工作涉及到一些编程,但编程只是一小部分,实际上,在所有工程师中他们的职责范围堪称最广。TE对产品的贡献很大,但他们承担的很多任务不需要编程(注:这只是通常的说法。许多TE所从事的工作与SET非常类似,需要编写大量的代码,而另外一些TE的职责更类似发布工程师,只需要编写很少量的代码)。

Google的TE综合了开发者仰慕的技术能力和以用户为中心检查软件质量而对开发者产生一定制约的能力。

TE的职位描述是最难定义的,因为其职责范围很广而且不确定。人们期望TE在各种各样的构建物的完成、集成、最终形成完整的产品过程中监督所有产物的质量。因此,大多数的TE都会从事一些基础技术层的、需要另外一种视角和较强的专业技术能力的工作。这一切都与风险有关:TE以对某种特定的产品最合适的方式发现软件中风险最大的地方并尝试减少或消除它。如果需要做SET的工作,TE就去做;如果需要代码审查,那就只管去做。如果缺少测试工具,那就花一些时间在上面。

接下来,同一个人还会在项目的其他时段去领导探索式测试,或者管理内部试用版(或beta版)的测试工作。在不同的项目阶段,SET和TE的重点不同,早期的工作涉及到更多的面向SET的任务,而项目后期才是面向TE的任务。还有一些情况是TE的个人选择,他们可以在不同的角色间切换。但凡事没有绝对,我们在下面所做的描述,只是代表了理想的情况。

在研发的早期阶段,功能还在不断变化,最终功能列表和范畴还没有确定,TE通常没有太多的工作可做。

当TE进入产品的时候,并不需要从零开始。SWE和SET已经在测试技术和质量方面做了大量的工作,可以作为TE的起点。TE在进入产品时,需要考虑以下一些问题。

  • 当前软件的薄弱点在哪里?
  • 有没有安全、隐私、性能、可靠性、可用性、兼容性、全球化和其他方面的问题?
  • 主要用户场景是否功能正常?对于全世界不同国家的用户都是这样么?
  • 这个产品能与其他产品(软件和硬件)互操作吗?
  • 当发生问题的时候,是否容易诊断问题所在?

当然这只是一个不完全列表。所有这些加起来,构成发布待评估软件的风险概要。TE并不需要自己去解决所有这些问题,但必须保证这些问题被解决掉,他们可以请其他人帮忙评估还有多少工作需要去做。TE的根本使命是保护用户和业务的利益,使之不受到糟糕的设计、令人困惑的用户体验、功能bug、安全和隐私等问题的困扰。在Google,TE是一个团队中全职地负责从整体角度发现产品或服务弱点的唯一角色。因此,与SET相比,TE的工作并不是那么确定。TE会介入项目的各个阶段:从产品的构思阶段到第8个版本,甚至是照看一个已经下线的项目。一个TE同时参与几个项目也很常见,尤其是那些具备安全、隐私或全球化等专门技能的TE。

这个角色需要敏锐的洞察力和领导力,因此很多Google的高级测试经理们都来自于TE。

TE的工作经常需要去打破常规流程。TE可以在任何时间进入项目,必须迅速评估项目、代码、设计和用户的当前状态,然后决定首要的关注点。如果项目刚刚开始,测试计划是第一优先级。有时,TE在产品后期被拉进来帮助评估项目是否可以发布,或者在beta版本发布之前确认还有哪些主要的问题。当TE进入了一个新被收购的应用或缺少相关应用经验的时候,他们经常会先去做一些不怎么需要计划的探索式测试。有时,项目已经很久没有发布了,只是需要去做一些修饰、安全补丁或界面更新,这需要迥然不同的方法。

在Google,TE需要在不同的项目中做不同的事情。我们经常将TE的工作描述为"从中间开始(starting in the middle)",因为TE必须保持足够的灵活,能够迅速融入一个产品团队的文化和现状。如果做测试计划已经来不及了,那就干脆不做了。如果一个项目最需要的是测试,那就做一个简单够用的指导性计划。一些测试教条所倡导的从头就介入的模式,在Google并不适用。

下面是我们关于TE职责的一般性描述。 * 测试计划和风险分析; * 评审需求、设计、代码和测试; * 探索式测试; * 用户场景; * 编写测试用例; * 执行测试用例; * 众包(译注:crowdsourcing,是互联网带来的新的生产组织形式。一个公司或机构把过去由员工执行的工作任务,以自由自愿的形式外包给非特定的(通常是大型的)大众网络的做法); * 使用统计; * 用户反馈。

测试人员要处理的是真正的文档和其他临时性的事物。在项目的早期阶段,测试人员编写测试计划;然后,他们创建和执行测试用例,编写bug报告;接下来是准备覆盖度报告,收集用户满意度和软件质量数据。在软件成功发布(或失败)之后,很少有人会问及测试产物是什么。如果软件深受人们喜爱,大家就会认为测试所作所为是理所应当的;如果软件很糟糕,人们可能就会质疑测试工作。但其实也没人真正想去了解测试到底做了什么。

测试计划是最早出现、最先被遗忘的测试产物。

下面是我们希望测试计划具有的一些特性。

  • 及时地更新。
  • 描述了软件的目标和卖点。
  • 描述了软件的结构、各种组件和功能特性的名称。
  • 描述了软件的功能和操作简介。

从纯粹测试的角度看,我们担心的是测试计划的投入和价值产出是否匹配。

  • 不必花过多的时间去撰写,必须随时可以被修改。
  • 应该描述必测点。
  • 应该能在测试中提供有用的信息,从而帮助确定进展以及覆盖率上的不足。

ACC(Attribute Component Capability,即特质、组件、能力。这是一种测试计划的替代方法,参见http://googletesting.blogspot.com/2011/10/google-test-analytics-now-in-open.html)可以做测试计划的替代。

特质是系统的形容词,代表了产品的品质和特色,是区别于竞争对手的关键。

源码工具:一系列用于简化创建工作环境、提交代码变更、代码风格检查的工具。可以用工具浏览数亿万行的代码,发现并预防重复的代码。还有用于建立大规模索引和代码重构的工具。

开发工具:集成开的发环境的一些插件,让其他各种工具适应google的代码并连接后端的云服务。代码审查工具,通过在审查阶段嵌入相关的信号,来快速完成高质量的代码审查。

构建框架:构建系统支持自动式,交互式,可以把原本需要数小时的任务缩短到数秒

测试基础架构:规模化的持续集成,开发人员的每次代码提交都会引发自动测试;另一方面是规模化的web测试,每个google产品都会启动数十万个浏览器会话,对各种不同的浏览器平台组合进行测试。

本地化工具
度量,可视化和报表:管理所有产品的bug,跟踪所有研发活动中工程师的各项指标。


技能、稀缺性、自动化和迭代集成。

参考资料

  • http://www.epubit.com.cn/book/onlinechapter/15909
  • http://www.51testing.com/html/00/category-catid-200.html
  • https://www.amazon.cn/Google%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95%E4%B9%8B%E9%81%93-%E6%83%A0%E7%89%B9%E5%85%8B/dp/B00FH36R6G/ref=sr_1_1?ie=UTF8&qid=1473818603&sr=8-1&keywords=%E8%B0%B7%E6%AD%8C%E6%B5%8B%E8%AF%95%E4%B9%8B%E9%81%93

links