谷歌是如何做软件测试的

发表于:2016-06-28来源:welkinwalker的遐想作者:welkinwalker的遐想点击数: 标签:谷歌
本文作者 James Whittaker, 前微软架构师,是“ How to Break Software ”系列图书中好几部书的作者,现任Google测试工程主管,最近他写了一系列的关于谷歌如何测试软件的文章,本文为其系列的
(一)
google在公司的大层面组织上有很多的Focus Area,search, apps, ads, mobile, operating system这些都是不同的FA。测试隶属于其中的一个FA,这个FA的名字叫Engineering Productivity。这个FA由很多纵向的横向的学科构成,测试是其中最大的一个学科。Eng Prod这个FA由下面的部分组成:
  1. product team。公司内部使用的工具还有开源工具都由它来生产,这些都是提高生产率的工具,包括代码分析工具、IDE、case管理工具、自动化测试工具、编译工具、编译系统、代码版本控制工具、code review工具、bug database。
  2. services team。给上面的product team的各种工具的提供使用经验,包括工具本身、文档、测试、发布管理、培训等,这些经验涵盖可靠性、安全性、国际化等方面。每个FA都共享这些经验。
  3. Embedded engineers。被按照具体的需求外借到不同的产品团队(FA)。有的呆在同一个产品团队好多年,有的则轮换多个产品团队。google鼓励工程师做这种轮换,因为这样可以保持新鲜感、浓厚的兴趣、立场的客观。测试工程也一样,不过这种轮换的平率则取决于个人。有测试工程师在Chrome上做了好几年有的只有18个月。在新鲜感和领域知识中间做好一个平衡是作为一个测试人员要特别关注的事情。

从上面的表述可以看出来,测试工程师在google其实就是Eng Prod这个部门下面的Embedded engineers,他们要向Eng Prod的汇报,但是却工作生活在别的产品团队,比如Search、gmail等。可是他们不向产品团队的人汇报,这种“分开汇报”方式的好处是他提供了一个forum,可以让测试工程师分享他们的知识。在 Eng Prod 中Good testing ideas可以很容易产生。

把项目线和汇报线分开有它的挑战。目前最大的挑战是:测试是(产品团队的)外部资源。产品团队不能指望测试工程师保证质量,而是要自己来确保。在Google产品质量是产品团队自己的事情,不是测试工程师的事情。每个开发工程师要自己来做测试。测试工程师的任务是确保他们有测试的自动化框架,另外还要建立一种有利于“自依赖”(开发依赖自己的测试来保证质量)的流程。总结起来就是:测试工程师让开发工程师更舒服的来测试自己的代码。

我(James)之所以喜欢这种方式,在于他把开发和测试人员放到了相同的位置(不存在上下游关系)。他让测试开发成为伙伴,并且把最大的质量任务给了开发,致力于让产品正确运行的开发自己。另外一个副效应就是做到一个很高的开发测试比。产品团队应当以此为荣!

上面这种策略的弊病在于开发通常自己不能确保自己的质量,在Google我们解决这个问题的方法是建立两种类型的测试角色,来解决两种完全不同的测试问题,这个划分是:

(二)

  1. SWE or Software Engineer。写功能代码,并发布到终端用户。他们写设计文档、设计数据结构,并且花大量的时间write和review代码。他们要写大量的测试,包括测试驱动设计、单元测试、参与小、中、大的测试。他们对任何他们碰过的代码质量负责,包括写的、修复的、修改的
  2. SET or Software Engineer in Test。也是一个开发者,但是他的侧重点在于可测性。他们review设计,并且审阅代码的质量、风险。他们重构代码并且使他们具备更好的可测性。他们编写单元测试框架、自动化测试框架。从写代码这个角度来看,他们是SWE的伙伴,但是他们关心的是如何从代码层面上提高质量、测试覆盖率,而不是添加功能和提高性能
  3. TE or Test Engineer。他们是SET的补充(上文提到的“两种类型的测试角色”的后者)。相比开发,他们更侧重测试(注意不是说他们不写代码)。他们要花大量的时间写代码,这些代码一般会是:自动化测试脚本、驱动、模拟用户场景的代码。他们同样要组织好SWE和TE的测试产出,理解他们的测试结果,并且一起运行他们,特别是到了项目的后期当发布的压力变大的时候。TE是产品专家、质量顾问和风险分析师。
