快乐学习
前程无忧、中华英才非你莫属!

Tester----Google软件测试之道

小编的感悟:
今天在QQ上我的一个朋友,在问我,测试人员地位低怎么办,我说了,如果公司目前现状如此,那么的产品就不会好到哪去,如果你真想去,那只能通过自己的努力改变公司的文化,改变他们公司所有开发,产品经理,boss的思维怪圈! 这里是“同乐学堂”,如果你有想法,尽管去学,去做就是”。
本文会围绕测试角色来讨论,谷歌是怎么对待自己的产品的。
测试角色:TE(基于用户的测试工程师)、SET(测试开发工程师)、SWE(功能开发)
正式开始记笔记:
软件测试团队等于工程生产力,需要一个特种部队的成员来打造一个成功的短小精悍的团队,不要招聘太多测试人员!  这支团队不仅在做好本职工作,还有更重要的任务让头衔没有测试字样的角色可以更好的去做测试!
对于互联网公司,在快速前进中保持高质量是一个永恒的难题,在一家版本快速迭代的公司,开发工程师、产品经理都需要参加测试,以此来提醒——质量是所有人的事情而不只是测试团队的事。
 
快乐阅读,快乐测试,祝愿你总能发现(并修复)bug。
虽然百分百的测试覆盖率听起来很困难,但是这是我们努力的目标,我们并不在乎产品中是否少了一个很酷的功能,与之相比,我们更在乎产品的可靠性和稳定性。
在互联网和软件产业,一切变化都如此迅速,以至于许多最近几年才出版的软件测试方面的书籍都已陈腐过时,打个比方,它们就像讲述水蛭吸血和开颅驱赶恶鬼的外科手术书一样。对付这种书,最好的办法就是直接把它们扔掉,或者做些有益的事情,例如,循环再利用,做出纸尿裤来,以防止流落到容易上当受骗的人之手。
每一行功能代码,写两到三行的单元测试代码,而且这些测试代码和功能代码一样都需要维护,且有着相同的出错概率。而且大家也意识到,仅做单元测试是不够的,仍然需要集成测试、系统测试、用户界面等方面的测试。当真正开始要去做测试的时候,会发现测试工作量变得非常大(且需要很多知识的学习),并要求在很短的时间内完成测试,要以“迅雷不及掩耳”之势完成。我们为什么要在很短的时间内迅速地完成测试呢? 我一直这么认为,对于一个坏点子或考虑欠周的产品,即便再多的测试,也无法把它变成一个成功的产品。但如果测试方法不当,却会扼杀一个本来有机会成功的产品或公司,至少会拖慢这个产品的速度,让竞争对手有机可乘。
有问题是常态,代码质量很糟糕,测试用例很差劲,团队也问题多多。我完全清楚那种被技术质量债压得喘不过气来的感受,在那种状态下,一切创新性的想法都会被遏制,以免不小心破坏了脆弱的产品。如果说我在以往的经历中有所收获的话,那就是经历了各种错误的测试实践。
一个团队能编写出高质量软件的唯一途径是全体成员共同对质量负责,包括产品经理、开发人员、测试人员等所有人
达到此目标的最好方式是使测试人员有能力将测试变成代码库的一个实际功能,而测试功能的地位应该与真实客户看到的任何其他功能同等重要。我所需要的能够实现测试功能的技能,也正是开发人员需要具备的技能。
持续集成,可以使产品一直保持可测试的状态。
 
Google是如何测试的?
随着我在Google工作的时间越来越长,发现Google的各种测试实践的不同之处也越来越多,答案也一直在变化。
质量不等于测试。当你把开发过程和测试放到一起,就像在搅拌机里混合搅拌那样,直到不能区分彼此的时候,你就得到了质量。
在Google,这正是我们的目标,就是把开发过程和测试融合在一起——开发和测试必须同时开展。
 
但这里的关键是由谁来做这些测试呢?
还有谁能比实际写代码的人更适合做测试呢?还有谁能比实际写代码的人更适合去寻找bug呢。
Google能用如此少的专职测试人员的原因,就是开发对质量的负责。如果某个产品出了问题,第一个跳出来的肯定是导致这个问题发生的开发人员,而不是遗漏这个bug的测试人员。
如果一些项目在线上被证实的确是bug重重,它将会被回滚到之前的版本。
 
测试是开发过程中必不可少的一部分,当开发过程和测试一起携手联姻时,即是质量达成之时。
Google的TE会花费大量时间在模拟用户的使用场景和自动化脚本或代码的编写上。同时,他们会把开发工程师和SET编写的测试分门别类地组织起来,分析、解释、测试运行结果,驱动测试执行,特别是在项目的最后阶段,推进产品发布。
把用户放在第一位来思考,代表用户的利益。
资深管理者一般都来自产品经理或开发经理,而不是来自于测试团队。在产品发布时,优先考虑的是功能是否完整和易用性方面是否足够简单,却很少考虑质量。作为同一个团队,测试总是在为开发让路。
一个产品团队不能任意降低测试人员招聘的技术要求,从而雇佣更多的测试人员,然后再让他们做一些简单和琐碎的脏活累活。这些功能相关的脏活累活本应是开发人员的工作,不能简单地扔给倒霉的测试人员。
工程生产力团队会根据不同产品团队的优先级、复杂度,并与其他产品实际比较之后,再来分配测试人员,
在 Google 有一个广泛被接受的做法:对于一个测试人员,如果在某个产品中工作满18个月之后,就可以无理由地自愿转岗到其他产品,当然这个转岗并不是强制的。
由于Google的产品和服务很大程度上有比较强的集成关联关系,测试人员可以很容易地保持相关的专业技能,并在公司范围内的产品之间自由穿梭。
Google 经常在最初的版本里只包含最基本的可用功能,然后在后继的快速迭代的过程中得到内部和外部用户的反馈,而且在每次迭代的过程中都非常注重质量。一个产品在发布给用户使用之前,一般都要经历金丝雀版本、开发版本、测试版本、beta或正式发布版本。
 版本介绍