(下面的这几段分析比较深入)
从质量的角度来看,SWE要分别对产品的功能和他的质量负责。他们要做到容错的设计、故障恢复、测试驱动开发、单元测试,并且还要和在SET的协助下编写代码测试他们的功能。(feature就是用户可以用到的功能,而这里作者列举的容错等都算是产品的质量维度。)
 
SET也是开发者,他们提供的产品功能(feature)是供测试使用的。例如:一个通过使用“待实现代码”(原文是stubs,我理解是code stub)模拟依赖的框架,从而能把新开发的代码分离出系统来测试(其实就是mock框架,gmock的功能)。简言之,SET编写的代码是为了能让SWE更方便的测试自己的功能。真正的测试工作是由SWE来做的。SET只确保SWE完成的功能是可测试的,SWE自己来完成写test case的工作。SET的关注的是SWE。具体功能的质量是最终目标,怎么让SWE能够容易的测试自己的代码是SET首要侧重点。这里有一个明显的质量漏洞,功能的使用者——终端用户呢?
 
在Google用户体验的测试是TE的事情。假设SWE和SET做的模块、功能测试都足够充分了,后面的任务就是这些程序和数据能不能有效的来满足用户的需求了。TE在这里是一个double-check。任何明显的bug说明SWE的测试不充分马虎。当这种bug难觅的时候,TE就可以转向他们最重要的任务了,这些任务有:确保软件完成了用户场景,性能上、安全上、国际化上都OK。TE要做很多的测试和测试协调工作,这种协调工作牵扯的角色很多,有:TE, contract testers, crowd sourced testers, dog fooders, beta users, early adopters(这里不直译了,contract表示契约,可以当做需求来理解;sourced指的是外包,可见google也有外包的产品;dog fooders是说公司的产品都要在公司内部先开展试用,公司鼓励每个人都试用自己的产品,这就叫eating your own dog food,dog fooder值得就是使用过自己产品的员工;beta用户是公测用户;early adopter就是尝鲜者,可以理解为发布后首先使用的人员。总之就是从产品)。他们要跟各种团体沟通的事情很多,包括:设计上固有的风险、功能的复杂性、避免故障的方法。一旦当TE介入,他们的工作没有尽头。(感觉TE更像是涵盖了产品的运营任务,不是运维哦)。

(三)
首先明确,质量是测试不出来的。有个比喻很有意思:不能通过反复测试来提高质量,这就好像你不能通过反复称重来减肥一样。
在Google,质量不等于测试,有些公司则不然。“质量不能通过测试而植入”这个是老生常谈了,我们不必去怀疑他的正确性。从手机到软件,如果你没有在一开始就把它构建好,那么他永远不会正确的工作。如果你不知道一开始不重视质量的代价,那么去问问陷入“召回门”的汽车厂吧。
 
“质量不能通过测试而植入”这话本身并不通俗,它也不是一个准确的描述。可是为什么这么说?因为显然,如果没有测试你不可能开发出什么高质量的东西。对啊,如果你不测试,你怎么知道你开发出来的东西就是高质量的呢?
 
解决这个问题的简单方法就是不要把开发和测试当做两个单独的学科。测试和开发应该是起头并进的——写一点、测一点;写一坨,测一坨。更好的方法是,在你写代码的时候就准备如何测试,甚至是在写代码之前。测试并不是一类单独实践艺术,他是开发过程的一个部分。质量不等于测试,好的质量是通过把开发和测试有机粘合在一起来实现的,以致你不能区分出对方。
 
上面的描述就是我们在Google的目标:合并开发和测试直到你不能在没有其中一个的时候完成另外一个。构建一尺,测试一尺;构建一丈,测试一丈。这里的关键问题是:谁来做这个测试。鉴于Google中全职的测试工程师从比例上来讲少得可怜,那么答案自然是开发工程师。有谁比代码的编写者自己来做测试更合适呢?有谁比他自己来发现bug更合适呢?谁会对能在第一时间避免bug更振奋呢?Google之所以能够在测试工程师这么少的情况下还能这么得瑟,就是因为开发对质量负责。事实上,坚持保留一个大量测试的团队通常被认为是在犯错。保有一个大型测试团队是“开发工作/测试工作”严重失衡的标志,增加更多的专职测试人员是不会解决问题的。
 
换句话说:质量保证是重预防而不是重检测。质量保证是一个开发问题,而不是一个测试问题。通过“把测试签入到开发中”,我们建立了一个“超增量”的过程,能做到“当一个改动导致错误太多,那么就会自动回滚”。我们不单是避免了很多用户问题,而且大幅降低了用来确保“没有recall-class bug”的测试工程师的数量。在Google,测试的目的就是发现这种“避免问题”的方式是不是做的足够好。TE时刻会关注SWE-SET的这种组合是不是能达到“避免用户问题”的目的,一旦流程出现了问题TE就会发出警告。
 
团队的各种迹象都能体现这种测试和开发的融合,从code review中的“你的测试呢”到厕所中大幅海报提醒开发者采纳最佳的测试实践——臭名昭著的“Testing On The Toilet”提示。测试必须成为开发不可回避的一面,开发和测试的联姻的那天就是质量能够得到保证的那天。SWE是测试工程师,SET是测试工程师,TE也是测试工程师。
 
如果你的组织也在做这种融合,何不分享你的成功和挑战呢?如果你们的组织不在尝试这种融合,那么这是你们组织可以尝试的一个变化:让开发工程师全权承担起质量的任务。有句谚语说得好chickens are happy to contribute to a bacon and egg breakfast but the pig is fully committed(意思是说,鸡愿意为“鸡蛋咸肉”早餐贡献一份力量,而猪不愿意。因为鸡只是提供了鸡蛋,自己毫发无损,而猪却把自己都押上了。其实就是说要把开发置于死地而后生,让他们自己测)。这样一来你如果发现你的开发工程师发出猪的叫声这就ok了,如果他们发出鸡的叫声那就有问题了。
 
(四)
 
匍匐、步行、跑步向前
 
之所以Google的测试人员相比其他公司非常少但是却还可以保持较好的质量,一个首要的原因就是:我们很少试图一次性发布很多功能。事实上,我们做的恰恰相反:首先构建一个产品的核心部分,并在他能惠及尽量一个大群体客户的时候就发布他,然后收集反馈意见并且迭代改进。我们就是这么来开发Gmail的,以至于beta标签在这个产品上呆了4年。这个标签也让我们的用户知道这是一个在不断完善的产品。直到我们能够保证用户email数据达到99.99%的可用性的时候我们才把这个beta标签取消。看到了没,质量的改善贯穿整个工作当中。
 
通过这个过程(确保质量)并不是一个很冒险的过程。事实上,为了能到达beta阶段,一个产品必须经过很多的其他阶段并证明它的价值。比如Chrome(我才开始来的时候在这个产品上做了2年),我们会依据我们在产品上的信心和反馈的程度不同来确定我们要引入多少个阶段。例如:
 
Canary Channel。这个阶段适用于那些不适合发布的代码。就好像是煤矿中的金丝雀,如果它不能活下来,我们还要努力。这个阶段构建的程序只能提供给那些具有超强耐受度的用户,让他们拿它来做实验,不指望它能完成真正的工作。
 
Dev Chanel。提供给开发者在日常工作中来使用。我们鼓励产品线上的每个工程师都把它拿来并应用到真正的工作当中。
 
Test Channel。这个阶段构建好的程序会提供给公司内部所有的员工来使用,如果那性能也足够好的话他也代表了一个准Beta版。
 
The Beta Channel or Release Channel。这个阶段构建出来的程序将成为首次对外公开的程序。一个产品只有在上面的各阶段呆够了足够的时间后,他才能最终赢得一个在“枪林弹雨搬的测试和真实使用”下露面的机会。
 