金丝雀版本:这是每日都要构建的版本,用来排除过滤一些明显不适宜的版本。就像煤矿井里的金丝雀(译注:17世纪,英国人将金丝雀放到煤矿井里检测井中空气质量。如果金丝雀死了,则表示矿井中的空气已达到令人中毒的水平。此处意为对一件事情的预警),如果构建失败了的话,意味着我们的流程可能在哪里出了严重问题,需要去复查一遍我们的工作。使用金丝雀版本需要极强的容忍度,而且在这个版本下可能无法使用应有的基本功能。一般来说,只有这个产品的工程师(开发或测试人员)和管理人员才会安装使用金丝雀版本。
开发版本:这是开发人员日常使用的版本,一般是每周发布一个。该版本具有一定的功能并通过了一系列的测试(我们将会在随后的章节里讨论这点)。所有这个产品下的工程师都会被要求去安装这个版本,并在日常工作中真正使用它,这样可以持续对这个版本进行测试。如果一个开发版本不能够满足日常真实工作的需求,那么它将会被打回为金丝雀版本。发生这种情况不但令人郁闷,工程团队也需要再花费大量的时间去重新评估。
测试版本:这是一个通过了持续测试的版本。这个版本基本上是最近一个月里的最佳版本了,也是工程师在日常工作中使用的最稳定最信任的一个版本。测试版本可以被挑选作为内部尝鲜(译注:dog food)版本,如果该版本有比较持续的优良表现,也是作为beta 测试的候选版本。一些情况下,如果测试版本在公司内部使用得足够稳定,一些想更早尝试这个产品的外部合作伙伴也会使用这个版本。
beta或发布版本:这个版本是由非常稳定的测试版本演变而来,并经历了内部使用和通过所有质量考核的一个版本,也是对外发布的第一个版本。
测试类型
Google并没有使用代码测试、集成测试、系统测试等这些命名方式,而是使用小型测试、中型测试、大型测试这样的称谓(不要和敏捷社区发的那些T恤型号混为一谈),着重强调测试的范畴规模而非形式。小型测试意味着涵盖较少量的代码,其他的测试类型以此类推。Google的三类工程师都会去执行其中的任何一种测试,无论是自动化的还是手动的。测试的规模越小,就越有可能被实现成为自动化的测试。
小型测试 一般来说(但也并非所有)都是自动化实现的,用于验证一个单独函数或独立功能模块的代码是否按照预期工作,着重于典型功能性问题、数据损坏、错误条件和大小差一错误(译注:大小差一(off-by-one)错误是一类常见的程序设计错误)等方面的验证。小型测试的运行时间一般比较短,通常是在几秒或更短的时间内就可以运行完毕。通常,小型测试是由SWE来实现,也会有少量的SET参与,TE几乎不参与小型测试。小型测试一般需要使用mock和fake(译注:mock对象是指对外面依赖系统的模拟,在运行时刻可以根据假设的需求提供期望的结果。fake 对象是一种虚假的实现,内部使用了固定的数据或逻辑,只能返回特定的结果。
中型测试 通常也都是自动化实现的。该测试一般会涉及两个或两个以上,甚至更多模块之间的交互。测试重点在于验证这些“功能近邻区”之间的交互,以及彼此调用时的功能是否正确(我们称功能交互区域为“功能近邻区”)
大型测试 涵盖三个或以上(通常更多)的功能模块,使用真实用户使用场景和实际用户数据,一般可能需要消耗数个小时或更长的时间才能运行完成。大型测试关注的是所有模块的集成,但更倾向于结果驱动,验证软件是否满足最终用户的需求。所有的三种工程师角色都会参与到大型测试之中,或是通过自动化测试,或是探索式测试。大型测试尝试去解决的问题是,这个产品操作运行方式是否和用户的期望相同,并产生预期的结果。这种端到端的使用场景以及在整体产品或服务之上的操作行为,即是大型测试关注的重点。
功能开发人员在编写功能代码的时候,测试开发人员编写测试代码,但我们还需要第三种角色,一个关心真正用户的角色。显然在我们理想化的乌托邦测试世界里,这个工作应该由第三种工程师来完成,既不是功能开发人员,也不是测试开发人员。我们把这个新角色称为用户开发人员(译注:user developer)。他们需要解决的主要问题是面向用户的任务,包括用例(use case)、用户故事、用户场景、探索式测试等。用户开发人员关心这些功能模块如何集成在一起成为一个完整的整体,他们主要考虑系统级别的问题,通常情况下都会从用户角度出发,验证独立模块集成在一起之后是否对最终用户产生价值。这就是我们眼中软件开发过程的乌托邦理想模式,三种开发角色在可用性和可靠性方面分工合作,达到完美。每个角色专门处理重要的事情,相互之间又可以平等地合作。
Google 的 SWE 就是功能开发人员,负责客户使用的功能模块开发。他们编写功能代码及这些功能的单元测试代码。Google的SET就是测试开发人员,部分职责是在单元测试方面给予开发人员支持,另外一部分职责是为开发人员提供测试框架,以方便他们编写中小型测试,用以进行更多质量相关的测试工作。Google的TE就是用户开发人员,负责从用户的角度来思考质量方面各种问题。从开发的角度来看,他们编写用户使用场景方面的自动化用例代码;从产品的角度看,他们评估整体测试覆盖度,并验证其他工程师角色在测试方面合作的有效性。这不是乌托邦,这就是Google实践之路上最好的尝试,前进的道路上充满了不可预料且无路可退。
在任何软件公司创立的初期阶段,通常都没有专职的测试人员(译注:本节标题“SET的工作”,因为原文为The Life of an SET。“The Life of ”是Google内部系列课程(搜索和广告是如何工作的)中使用的特定术语。针对Nooglers(新Google员工)的课程里,Life of a Query揭秘搜索query是如何实现的,Life of a Dollar揭秘广告系统的工作原理)。当然那时候也没有产品经理、计划人员、发布工程师、系统管理员等其他角色。每位员工都独自完成所有工作。我们也经常想象Larry和Sergey(译注:Google的早期创始人之一)在早期是如何思考用户使用场景和设计单元测试的样子。随着Google的不断成长壮大,出现了第一个融合开发角色和质量意识于一身的角色,即SET。
工程师团队的交付物就是即将发布的代码,
这种单一的代码库模式,使得工程师可以很从容地在不同项目之间转换而几乎不需要什么学习成本。这为工程师提供了很大便利,这种单一的代码库模式让工程师从他们进入项目开始的第一天起,其“百分之二十的贡献”(译注:“百分之二十时间”是指 Googler称为的“业余项目”。这并不是一个炒作的概念,而是官方真正存在的,允许所有 Googler每周投入一天时间在他的日常工作之外的项目上。每周四天工作用来赚取薪水,剩下一天用以试验和创新。这并不是完全强制的之前有些 Googler 认为这个想法只是一个传说。根据我们的真实经历,这个概念是真正存在的,我们三个都参与过“百分之二十时间”项目。实际上,本书提及的许多工具都是“百分之二十”项目的结晶。
 
公开的代码库、和谐的工程工具、公司范围内的资源共享,成就了丰富的Google内部共享代码库与公共服务。
对于公共的共享代码,首先要考虑的是能否可以容易地被找到,并具有良好的可读性。
公共代码必须尽可能地被复用且相对独立。如果一个工程师提供的服务被许多团队使用,这将为他带来很高的信誉。与功能的复杂性或设计的巧妙性相比,可复用性带来的价值更大。所有依赖必须明确指出,不可被忽视。如果一个项目依赖一些公用共享代码,在项目工程师不知情的前提下,这些共享代码是不允许被修改的。如果一个工程师对共享代码库在某些地方有更好的解决方案,他需要去重构已有的代码,并协助依赖在这个公用代码库之上的应用项目迁移到新的代码库上。这种乐善好施的社区工作是值得鼓励的,任何工程师如果受到其他工程师正面的影响,就可以送出“同僚奖金”作为感谢。除此之外,经理还有权使用其他奖励手段。这样做的目的就是让这种正向团队合作形成一种良性循环,并持续下去。当然,另外还有同事之间私下里的感谢)。
Google非常重视代码审核,特别是公共通用模块的代码必须经过审核。开发人员必须通过相关语言的可读性审核。在开发人员拥有按照代码风格编写出干净代码的记录之后,委员会会授予这名开发人员一个“良好可读性”的证书。Google的四大主要开发语言:C++、Java、Python和JavaScript都有可读性方面的代码风格指南。
最小化对平台的依赖。所有工程师都有一台桌面工作机器,且操作系统都尽可能地与Google生产环境的操作系统保持一致。为了减少对平台的依赖,Google对Linux发行版本的管理也十分谨慎,这样开发人员在自己工作机器上测试的结果,与生产系统里的测试结果会保持一致。从桌面到数据中心,CPU和OS的变化尽可能小(注:唯一不在Google通用测试平台里的本地测试实验室,是Android和Chrome OS。这些类目不同的硬件必须在手边进行测试)如果一个bug在测试机器上出现,那么在开发机器上和生产环境的机器上也都应该能够复现。所有对平台有依赖的代码,都会强制要求使用公共的底层库。维护 Linux 发行版本的团队同时也在维护这个底层平台相关的公共库。还有一点,对于 Google 使用的每个编程语言,都要求使用统一的编译器,这个编译器被很好地维护着,针对不同的Linux发行版本都会有持续的测试。这样做本身其实并没有什么神奇之处,但限制运行环境可以节省大量下游的测试工作,也可以避免许多与环境相关且难以调试的问题,能把开发人员的重心转移到新功能开发上。保持简单,也就相对会安全。
 
许多创新的产品都是来源于团队20%的业余时间。
这些时间投入的产品有些慢慢地消失了,而另外一些规模会越做越大,有的甚至会成为Google的官方产品
 
在试验初期阶段强调测试是一件非常愚蠢的事情。
 
如果一个产品太长时间没有测试的介入,早期在可测试性上的槽糕设计在后期也很难去做改进,这样会导致自动化难以实施且测试工具极不稳定。在这种情况下,不得不以质量的名义来做重构。这样的质量“债”会拖慢产品的发布,甚至长达数年之久。
在项目早期,Google一般不会让测试介入进来。实际上,即使SET在早期参与进来,也不是从事测试工作,而是去做开发。绝非有意忽视测试,当然也不是说早期产品的质量就不重要。这是受Google非正式创新驱动产品的流程所约束。Google很少在项目创建初期就投入一大帮人来做计划(包括质量与测试计划),然后再让一大群开发参与进来。Google项目的诞生从来没有如此正式过。
在Chrome OS的开发总监给我们介绍他们项目、进度和发布计划时,我们也要求提供当前已有的测试状态、期望的单元测试覆盖率水平、以及明确在发布过程中各自承担的责任。
在项目还是概念阶段的时候,测试人员不会参与进来,而项目一旦真正立项,我们就要在这些测试是如何执行的方面发挥我们的影响力。
在整个项目生命周期里,功能的实现、版本的发布、补丁的创建、为改进而做的重构在不断地发生,你很难说清楚什么时候项目结束或一个项目是否真的已经结束。但所有软件项目都有明确的开始时间。在早期阶段,我们常去改变我们的目标。我们做计划,并尝试把东西做出来。我们尝试去文档化我们将要去做的事情。我们尝试去保证我们早期做的决定长期看来也是正确的。
我们在编码之前做计划、试验、文档,这部分工作量取决于我们对未来产品的信心。我们不想在项目初期做少量的计划,而到项目后期却发现这个计划是值得花费更多精力去做的。同样,我们也不希望在早期计划上投入数周时间,而之后却发现这个世界已经改变了,甚至与之前我们想象的世界完全不同了。某种程度上来说,我们早期在文档结构和过程中的处理方式也是明智的。总而言之,做多少和怎样做比较合适,由创建项目的工程师来做最终决定。
所有Google项目都有设计文档。这是一个动态的文档,随着项目的演化也在不断地保持更新。最早期的项目设计文档,主要包括项目的目标、背景、团队成员、系统设计。在初期阶段,团队成员一起协同完成设计文档的不同部分。对于一些规模足够大的项目来说,需要针对主要子系统也创建相应的设计文档,并在项目设计文档中增加子系统设计文档的链接。在初期版本完成后,里面会囊括所有将来需要完成的工作清单,这也可以作为项目前进的路标。从这一点上讲,设计文档必须要经过相关技术负责人的审核。在项目设计文档得到足够的评审与反馈之后,初期版本的设计文档就接近尾声了,接下来项目就正式进入实施阶段。
审阅设计文档的时候应该有一定的目的性,而不是像读报纸那样随便看两眼就算了。优秀的SET在审阅过程中始终保持强烈的目的性。下面是一些我们推荐的一些要点。完整性:找出文档中残缺不全或一些需要特殊背景知识的地方。通常情况下团队里没人会了解这些知识,特别是对新人而言。鼓励文档作者在这方面添加更多细节,或增加一些外部文档链接,用以补充这部分背景知识。正确性:看一下是否有语法、拼写、标点符号等方面的错误,这一般是马虎大意造成的,并不意味着他们以后编写的代码也是这样。但也不能为这种错误而破坏规矩。一致性:确保配图和文字描述一致。确保文档中没有出现与其他文档中截然相反的观点和主张。设计:文档中的一些设计要经过深思熟虑。考虑到可用的资源,目标是否可以顺利达成?要使用何种基础的技术框架(读一读框架文档并了解他们的不足)?期望的设计在框架方面使用方法上是否正确?设计是否太过复杂?有可能简化吗?还是太简单了?这个设计还需要增加什么内容?接口与协议:文档中是否对所使用的协议有清晰的定义?是否完整地描述了产品对外的接口与协议?这些接口协议的实现是否与他们期望的那样一致?对于其他的 Google产品是否满足统一的标准?是否鼓励开发人员自定义Protocol buffer数据格式(后面会讨论Protocol buffer)?
测试:系统或文档中描述的整套系统的可测试性怎样?是否需要新增测试钩子(译注:testing hook,这里指为了测试而增加一些接口,用以显示系统内部状态信息)?如果需要,确保他们也被添加到文档之中。系统的设计是否考虑到易测试性,而为之也做了一些调整?是否可以使用已有的测试框架?预估一下在测试方面我们都需要做哪些工作,并把这部分内容也增加到设计文档中去。
为了能够尽早可以运行集成测试,针对依赖服务,SET 提供了 mock 与fake。
如果SET希望能从SWE那里得到帮忙,他的自动化计划就必须合情合理且有影响力。自动化上投入的越多,维护的成本也就越大。在系统升级变化时,自动化也会更加不稳定。规模更小且目的性更强的自动化计划,并存在可以提供帮助的测试框架,这些会吸引SWE一起参与测试。
在端到端自动化测试上过度投入,常常会把你与产品的特定功能设计绑定在一起。在Google,SET遵循了下面的方法。我们首先把容易出错的接口做隔离,并针对它们创建 mock 和 fake(在之前的章节中做过介绍),这样我们可以控制这些接口之间的交互,确保良好的测试覆盖率。接下来构建一个轻量级的自动化框架,控制 mock 系统的创建和执行。这样的话,写代码的SWE可以使用这些mock接口来做一个私有构建。在他们把修改的代码提交到代码服务器之前运行相应的自动化测试,可以确保只有经过良好测试的代码才能被提交到代码库中。这是自动化测试擅长的地方,保证生态系统远离糟糕代码,并确保代码库永远处于一个时刻干净的状态。SET除了在这个计划中涵盖自动化(mock、fake和框架)之外,还要包括如何公开产品质量方面的信息给所有关心的人。在Google,SET使用报表和仪表盘(译注:dashboard)来展示收集到的测试结果以及测试进度。通过将整个过程简化和信息公开透明化,获取高质量代码的概率会大大增加。
SET的第一要务就是可测试性。SET在扮演一个质量顾问的角色,提供程序结构和代码风格方面的建议给开发人员,这样开发人员可以更好地做单元测试。同时提供测试框架方面的建议,使得开发人员能够在这些框架的基础上自己写测试
随着Google不断的成长和新员工不断的增加,一些令人疑惑的测试类型方面的专业术语持续不断地涌现出来:单元测试、代码级别测试、白盒测试、集成测试、系统测试、端到端测试等,从不同的粒度级别来表述测试的类型,如图 2.1 所示。在不久前,我们终于觉得忍无可忍,于是自己创建了一套测试命名规则。
小型测试小型测试是为了验证一个代码单元的功能,一般与运行环境隔离,例如针对一个独立的类或一组相关函数的测试。小型测试的运行不需要外部依赖。在Google之外,小型测试通常就是单元测试。小型测试是所有测试类型里范畴最小的,一般集中精力在函数级别的独立操作与调用上,如图 2.2 所示。这样限定了范畴的测试可以提供更加全面的底层代码覆
在小型测试里,外部服务(如文件系统、网络、数据库)必须通过模拟或虚假实现(mock& fake)。为了减少依赖,适当的时候也可模拟实现被测类所在模块的内部服务。范畴隔离且没有外部依赖,这让小型测试可以在很短时间内就运行结束。因此,它们的执行频率也会更加频繁,并且可以很快就会发现问题。通常情况下,在开发人员修改了他们的功能代码之后就会立刻运行这些测试,当然他们还要维护这些测试代码。范畴隔离可以使构建与测试执行时间变短。
中型测试是验证两个或多个模块应用之间的交互,如图 2.3 所示。和小型测试相比,中型测试有着更大的范畴且运行所需要的时间也更久。小型测试会尝试走遍单独函数的所有路径,而中型测试的主要目标是验证指定模块之间的交互。在Google之外,中型测试经常被称为“集成测试”。中型测试运行的时间需要更久,需要测试执行工具在执行频率上加以控制,不能像小型测试那样频繁地运行。一般情况下是由SET来组织运行中型测试。对于中型测试,鼓励使用模拟技术(mock)来解决外部服务的依赖问题,但这不是强制的,如出于性能考虑可以不使用模拟技术。轻量级的虚假实现(fake),如常驻内存的数据库,在不能使用mock的场景下可以用来提升性能。
.对于大型测试在 Google 之外通常被称为“系统测试”或“端到端测试”。大型测试在一个较高层次上运行,验证系统作为一个整体是如何工作的。这涉及应用系统的一个或所有子系统,从前端界面到后端数据储存,如图 2.4 所示。该测试也可能会依赖外部资源,如数据库、文件系统、网络服务等。
小型测试是为了验证一个代码单元的功能。中型测试验证两个或多个模块应用之间的交互。大型测试是为了验证整个系统作为一个整体是如何工作的。
大型测试的优点和缺点包括如下。测试最根本最重要的:在考虑外部系统的情况下应用系统是如何工作的。由于对外部系统有依赖,因此它们是非确定性的。很宽的测试范畴意味着如果测试运行失败,寻找精准失败根源就会比较困难。测试数据的准备工作会非常耗时。大型测试是较高层次的操作,如果想要走到特定的代码路径区域是不切实际的,而这一部分却是小型测试的专长。
中型测试的优点和缺点包括如下。由于不需要使用mock技术,且不受运行时刻的限制,因此该测试是从大型测试到小型测试之间的一个过渡。因为它们运行速度相对较快,所以可以频繁地运行它们。它们可以在标准的开发环境中运行,因此开发人员也可以很容易运行它们。它们依赖外部系统。由于对外部系统有依赖,因此它们本身就有不确定性。它们的运行速度没有小型测试快。3.小型测试小型测试的优点和缺点包括如下。为了更容易地就被测试到,代码应清晰干净、函数规模较小且重点集中。为了方便模拟,系统之间的接口需要有良好的定义。由于它们可以很快运行完毕,因此在
有代码变更发生的时候就可以立刻运行,从而可以较早地发现缺陷并提供及时的反馈。在所有的环境下它们都可以可靠地运行。它们有较小的测试范围,这样可以很容易地做边界场景与错误条件的测试,例如一个空指针。它们有特定的范畴,可以很容易地隔离错误。不要做模块之间的集成测试,这是其他类型的测试要做的事情(中型测试)。有时候对子系统的模拟是有难度的。使用mock或fake环境,可以不与真实的环境同步。小型测试带来优秀的代码质量、良好的异常处理、优雅的错误报告;
大中型测试带来整体产品质量和数据验证。单一的测试类型不能解决所有项目需求。正是由于这个原因,Google项目维护着一个不同测试类型之间的健康比例。对于一个项目,如果全部使用大型的端到端自动化测试是错误的,全部使用小型的单元测试同样也是错误的。
并非所有的产品都需要 TE 的介入。试验性工作、尚无明确目标或用户故事的早期产品,TE很少参与,甚至不参与
在研发的早期阶段,功能还在不断变化,最终功能列表和范畴还没有确定TE通常没有太多的工作可做。
当前软件的薄弱点在哪里?
有没有安全、隐私、性能、可靠性、可用性、兼容性、全球化和其他方面的问题?主要用户场景是否功能正常?对于全
世界不同国家的用户都是这样吗?这个产品能与其他产品(软件和硬件)互操作吗?当发生问题的时候,是否容易诊断问题所在?当然这只是一个不完全列表。所有这些加起来,构成发布待评估软件的风险概要。TE并不需要自己去解决所有这些问题,但必须保证这些问题被解决掉,他们可以请其他人帮忙评估还有多少工作需要去做。TE的根本使命是保护用户和业务的利益,使之不受到糟糕的设计、令人困惑的用户体验、功能bug、安全和隐私等问题的困扰。在Google,TE是一个团队中全职地负责从整体角度发现产品或服务弱点的唯一角色。因此,与SET相比,TE的工作并不是那么确定。TE会介入项目的各个阶段:从产品的构思阶段到第8个版本,甚至是照看一个已经下线的项目。一个 TE 同时参与几个项目也很常见,尤其是那些具备安全、隐私或全球化等专门技能的TE。
TE通常是团队里最出名的人,因为他们需要与各种角色沟通。这个角色需要敏锐的洞察力和领导力,因此很多Google的高级测试经理们都来自于TE。
TE 的工作经常需要去打破常规流程。TE 可以在任何时间进入项目,必须迅速评估项目、代码、设计和用户的当前状态,然后决定首要的关注点。如果项目刚刚开始,测试计划是第一优先级。有时,TE在产品后期被拉进来帮助评估项目是否可以发布,或者在beta版本发布之前确认还有哪些主要的问题。当 TE 进入了一个新被收购的应用或缺少相关应用经验的时候,他们经常会先去做一些不怎么需要计划的探索式测试。有时,项目已经很久没有发布了,只是需要去做一些修饰、安全补丁或界面更新,这需要迥然不同的方法。在Google,TE需要在不同的项目中做不同的事情。我们经常将TE的工作描述为“从中间开始(starting in the middle)”,因为TE必须保持足够的灵活,能够迅速融入一个产品团队的文化和现状。如果做测试计划已经来不及了,那就干脆不做了。如果一个项目最需要的是测试,
那就做一个简单够用的指导性计划。一些测试教条所倡导的从头就介入的模式,在Google并不适用。下面是我们关于TE职责的一般性描述。测试计划和风险分析。评审需求、设计、代码和测试。探索式测试。用户场景。编写测试用例。执行测试用例。众包(译注:crowdsourcing,是互联网带来的新的生产组织形式。一个公司或机构把过去由员工执行的工作任务,以自由自愿的形式外包给非特定的(通常是大型的)大众网络的做法)。
使用统计。用户反馈。当然,能够最好的完成这些任务的,是那些有很强的人格魅力和优秀的沟通技巧的测试工程师。
和测试人员相比,开发人员有一个优势就是他们的工作产物是每个人都真正关心的。开发人员编写代码,构建用户期望的、能为公司赚钱的应用。很明显,代码是项目过程中产生的最重要的文档。然而,测试人员要处理的是真正的文档和其他临时性的事物。在项目的早期阶段,测试人员编写测试计划;然后,他们创建和执行测试用例,编写bug报告;接下来是准备覆盖度报告,收集用户满意度和软件质量数据。在软件成功发布(或失败)之后,很少有人会问及测试产物是什么。如果软件深受人们喜爱,大家就会认为测试所作所为是理所应当的;如果软件很糟糕,人们可能就会质疑测试工作。但其实也没人真正想去了解测试到底做了什么。测试人员不应该对测试文档过于珍爱。软件开发过程充满了痛苦的挣扎:编码、评审、构建、测试、一轮接一轮的开发等,在这个过程里实在很难有时间坐下来欣赏一下测试计划。糟糕的测试用例不会受到足够的关注和改善,它们只会被抛弃,而最后留下来的是更好的测试用例。大家的关注点集中在不断增长的代码库,这才是最重要的东西,理应如此。作为一种测试文档,测试计划的生命周期是所有测试产物中最短的(显然,当客户明确要求编写测试计划,或者出于某些政府法规要求,就没这么灵活了。某些场合必须有测试计划并且保持更新)。在项目早期,人们需要一个测试计划
事实上,项目经理经常坚持必须有一个测试计划,并将编写测试计划作为一个比较重要的里程碑。但是,一旦计划就绪,这些人就把它扔到一边了,既不评审也不更新。测试计划就像是闹脾气的小孩儿手中可爱的毛绒玩具。我们希望它总是存在,到哪里都能带着它,但却从不真正关注它。只有它被拿走的时候,我们才会发出尖叫。测试计划是最早出现、最先被遗忘的测试产物。在项目早期,测试计划代表了对软件功能的预期。但是,除非得到持续的关注,它会很快随着新代码的完成、功能特性的改变以及设计的调整而过期。伴随着计划内或计划外的变更,维护一份测试计划是要花费大量精力的,除非多数项目的成员会定期查看,否则测试计划并没有什么价值。
Google 的分享文化——支持自底向上的实验,以及组织上的灵活性提供了测试创新的肥沃土壤。除非付诸实现和应用到真实问题,你永远都不会知道结果是成还是败。Google允许工程师尝试新鲜的想法,只要他们知道如何衡量成功。
HGTS:你如何参与一个新项目呢?你首先会提出哪些问题、做哪些事情?
Lindsay:对于一个新项目,我首先要站在用户的角度了解这个产品。有可能的话,我会作为一个用户,以自己的账户和个人数据去使用产品。我努力使自己经历完整的用户体验。一旦有自己的真实数据在里面,你对一个产品的期待会彻底改变。在具备了用户心态之后,我会做下面的一些事情。从头到尾的理解产品。不管是整体的设计文档,还是主要功能的设计文档,我都会去看。只要有文档,我就看。在消化了这些文档之后,我开始关注项目的状态,特别是质量状态。我会去了解bug数量、问题的分组方式、已经报告的bug类型、最长时间未处理的bug、最近一些bug的类型等,我还会看一下发现—修复比例。。
夸张地说,只有熟悉了团队的全貌,才能真正有效的展开工作。
我还会去检查应用的代码库。对每一个大一点的类,我会寻找关联的单元测试,并且运行这些测试查看是否能够通过。这些测试用例是否有效?是否完整?有集成或端到端的测试用例吗?它们仍然通过吗?历史的通过率是多少?这些测试用例只是基本场景,还是也覆盖到了边界情况?代码库的哪些包变化最多?哪些已经很长时间没有变更了?开发人员在测试方面的文档工作是否非常随意。我还会评审所有自动化测试。有自动化测试吗?是否还在运行且能运行通过吗?不管怎样,我都要去检查测试代码,理解每个测试步骤,看它们是否完整,看相关的假设、通过和失败点是否正确、是否有效。有时,自动化只覆盖了简单的测试;有时,自动化测试集包含了复杂的用
户场景(这是一个非常好的迹象)。在看完所有文档之后,接下来是团队。我会了解他们沟通的方式和对测试人员的期望。如果他们使用电子邮件列表,我会全部加入;如果有团队IRC或其他的实时通讯方式,我也会加入。询问他们对测试的期望,会帮助发现开发团队没有测试过的内容。
侦查结束,就该开始干正事了。第一件事是把应用分解为合理的功能模块,有一点重叠没有关系。分解不能太细,以免纠缠于细节;但也不能太粗,必须细致到可以罗列子模块和功能
有了功能模块,就可以排列测试的优先级了。风险最大的是哪部分呢?
到这里,我会再次检查bug库。这次是按模块对bug进行分组。这将加快已有bug的查找,减少重复的bug,更容易暴露不断重现的问题。接下来,我会按照优先级顺序更加细致地遍历所有模块,创建用户故事(译注:user story)。对于那些需要详细的步骤说明才能决定pass/fail的特性,通常会编写测试用例并链接到相应模块的用户故事。针对比较奇怪的 bug,尽量附加上屏幕截图、视频、快速参考,或者指向现存bug的链接。
有了测试集合,我接下来会通过再次检查bug和应用来寻找覆盖度上的不足。测试人员做的很多事情是周期性的。此时,我会查看不同类型的测试,检查覆盖情况:安全、兼容性、集成、探索式的、回归、性能、负载等。
有了这些基础材料,我的工作通常只是维护和更新:更新测试用例,增加新特性的文档,更新变化了的模块的截屏或视频。最后,观察哪些bug遗漏到了生产环境,会告诉我们测试覆盖上的不足。
HGTS:身为TE,在你的工作中如何代表用户呢?
Lindsay:我把自己变成用户,就这么简单。我认为,除非能以某种方式将自己置于用户的视角,否则就不可能真正有效地对一个应用进行测试。这就是为什么测试远比检查一个版本是否可用要复杂得多的原因;它包括应用的直观性、行业标准等各方面的反馈。换句话说,测试要清楚地指出当做之事。
 
HGTS:对于你的工作,开发是怎么看待的?如果他们不认可测试的价值,那你又该怎么办?
当我坦诚地指出某些组件或领域的测试不应该由我负责,而应该由他们自己负责的时候,开发反而更加看重我的工作了。很多测试人员试图避免自我宣传,避免公开讨论他们不会测试的东西,担心这样做会使人轻看测试的价值。但在我的经验里,事实却恰恰相反,开发会因此而尊敬你。
 
 
HGTS:谈一谈Google Sites的测试吧。你是怎么开始这个项目的?
产出了哪些文档、是什么格式的?如何与开发沟通你的发现和成果?
通过亲自使用Sites建立网站、熟悉大概功能,我加强了对这个产品的了解。我还联系了有经验的用户。例如,几个月之前,我的房管协会将我们的社区网站搬到了Google Sites上。因此,我找到几个协会成员,咨询了他们的使用情况。这个团队的设计文档和规格文档的更新不是很好。因此,我先把产品分解成了一些可以理解的小块儿,然后再逐个编写模块和子模块的文档。
Google与其他公司的做事方式不同,Google Sites的代码结构与我的习惯不一致,这也减缓了工作进度。另外,创业型公司不怎么写测试——单元的、端到端的或自动化的。因此,JotSpot转来的Google Sites项目只能边走边完善,有些地方使用了不同的风格和方法。这些都是身为测试人员要学着面对的东西。项目已经存在很长时间了,几年下来不但累积了很多bug,而且bug库难以理清、结构不好,并且没有详细的子模块来支持问题分类。我们花了很长时间才将bug按照模块结构整理完毕。
我建立了一个网站(当然是使用Google Sites)用于集中Site测试的所有文档:用户故事、测试环境信息、测试团队信息、各条发布线的测试等。我用电子表格(不怎么时髦)按照测试优先级列出了所有模块和子模块,管理各个发布的测试。所有这些大修整结束之后,我给开发团队做了一次报告,介绍了完整的测试流程。这对于开发团队理解测试的范围和挑战起了很大的作用。在此之后,我确实感到自己的努力受到了更高的赞赏。
HGTS:你能讲一个特别的bug及其发现过程吗?
Lindsay:对我而言,对日期字段的应用进行的“日期”测试一直很有意思。我喜欢测试未来的日期和很久以前的日期,通常总会发现一些很奇怪的错误行为,甚至是一些很有趣的计算错误。有一个查找bug是这样,当在生日字段填写一个未来的日期时,年龄计算就会出现混乱。我觉得查找bug真的很有趣!
 
 
HGTS:怎样评价自己的影响力?
Lindsay:遗漏到客户的bug是一项重要指标,我希望这个数字接近0。另外,我还认真关注所负责项目的声誉。如果项目以bug或糟糕的UI闻名,如在用户论坛里(要密切关注用户论坛),这是项目有待改进、影响也有待提高的信号。一个项目还会困扰于bug债务,即一直没有被修复的陈旧 bug。因此,我还会用仍在影响用户的陈旧 bug 的数量来衡量我的作用。我努力向上反馈这些问题,并用bug寿命等事实来说服开发提高优先级。
 
 
HGTS:你如何判断测试可以结束了?
Lindsay:不太好说。在测试一个新的发布时,这通常由发布日期决定,而不是根据我的判断。此外,由于新的浏览器版本和访问Web应用的新设备的出现,即使是一个开发已经不太活跃的Web应用也需要进行测试。我认为测试的退出标准应该是:你有足够的信心,剩下的bug都属于那些使用率较低、出问题之后对用户影响也较低的模块(或功能特性、浏览器、设备等)。这就是为什么要按照一定的优先级处理应用的各种功能和环境支持。
HGTS:如何推动bug得到修复?
Lindsay:推动bug得到解决是TE的一件重要工作。我必须不断地跟新特性开发抢时间,要求开发人员去修复 bug。用户反馈是一种很有力的论据。一个 bug 带来的用户抱怨越多,我就越能证明修复问题而非开发新特性的时间不会白费。在Google,像Sites这样的企业产品有专门的客户服务代表,我会与这些团队保持密切联系,时刻关注来自客户的频发性的问题。
 
 
HGTS:你的工作如何影响一个产品的发布决定呢?
Lindsay:我会从对用户产生的影响的角度来说明为什么一个功能不能上线或整个发布都不能上线。值得感谢的是,我的团队通常会同意。除非存在严重的问题,我不会阻挡一个发布。重要的是,要维护团队的这份信任——如果我强烈感到发布时机未到,那么这可能也是他们希望的。
 
HGTS:Google和其他公司的测试有何不同?
Lindsay:自主性。在选择全时工作的项目和20%的项目上,我有很大的自由度。20%的时间是Google的一种制度,我们可以每周拿出一天时间,或者说一周工作时间的20%来做自己选择的项目。这使我得以参加了各种不同的项目,提升了技能,同时激发和保持了我的工作热情。否则,我可能会经常感到又是一个土拨鼠日(译注:典故来自偷天情缘Groundhog Day这部电影。在传统的土拨鼠日这一天,主人公陷入了一个偷天陷阱,每当他第二天醒来,都是相同的一天。这里形容毫无新意、重复性劳动造成的日复一日、时间停止的感觉)。
HGTS:SET怎么看待你的工作?
Lindsay:SET可能会忽视人工跟踪bug库和每个发布的测试的重要性,直到他们受益并注意到产品由此产生的变化。即使他们认为自动化覆盖了所有的测试场景(的确如此),如果没有人做探索式测试,就没人去设计开发新的、发现更多问题的测试用例。此外,没有人跟进自动化发现的所有bug,就没有人把这些bug与其他bug和用户反馈关联起来,或者提升其重要性,督促问题得到及时解决。我会把这些事情都讲清楚,所以同我合作过的SET通常会真心实意地肯定我带给项目的变化。当然,还是有一些不那么尊敬我的工作的 SET,但他们就像有类似想法的开发人员一样,不曾与我或其他 TE 一起工作过。一旦发生了合作,他们的态度通常会迅速的转变。
 
HGTS:你是怎样与SET互动的呢?
Lindsay:我负责组织包括SET在内的整个团队的测试战略。当SET不清楚从何处开始实现测试或者工具时,我会展示最需要测试的地方并以bug数据做支持。我还能用真实数据说明他们的方案在预防bug方面的有效性如何。因此,我们的互动主要是围绕组织和反馈进行的。
HGTS:你觉得TE和SET的面试流程怎么样?
Apple:Google的目标是发现有能力学习、成长、解决各种不同问题的多面手。我认为这适用于TE、SET和SWE。在很多其他公司,针对不同的角色有指定的面试团队,面试你的人是你将要一起工作的人。但在Google,面试却不是这样的。面试官来自不同的团队,这样候选人可以得到多个角度的不同评价。总而言之,我觉得这种流程的设计是为了招聘到几乎能在Google的所有团队工作的人。这一点也很重要,因为它方便了Google的内部转岗,你总可以选择新产品领域和新团队。在这种结构下,成为多面手非常重要。
HGTS:你有多家技术公司的工作经历。来到Google之后,这里的软件测试最令你惊讶的是哪一点?
Apple:差别太大了。也许由于深爱 Google 而使我的观点有失偏颇,但我觉得这里的TE 和 SET 比其他绝大多数的公司都更加技术化。我经历的其他公司有专门的自动化团队和手工测试团队,而 Google 的 SET 必须写代码,这是他们的工作。这里也很难找到不会写代码的TE。具备编程能力有助于我们在项目早期就发挥影响力,因为在项目初期主流测试技术通常都是单元测试方面的,这个时候真正的端到端测试还都无法运行。在Google,我认为技术能力是测试人员得以发挥影响力的关键因素。
Google测试的另外一个独特之处是大量的自动化。绝大多数的自动化测试在手工测试人员拿到产品之前就已经执行了。这样,到人工测试开始的时候,代码质量已经相当高了。与其他公司相比,工具也是另外一个不同之处。通常,Google 不使用商业性工具。Google有着高度重视工具的文化,20%时间保证每一个人都能抽空为Google的内部工具做出贡献。工具帮助我们越过困难的、重复性的测试,将宝贵的人力劳动集中在真正需要人的地方。接下来,当然要说一下开发负责质量(developer-owns-quality)和以测试为中心的SWE文化了。质量是大家的共同责任,没人置身事外。任何工程师可以测试任何机器上的任何代码,这就是我们的敏捷之道。
HGTS:作为YouTube的TE,你负责哪些功能的测试?
Apple:我参与了很多项目,帮助完成了很多产品功能的上线。其中新Watch页面值得一提,它是YouTube 视频页面上一个全新的设计,是整个Internet最火的页面之一。另外一个难忘的项目是与Vevo的合作。Vevo是由Google、索尼音乐和环球音乐成立的合资公司。它使用了YouTube的视频托管和流引擎,提供优质的音乐内容。2009年12月8日发布当天,有超过14 000个视频上线,接下来的三个月内,VEVO优质视频的访问量达到了14000 000。我还负责了 YouTube 基于 Flash 的视频播放器从 ActionScript2 升级到ActionScript3的重写的测试工作,以及Channel and Branded Partner的新页面的发布。
 
HGTS:你是如何在YouTube中应用探索式测试思想的呢?
Apple:对YouTube这样一个人性化和视觉体验型的产品而言,探索式测试是非常重要的。我们尽可能地多做探索式测试。
 
 
HGTS:YouTube的测试人员是怎样接受探索式测试这一方法的?
Apple:这是一个巨大的精神鼓舞!测试人员喜欢测试,也喜欢发现bug。探索式测试开阔了测试的活动空间、增加了测试的趣味性。测试人员需要像旅行者一样思考,从不同的角度出发,创造出不同的测试模式来破坏软件。这使测试变得更加有意思、更加有效,因为这种方式的测试可以暴露有趣的、隐秘的、用其他手段或传统重复的过程难以发现的bug。
 
HGTS:我们知道你正在YouTube团队推动Selenium测试。
关于使用Selenium实现测试自动化,你最喜欢的和最不喜欢的分别是什么?
Apple:最喜欢的是简单的API,你可以使用自己喜欢的编程语言写测试代码,如Python、Java和Ruby。你可以从应用里直接调用JavaScript代码这种了不起的特性非常有用。最不喜欢的依旧是浏览器测试。运行速度较慢,还需要API回调,测试离被测的对象很远。它有助于通过自动化那些人工验证极端困难的场景来保证产品质量,如对广告系统后端的调用。我们有一些测试用于加载不同的视频,然后使用Banana Proxy(一个内部开发的Web应用安全审计工具,可以记录HTTP请求和应答)拦截广告调用。这样,浏览器请求经过Banana Proxy(日志)的中转到达Selenium,再到达Web。由此,我们可以检查向外发送的请求是否包含了正确的URL参数,接收到的响应是否包含了期望的内容。总的来说,UI 测试的执行比较慢,非常脆弱,维护成本也很高。一个教训是,只保留少数几个用来验证端到端的集成场景的高级别冒烟测试,除此之外尽可能编写底层的测试用例。HGTS:Flash占据了YouTube内容和UI的一大部分,它怎样测试的呢?你们是否有某种通过Selenium测试Flash的秘籍?Apple:不幸的是,没有。有的只是大量的艰苦劳动。Selenium在某些方面有帮助,因为我们的JavaScript API是暴露的,可以利用Selenium来进行调用测试。我们使用了一个图像比较工具pdiff来测试缩略图、最后一屏(end of screen)的渲染。我们还使用了大量的HTTP流代理来监听流量,这样就可以了解页面变化的更多信息。我们使用As3Unit和FlexUnit 来加载播放器来播放不同的视频,以及触发播放器事件。关于验证,我们可以使用这些框架来验证软件的各种状态、完成图像对比。我想说这就像变戏法一样,但实际上是大量代码铺就的。
 
 
HGTS:你或团队曾经发现过的、避免用户遇到的最大的bug是什么?
Apple:最大的bug通常不那么有趣。然而,我记得曾经有一个导致IE浏览器崩溃的CSS问题。这是我们第一次遇见CSS搞垮浏览器的情形。一个难忘、微妙的bug发生在2010年新Watch页面上线期间。我们发现,在IE7中,当用户将鼠标指针移动到播放器区域之外时,播放器会在一段时间后失去响应。这个问题值得关注,因为当用户在长时间的观看一个视频并四处移动鼠标时就会中招。一切操作都会慢下来,直到浏览器彻底失去响应。最后发现原因是未释放的事件指针和资源一直在反复执行同样的计算。如果你正在看短片或不移动鼠标,就不会发生这个问题。
HGTS:你认为YouTube测试最成功的一点是什么,最不成功的是什么?
Apple:最成功的是一个获取并检查问题 URL 的工具。尽管这个测试很简单,但对快速捕捉到关键的bug真的很有效。我们增加了一个功能,它提供的堆栈跟踪(stack traces)可供工程师用来跟踪和修复问题,这使问题更容易得到调试和解决。这个工具很快就成为部署期间测试的第一道防线,节省了大量的测试时间。
我们还花少许精力进行了扩展,使之可以覆盖到通过日志确定的最流行的URL以及一个人工挑选出来的列表。这件事非常成功。最不成功的大概要算每周上线过程对人工测试的持久的依赖了。我们只有非常小的时间窗口用于测试(冻结代码的当天就要上线),但是却有大量的非常难以自动化的 UI 变动,这就导致手工测试在每周的发布流程中变得非常关键。这个问题很困扰,我希望能有更好的答案。
HGTS:YouTube是一个由数据驱动的网站,因为很多内容都是由算法来决定的。
你们如何验证正确的视频在正确的时间和位置被显示了呢?你的团队验证视频的质量吗?如果验证的话该怎么做呢?
Apple:我们度量视频被观看的频率、它们之间的相互关系,以及一大堆的其他参数变量。我们分析缓冲区内容滞后(buffer under-runs)和高速缓存未命中(cache misses)的数量,并基于这些数据优化全球的服务架构。我们有视频质量级别的单元测试,以确保达到适当的质量。有一个团队实现了一个对此进行更为深入测试的工具,且已经开源(AS3 播放器助手的源代码见 http://code.google.com/p/youtube-as3-player-helper/source/checkout)。它的原理是使用FlexUnit测试用例(基于内置的YouTube播放器)播放各种测试视频并检查播放器状态和属性。这些测试视频具有大型的条码来标记帧和时间轴,使之在压缩失真和质量损失的情况下仍可以很容易识别。度量状态还包括抓取和分析视频帧的快照。我们会检查正确的长宽比或裁剪、变形、色偏、空帧、白屏、同步等,还加入了对bug报告发现的问题的检查。
 
HGTS:关于web、Flash以及数据驱动的web服务,你对其他测试人员有哪些建议?
Apple:不管是测试框架还是测试用例都以简单为要,随着项目的开展再迭代的设计。不要试图事先解决所有问题。要敢于扔掉过时的东西。如果测试或者自动化过于难以维护,不如放弃它并试着去实现更有韧性、更好的东西。密切关注一段时间维护和排错的成本。遵守70-20-10法则:小型的用来验证单个类或功能的单元测试占70%,中型的用来验证一个或多个应用模块之间集成的测试占20%,大型的高级别的用来验证完整应用的测试(一般称为系统测试和端到端测试)占10%。
除此之外,安排好优先级,寻找小成本大回报的自动化项目。一定要记住自动化并不能解决所有问题,尤其是前端项目和设备测试。你总会需要聪明的、探索式的测试并跟踪测试数据。
 
 
HGTS:那么告诉我们真相吧。YouTube 测试一定很热闹吧?比如看一整天搞笑的猫咪视频。
Apple:好吧,有一个愚人节我们颠倒了所有视频的标题。我不说谎,是的,测试YouTube很好玩。我发现了很多有趣的内容,这不正是我的工作嘛!即使这样,我还是会在看猫咪视频时大笑不止。
HGTS:告诉我们你是怎么接手一个新测试项目的吧。你首先会做什么事,问哪些问题?
Ankit:加入一个新项目的头几个星期,我主要用来倾听而不是发表意见。深入理解团队非常重要,要学习产品的架构,了解团队的最新动态。我不能接受一位医生在观察我不到五分钟的时间就给我开具抗生素类的药品。同样地,我也不期望一个测试团队可以接受我一开始就提出的什么解决方案。在进行诊断之前你必须先要学习。
从用户的角度来说,Gmail最大的特性就是它的速度。我料想如果我们为开发团队解决了这个问题,我们就能赢得他们的尊重并开始建立平等的关系。这是个难题。我们必须测试Gmail老版本和新版本速度上的差异,当新版本的速度下降时及时发现。然后我们需要检查所有新版本里改动的代码,并找到速度变慢的原因,从而修复这个问题。这是一个痛苦的过程,非常耗时,并伴随大量的尝试和失败。我曾经和一位测试开发工程师一起想办法,想让Gmail的速度变慢,以便于我们能更好地观察前端和后台数据中心的通讯,从而发现造成性能下降的原因。我们最后到处找了些旧机器,弄了一大堆512M内存、40GB硬盘和低速CPU的机器。Gmail在这些机器上运行速度慢了很多,我们可以把所需的信号分辨出来,然后开始运行长时间的压力测试。头几个月特别艰苦,我们有几次误报。我们花费了大量的精力搭建基础设施,可没有什么产出。但是后来,回归测试的需求滚滚而来。我们可以测量到毫秒级的性能损耗并把数据记录下来。开发工程师能在几小时内就发现产生延迟的问题,而不是以前的几个星期。这样就可以趁问题刚出现的时候就开始调试,而不像以前得在几个星期以后才能开始。这件事立即为测试团队赢得了尊重,以至于在我们着手开展接下来的重要任务(修复端到端的测试和搭建高效的负载测试平台)时,开发工程师实际上还自发地帮助我们。整个团队发现了高效测试带来的价值。Gmail 的发布周期从每三个月缩短到每周,再到每天都能向我们的部分用户发布新的版本。
HGTS:所以经验就是解决掉一些难题来赢得尊重。我喜欢这点。不过做完这些之后你还做了什么?
Ankit:其实,难题永远也解决不完!不过你说的对,基本思路就是关注最重要的事。我们确定Gmail最紧要的问题,然后一起解决它们。通过团队配合,你会发现这些问题并不那么困难。当然,我还是坚信只应该关注最重要的事情。每当我发现团队打算做太多的东西的时候,就好像你要同时做五件事情,但是每件只能完成 80%的时候,我就会要求他们退回来重新安排优先级。把你需要做的事情减少到两到三件,但都能完成到100%。这样团队才能获得真正的成就感,而不是好多事情在他们手里没有完成。如果这些工作最后都能积极地影响到产品质量,那么我也会感到特别高兴。
HGTS:你对测试项目的人员配备有什么建议吗?开发测试比是多少会比较好?SET和TE的比例呢?
Ankit:人员的问题其实很简单,那就是绝不妥协。选用不合适的人来填充名额永远要比等待合适的人员要糟糕。只选用最好的人,不能动摇。Google不让公布人员比例数据,不过以前我们团队中测试人员的比例比正常水平高很多。自从我们解决了很多最初的问题,并得到开发工程师的支持以后,我们的比例就降到和 Google 的标准水平差不多了。从技能分配的角度来说,Gmail的经验是用20%的测试人员进行探索式测试。任何关注用户体验的产品都需要探索式测试。还有30%的测试工程师关注于产品的整体性测试,他们和测试开发工程师一起来保证测试的效果。另外 50%的工作,是测试开发工程师开发相关的自动化测试和工具,以保持代码库的健壮和提高开发人员的工作效率。我不敢说我在下一个项目还会按照这样的比例分配,但是这个比例对Gmail来说是有效的。
 
HGTS:我知道你现在开始负责 Google+的测试了。在新项目中你发现哪些在 Gmail的经验是最有价值的?
Ankit:首先,不要把你所有的精力都放到前端。Gmail拥有最庞大的分布式后台系统,那里还有很多的测试问题我们尚未解决。除此之外,还有很多经验教训值得吸取。使用与应用程序开发语言相同的编程语言来编写测试。让负责开发新特性的人同时负责相应
测试的执行,他需要对漏掉的测试负责。关注测试基础设施的建设,让测试的编写和执行非常容易,甚至比忽略它们还要容易。20%的用例覆盖了80%的使用场景(可能会有些出入)。把这20%自动化而别管剩下的。把那些测试通过手工完成。这里是Google,速度才是王道。如果用户只在乎一件事,那就是速度。确保我们的产品足够快。进行性能分析以便于可以证明给所有人看。与开发团队的沟通至关重要。如果这点做的不好,你就会疲于应付,那可不是什么好事。Google的DNA里富含着创新精神。测试团队也应该被看做创新者。发现重要的问题并能创造性地提出解决方案。哪些陷阱吗?Ankit:有的。假设我们知道用户的需求,然后进行了大规模的改动或编写了大量的代码提供新特性,却没有进行小规模的试验。如果用户不喜欢这些改动,麻烦就大了,而针对这些特性构造的测试框架再好也是浪费。因此,要先为少量用户放出一个版本,获得必要的反馈,然后再为大量的自动化测试进行投资。另外,试图构造完美的解决方案可能花费太长的时间,到时候市场的发展早已超出你的想象了。应该快速迭代,展现阶段性成果。最后,就像开车一样,你必须找到测试的离合点。过早编写测试,有可能由于架构的变化导致全部工作作废。若等待太久,则又可能错失测试良机而导致没有充分测试。测试驱动开发是不错的方法。
 
HGTS:对于个人来说有什么陷阱吗?
年轻的测试工程师和测试开发工程师在新项目里会犯哪些错误?
Ankit:是的。他们可能一上来就开始干,不明所以。他们写了很多测试,但忘记思考为什么要写这些测试,怎么让这些测试为整体目标服务。编写测试的时候,他们往往没有意识到他们还要负责维护这些测试。测试开发工程师应该牢记测试应该是开发人员的工作而他们自己应该专心让测试成为开发人员工作中的一环。我们通过编写工具帮助开发人员做到这点,而且应该让开发人员在维护开发代码的同时也负责维护测试代码。这样一来,测试开发工程师才能集中精力让测试执行得更快,更容易分析。测试工程师有时候会迷失方向,做起测试开发工程师的工作。我们希望测试工程师更全局地看待整个系统,全面地掌控整个产品。他们的重点应该是从最终用户角度考虑的测试,帮助测试开发工程师和开发工程师确保所有的测试和底层测试框架都被正确有效地使用。测试工程师编写的工具和对问题的诊断应该能够影响整个产品。

 

HGTS:除了你前面提到的性能方面的自动化测试以外,还有什么测试方面的工作让Gmail获得了巨大的收益吗?
Ankit:JavaScript自动化测试。我们为Gmail本身加入了一个用于自动化测试的servlet。通过它,开发人员就可以使用与前端开发一致的编程语言编写端到端的测试(译注:端到端的测试是指涉及整个应用系统环境,在现实世界使用时的情形模拟的测试。)。因为它使用很多相同的函数和程序库,开发人员对于如何编写测试代码很熟悉,没有学习曲线。他们可以很容易地写出一些测试,来检验他们的新代码是否影响了Gmail的正常功能,也能够更好地保护他们开发的特性不被其他开发人员破坏。现在,Gmail 的每个新特性都至少会有一个通过这个servlet编写的测试。最棒的是,在我现在负责的社交产品里面我也在用这个方法。我们已经有了大约两万个自动化测试!还有压力测试。在Google你不做压力测试不可能蒙混过关,因为我们的所有应用都有大量的用户,后台数据中心的负载会非常大。我们基本上必须复制一份线上环境并引入真实用户流量。我们花费了几个月的时间分析线上系统的使用情况,构建了一个代表用户的使用模型。接下来,为了数据更为真实,我们使用和真实的Gmail数据中心一样的机器来运行我们的压力测试。然后,我们观察测试环境和被监控的真实环境上的结果差异。我们发现了很多性能退化的问题,并帮助开发人员细化和定位了这些问题。最后,我们更专注于预防 bug 而不是检测 bug,这为我们带来了巨大收益。我们推动自动化测试在代码提交之前更早地执行,避免了大量质量不佳的代码污染项目。这让测试团队随时保持在最前沿,支持项目产出高质量的版本。这也给我们的探索式测试人员提出了更大的挑战。
 
HGTS:在选用人才方面你已经很有经验了。你现在转到社交产品项目上,你的测试团队需要找什么样的人呢?
Ankit:我需要寻找那些不会沉迷于系统的复杂性、遇到困难的问题时能够分解为可执行的步骤并能最终解决的人。我需要有执行力的人,他们会被紧迫感激发而不是吓跑。我需要能够在创新和质量中掌握平衡的人,他们不应该只满足于发现更多的 bug。但最重要的是,我需要能看到他们的激情。我需要那些真正想做测试的人

 

HGTS:这也是我们最后一个问题。在测试领域什么东西会引发你的激情呢?
Ankit:我喜欢由快速迭代和高质量带来的挑战。这两者相互矛盾但又都很重要。这个经典的矛盾迫使我为这两个目标不断优化,而又不会伤害我自己或我的团队。创建一个产品不难,但要快速创建一个高质量的产品会有相当大的难度,而这正是使我的工作——富于挑战又充满乐趣。
HGTS:好的,咱们谈谈手工测试吧。你显然很认真地对待对手工测试(我为此佩服你)。
Hung:我是手工测试坚定不移的支持者。坐下来自己钻研整个产品不是明智之举。我们需要仔细观察要进行测试的每日构建版本,分析里面有些什么。哪些是变化了的?有多少行新增或修改的代码?有多少新的或更改过的功能我们需要处理?提交代码更新的是哪些程序员?与昨天的版本相比,变化的代码分布有多广?这些问题都能帮助我们抓住重点,而不是自顾自地探索整个产品。针对每日构建的版本,我们可以把重点放在发生改变的地方,来让自己的工作更有效率。这也意味着团队之间的沟通非常重要。我要求每个人都要进行探索式的测试,因此减少大家的重复工作很重要。我们有每日沟通会,来确定哪些东西是重要的、需要测试的,保证大家可以一起来完成它们。手工测试对我来说就是抓重点和做沟通。有了这两点我就认可所付出的努力就是值得的、有价值的.

 

HGTS:你会为手工测试创建文档吗?还是纯粹的探索式测试?
Hung:是探索式的,但也为它创建文档。在两种情况下,我们会为手工测试创建文档。第一种情况是,当我们有一个通用的用例,它可以被每次的构建版本使用而且也是主要的测试路径。我们把这些用例记录下来放到GTCM中,这样所有的测试人员或测试外包都能获取和使用这些文档。第二种情况是,我们为每个功能点记录测试指导方案。每个功能点都有自己的特性。手工测试人员把这些特性作为一些指导原则记录下来,一般后来的测试人员能够在后续的版本里很快接手这个功能点的测试。总的来说,我们会花时间为系统级的用例和特定于功能点的指导方针创建文档。
 
HGTS:谈谈你们对开发人员的要求吧。你会要求他们提供规格说明书吗?
会要求他们使用测试驱动开发吗?单元测试呢?
Hung:在理想世界里,我猜想在写每行代码之前都能为之写好测试用例,而每个测试用例又来源于规格说明书。也许这样的理想世界真的存在。我不知道。不过在这个快速发展并充满革新的世界,你只会得到你能得到的东西。如果你写了规格说明那么非常感谢,我会好好利用它。但现实是,你必须遵循一些现有的东西。要求提供规格说明书并不会奏效。坚持要求单元测试也不会让那些单元测试更有价值。规格说明书或单元测试用例并不会(除了一些明显的回归错误)帮助我们更好地发现真实用户会遇到的问题。这就是我们的世界,测试人员的世界。你只有手上的这些东西,还要利用好这些东西为产品、为团队增加价值。
 
HGTS:说一个你们在产品发布以后令你沮丧的测试遗漏的bug吧。
Shelton:喔,你之前问过这个问题吧?我怀疑是不是有谁能真的曾经发布过一个完美的产品?反正我不能,真遗憾!我最后悔的bug是由于我们没能详尽的测试数据中心的各种配置变化引起的。有一次,新版本上线却没经过任何测试。那次配置变化使得最终用户看到的搜索结果变差。通过这个教训,我们学习到配置变化对搜索质量有多么重要。从那以后,我们把配置变更也纳入质量流程中,我们开发了一套自动化测试,每次数据和配置变更时都要执行。
HGTS:你对那些准备构建自动化流水线的公司有什么建议?从哪些工具开始?
Ashish:特别重要的一件事,是要关注团队里新来的开发工程师必须使用到的开发环境。要让代码的获取、编辑、测试、运行、调试和部署都非常简单。消除开发人员这些环节的痛苦会大大提高生产力,而且能帮助团队按时交付高质量的软件。要想达到这一点,清楚地定义依赖关系非常重要。建立一套持续集成的系统,让它能够稳定运行,能够快速的向开发工程师提供反馈。如果信息反馈超过了几分钟,那就需要加入更多的机器。CPU的运行时间可要比程序员在事务间进行切换或等待要便宜多了。让执行和调试代码像输入一条命令那么简单,部署也许能够做到这一点。如果是互联网公司,还要能够支持简单的灰度发布。
测试优先级的建议,根据特定的代码变化指出需要被执行的测试用例。我们这样就有了更有效的测试覆盖、更可信的代码质量和快速反馈,为Google节省了大量的工程资源。
打赏
赞(0) 打赏
未经允许不得转载:同乐学堂 » Tester----Google软件测试之道

特别的技术,给特别的你!

联系QQ:1071235258QQ群:710045715

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫打赏

微信扫一扫打赏

error: Sorry,暂时内容不可复制!