这种“匍匐、不行、跑步向前”的方式让我们能够尽早的在我们的产品上测试、做实验,并从用户真实使用和每个阶段的自动化测试中收集各种反馈信息。
 
(五)
在测试层级的划分方面我们没有采用代码级、集成级、系统级这样的分类方式,取而代之的小测试、中测试、大测试,这样做是为了强调测试的规模而不是外在形式。小测试只会覆盖一小撮代码,然后是中、大测试。不论是SWE、SET、还是TE,都会执行这三类的测试,可能是通过自动化的方式开展也可能是手工的方式。
 
小测试通常(但不总是)通过自动化的方式来运行,它只会运行一个函数或一个模块的代码。通常他们都是由SWE或SET来完成编写的,他们的运行可能会需要mock环境,TE通常会在需要诊断一个具体问题的时候直接拿过来运行。对于小测试来说他们关注的是些典型的问题,如数据损坏、错误条件或一个错误。一个小测试要回答的问题是:代码是不是完成了它应有的功能。
 
中测试可以被自动化也可以是手工的,他们通常包含两个或多个功能,并特别的关注功能之间的交互。曾经有SET把这种测试描述成“测试一个功能和它的近邻”。对于一个产品的周期中,在单独的各功能的实现过程这个阶段,SET会驱动这种测试的开发(为了让SWE能方便的编写“中测试”做准备);这种测试的大量编写、调试、维护工作则是SWE的事情。如果测试失败,工程师会自己去搞定它。在开发阶段的后期,TE会手工执行(当这个测试不容易自动化,或者自动化的代价太大时)或自动化的执行他们。中测试要回答的问题是一组邻居功能是不是能完成他们应有交互任务。

Large Tests。大测试覆盖三个或更多的功能,并且要尽可能的代表真实的用户场景。怎么来对一个集成了所有功能的场景来设计case这个或许有疑问,大师大测试都是结果导向的,比如软件是不是能有满足用户的预期?三个角色都会参与大测试的编写,从自动化测试到探索性测试所有的事情都要完成。大测试要回答的问题是:产品是不是完成了用户预期的功能。
 
语言上的称谓具并不重要,重要的是Google的测试人员有这么个共同语言并且知道他们每个测试代表的范围。当一些激进测试人员谈论第四类测试的时候,他们值得实际上是一种能够涵盖所有功能的系统测试,而且这个测试要跑很长的时间。
 
我们要测试什么以及测试多少,这后面的驱动力量是动态变化的,而且产品之间也有不同。Google更倾向于频繁的发布,把产品推向用户,然后从用户收集反馈并迭代。基本想法就是一旦我们开发了一个产品或一个现有产品的新功能,就立即把他推向用户,这样用户就能第一时间从中受益。这就需要我们把用户和外部开发者在前期就纳入进来,这样我们就能清楚我们做的东西是不是已经达到目的了。

最后,对自动化和手工测试的混合来说,自动化毫无疑问是最推崇的,不管是在大中小的测试中。如果它能够被自动化,并且过程中不需要人的智慧和灵感的介入,它理所当然要被自动化。只有在需要人来做判断的情况下才考虑手工来做,比如:UI的美观性、暴露一些数据会构成隐私问题。
 
尽管说了这么多,你必须要晓得Google要做大量的手工测试的,可能是写脚本方式也可能是探索性方式,但即便如此这些测试也是在自动化的监视下完成的——工业化的脚本录制技术可以把手工测试转换成自动化测试脚本,这些脚本就可以在每次构建后来执行,以此来最小化回归测试的开销,并且把人力集中到那些新问题上。我们也自动化了bug的提交和手工测试任务指派。比如:如果有个自动化测试失败了,系统会确定最后的代码更改位置(这里最可能是出现问题的地方),然后发邮件给其作者并记录一个bug。The ongoing effort to automate to within the “last inch of the human mind” is currently the design spec for the next generation of test engineering tools Google is building.(within在这里应做动词“把XX融入”来讲,大概意思是:正在努力的方向是“自动化人类的每个想法”,也就是人只要一想出来怎么测试,然后就可以立即把这个想法自动化,这是Google在建设的下一代测试工具)
 
下一篇将是关于SET的工作的。
 
(六)SET的工作方式
 
SET是专注于测试的软件工程师。他们是乐于编写测试功能的软件工程师。首先说,SET是开发者,在招聘的时候我们就会说这个工作是100%的编码工作,晋升阶梯中的描述也是如此。当我们面试SET的时候,对于写代码能力的要求跟SWE几近相同,之外我们还会强调SET要懂得如何测试他们自己的代码。换句话说,SWE和SET都要回答编码问题,但是SET要面对更多的测试问题。
 
你应该猜到了,这个角色很难做,而且造成Google的SET数量很少的原因,可能完全不是因为我们有针对生产率的一套魔法公式,而在于:把我们的工程实践应用到SET技能的人真的很难找。我们优化这项重要的工作并且围绕这些人建立流程。
 
SET不会参加到前期的设计当中,之所以如此不是我们有一这样的,这是由我们的项目诞生方式来决定的。一个典型的新项目诞生情况就是:员工的20%非正式时间的投入变成了Google自己品牌的项目。Gmail和Chrome OS都是这样在一开始没有自上而下的一个任务指派,但是最终成长为由很多开发和测试工程师组成的团队来共同构建的产品。在这样的一种情况下,一开始的开发是不在乎质量的,其目的在于验证一个概念,或者是专注可扩展性、性能等一些在质量成为问题之前必须正确的东西。简单来说,如果你不能够使你的web service能够有扩展性,那么测试问题就显然不是一个最大问题(扩展性才是)。

一旦确定一个产品能做、要做的时候,那么开发团队就要开始寻求测试的介入了。
 
关于这个流程你可以这么来想象:某人有了一个想法,首先要对其思考,然后写一下实验代码,去征求其他人的想法,再写代码改进,找其他人一起来做,再写更多的代码,之后他们意识到他们的这个想法非常有价值,进而写更多的代码来实现他们的想法并把实现出来的效果给更多的人看,并收集反馈,这个时候这个项目其实就已经放入了Google的项目数据库了,项目也变成了真正的项目。一个项目在没到达这个阶段前,是不会有测试人员介入的。
 
所有的项目都会有测试人员么?默认不会。小项目还有那些只对有限的一些用户有用的项目都是由开发那些项目的工程师自己来测试的。其他那些对用户和公司更具风险的才会引起测试的注意。
 
开发团队任务是向测试人员寻求帮助,向测试人员证明他们的项目是多么的刺激和充满潜力。开发的负责人向测试负责人讲解项目的想法、进展和发布计划,测试负责人则要就“测试工作如何分担”“SWE参与测试”“预期的单元测试级别”“发布中的责任如何分担”等问题展开商讨。SET可以在项目一开始不介入,但是一旦正式立项,在项目如何来实施这个问题上,则有巨大的影响力。

当我说“testing”这个词的时候,我指的不单单是运行代码,覆盖代码路径。测试人员不一定从一开始就介入,但测试(testing)却是(作者的意思是测试其实是无处不在,从项目一开始的各种工作都会与测试有多多少少的联系,比如后面说的提交代码,这里testing如果换成QA可能更有利于国内的一些业内人来理解)。事实上,(请注意)一个开发即便是在提交代码的时候都会感觉到SET的存在。
 
(七)TE的工作
 
相比SWE和SET,TE在Google是一类新职位。因此,这个职位的角色定义还在进行中。当前Google的这代TE正在为这个职位开辟一条道路,这样就能更好的指导后面招聘进来的TE来开展工作。我们这里描述的是在Google新兴起来的一个最好过程(It is the process that is emerging as the best within Google that we present here)。
 
并不是每个项目都需要TE。那些在产品初期的实验性尝试,没有良好定义的任务或用户场景的项目势必不会引起很TE的注意。如果一个产品看起来没什么希望(作为一个概念他不能通过审核)或者尚未能吸引用户注意或者没有清晰的功能定义(原文是have a well defined set of features,怀疑是作者落下了not,从上下文判断应该是not have a well defined set of features),测试工作就应该是开发他的人自己来做。
 
即便对于一个确定要对外发布的产品,TE在开发阶段的初期也没什么事情可做,因为在这些阶段功能在不断变动,最终的功能和边界也不确定。在测试方面太早的投入过多就会导致很多工作被丢弃(因为产品的功能可能后来就变了)。同理,一开始做测试计划需要的TE数量比后期做探索性测试TE数量少很多,因为,到了后期产品几近成型,这个时候寻找遗漏bug显得非常紧急。
 
在一个项目中配备TE跟风险和ROI息息相关。对于客户和企业来说这意味着要花更多的测试精力同时需要更多TE。但是这种努力需要和回报成比例。我们需要正确数量的TE在正确的时间并起到正确的作用。

一旦介入,TE并不是一切从头开始来。因为已经有SWE和SET做了大量的测试工程化和面向质量的工作,这些工作都是TE后续工作的基础。TE的初期介入要做的事情有:
  • 软件什么地方最薄弱?
  • 安全、隐私、性能、可靠性方面都有哪些考量?
  • 对于国际的各种用户,是不是所有的首要用户场景都能按照既定的方式工作?
  • 产品会和其他产品(包括硬件和软件)交互吗?
  • 一旦出了问题,问题的诊断是不是容易做到?
所有的这些都在质疑要发布软件的风险轮廓。TE并不需要亲自做所有的这些工作,但是他要确保这些事情都做了,并利用别人的工作来评估是不是还有更多需要做的事情。总的来说,TE对企业的价值体现在他保护用户和公司免受一系列问题的侵扰,比如坏的设计、令人困惑的UI、功能bug、安全和隐私问题等。在Google,TE是一个团队中唯一个全职的从整体上来关注产品和服务弱点的人。因此,TE的职业路线相比SET来说远没有规则和格式可循。在项目的任何阶段都有可能需要TE的协助,从创意阶段到好几个版本发布,甚至是监视一些过时的、封存的项目。通常,一个TE会同时服务于多个项目,特别是那些有特殊技术(比如安全)TE。
 
显然,不同项目中TE要做的事情可能差别蛮大的。有些TE要花大量的时间写代码,有点像SET,只不过重心是关注终端用户的使用场景。还有些TE针对现有的代码和设计从中寻找故障失败模式和导致故障的原因,这种情况下,TE可能会修改代码但是不会从头写。TE在做测试计划的时候必须更系统、全面,并在真正使用(系统)和系统经验方面兼顾完整性。TE擅长处理需求中的模糊性,并且善于推理和表达逻辑问题。
 
成功的TE在敏感的、有时候个性很强开发、产品团队之间游走过程中完整所有任务。每当他发现漏洞,TE高兴的攻破系统,并驱动SWE、PM、SET去解决这些问题。

这样的一个职位描述可能让他的前景有点吓人,他需要各种知识的融合包括技术方面的、领导力方面的、产品理解方面的,如果没有合适的指导,这个职位很可能会失败。但在Google,强大的TE社区已经出现来对付这种情况。在所有的职位中,TE可能是最注重支持(peer supported)的这么一个角色,做好TE这个职位需要的洞察力和领导力通常意味着很多的测试经理都是从TE这个职位里走出来的。
 
Google的TE工作的流动性掩盖了各种程式化的介入过程(言外之意就是TE的工作很灵活不确定,原文是:belies any prescriptive process for engagement)。TE可以在任何时间点介入项目,并且必须要迅速的评估项目的状态、代码、设计和用户,还要确定什么是首要关注的东西。如果项目是刚开始启动,测试计划通常首要考虑的事情。有的时候TE会在项目的末尾阶段被拉来评估项目是不是适合发布,或者一个早期的Beta版被放出的话会不会有问题。如果TE来到的是一个新应用或者是一个他之前没有任何经验的应用,他们就会从一些探索性测试开始做起,基本没有什么规划。还有的情况是项目很久没有发布了仅需要一些(安全)修复,或者界面交互的调整,这对TE来说就需要一些不同的策略。总之一句话,在Google中TE的工作没有定式可循。

原文转自:http://www.cnblogs.com/welkinwalker/archive/2012/04/18/2455018.html