说说Google软件测试开发工程师的工作内容

2018-07-08 04:29:19 / 打印

一个完美的开发过程是这样的:测试先行,开发人员会些设计一些边界场景的测试用例,比如数据的取值范围从极大到极小、循环语句超出限制范围等等许多极端情况。这些测试代码会作为产品代码的一部分,以自检代码或者单元测试代码的形式与功能代码放在一起。这种类型的测试,开发人员是最适合、也是最有资格去做的人。

对于功能代码而言,思维模式是建设,重点在考虑用户、使用场景和数据流程上;对于测试代码而言,思维模式是破坏,借用代码扰乱用户以及数据。在理想的开发过程里,我们可以把开发人员分为功能开发人员与测试开发人员。

我们还需要一个用户开发人员,他们主要关心的问题是面向用户的任务,包括用例、用户故事、用户场景、探索式测试等等。

上面的这种乌托邦式的理想开发过程,三种角色分工合作,真是完美啊。

可惜,这种公司在现阶段好像还不存在过,Google 也只是接近这种模式。当前的软件业的发布周期需要以年为单位的客户端模式向每周、每天、甚至每小时都会发布的云端模式转变。Google 的客户端也按照 “云端模式” 来发布,他们的客户端都有一个“自动更新”功能。

Google 的软件测试开发工程师(SET)的职责如下:

在单元测试方面给予开发人员支持。

为开发人员提供测试框架,这样会方便开发人员编写一些中小型测试,以利于后期进行更多的与质量相关的测试。

公开的代码库(搜索非常便利)、和谐的工程工具、公司范围内的资源共享,这些共享服务依赖于 Google 的基础设施产品,它们会加速项目完成,并且减少了项目失败的风险。

开发人员在维护这些代码时,需要遵守这些规则:

所有的开发人员必须复用已经存在的公共库,除非在需求方面有很好的说服理由。

对于公共的共享代码,必须能够很容易被找到,并且具有良好的可读性,这些代码必须存储在代码库的共享区域,以便查找。

公共代码必须尽可能地被复用而且相对独立。因为与功能的复杂性和设计的巧妙性相比,可复用性带来的价值更大。

所有依赖必须明确指出。

Google 非常重视代码审核,特别是公共通用模块的代码必须经过审核。开发人员必须通过相关语言(C++、Java、Python、JavaScript)的可读性审核,当开发人员按照约定的代码风格写出干净、简洁的代码之后,委员会会授予这名开发人员一个“良好可读性”的证书。

在共享代码库中的代码,对测试有更高的要求。

最小化对平台的依赖。所有开发人员的操作系统都尽可能地与 Google 生产环境的操作系统保持一致。对 Linux 发行版本也进行了管理。这样如果一个 bug 在测试机器上出现时,那么在开发机器和生产机器上应该也能复现。

所有对平台依赖的代码,都强制要求使用公共的底层库。Google 使用的每种编程语言,都要求使用统一的编译器,这个编译器针对不同的 Linux 发行版本都会进行持续的测试。限制运行环境可以避免许多与环境相关的那些难以调试的问题。保持简单,也就相对安全。

使用统一的运行平台和相同的代码库,进行持续集成测试、打包。

整体构建流程如下:

针对某个服务,保证所有相关代码编译通过。

设置这个服务的构建目标(Google 中是公共库、二进制文件或者测试套件,我们假设是公共库)

编写一套单元测试用例,所有外部重要的依赖通过 mock 模拟实现。

为单元测试创建一个测试目标。

构建并运行测试目标,有问题就修改代码,直到所有的测试都运行成功。

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

提交代码,申请代码审核,根据反馈再做修改,然后运行所有的单元测试并保证顺利通过。

这里面包含两个目标:

库构建目标:需要新发布的公共库。

测试构建目标:验证新发布的公共库是否满足需求。

一个 Google 产品由三部分组成:

经过良好测试的独立库。

可读性和可复用性好的公共服务库。

覆盖所有重要构建目标的单元测试套件。

为了保证单独的服务可以并行地开发,服务之间的接口需要在项目的早期确定下来,这样开发人员就可以依赖于协商好的接口上。为了保证服务级别之间的早期测试,这些接口一般只做了虚假实现。

在构建目标增长到一定规模时,针对功能集成的小型测试会成为回归测试的一部分。

在以上的活动中,SET始终是核心参与者。SET 还会同时编写许多的Mock工具。

SET也是软件工程师,是一个 100% 的编码角色,他会作为测试人员尽可能早地参与到设计和代码开发流程中去。

SET是和功能开发人员坐在一起的,这样更容易融入进去。

在面试 SET 的时候,在代码要求上与软件开发工程师(SWE)是一样的,同时还要求 SET 明白如何去测试 SWE 编写的代码。也就是 SET 的要求更高,需要同时了解代码以及测试的问题。

许多创新产品(比如 Gmail 和 Chrome OS)都来源于团队 20% 的业余时间。只有在软件产品变得重要的时候,质量才显得重要。

如果一个产品在概念上还没有完全成型就去关心质量,这是优先级混乱的表现。因此在项目早期就强调测试,是一件非常愚蠢的事情。

Chrome OS 刚开始只有几个开发人员做了原型,且多数都是脚本和虚假实现,他们拿着只是原型的浏览器应用模型做演示,并通过了正式的立项批准。一旦得到正式批准立项,项目的开发总监就会找测试团队,寻求测试资源。

SWE 一般仅在自己的模块领域内提供最优的解决方案,但从整个产品的角度来看,视野略窄,而一个 SET 不仅要具有更广的产品视野,而且在产品的整个生命周期中对产品和功能特性都要做充分的理解。

早期的计划做多少和怎样做比较合适,由创建项目的负责人来做最终的决定。

苏州行驶那个的google浏览器官网下载的那么享用的

Google 的技术负责人一般由工程师担任,负责设定技术方向、开展合作、充当与其他团队沟通的项目接口人。

在初期,团队成员一起协同完成设计文档的不同部分,这些文档需要技术负责人的审核。SET 在团队中的优势就是他们拥有产品方面最广阔的视野。

为什么要让 SET 参与审核设计文档:

SET 熟悉系统设计(通过阅读所有设计文档)。

SET 早期提出的建议会反馈在文档和代码里。

作为第一个审阅所有设计文档的人,SET 对整个项目的了解程度超过了技术负责人。

SET 在项目初期就与开饭人员建立了良好的工作关系。

审核设计文档时,需要带着一定的目的性:

数十颗谷歌浏览器下载安装

完整性:找出一些特殊背景知识的地方,鼓励作者在这方面添加更多的细节,或者增加一些外部文档的链接,作为补充。

正确性:是否有语法、错字、标点符号等方面的错误。

一致性:确保配图和文字描述保持一致,确保文档没有出现与其他文档在观点上截然相反。

设计:设计经过深思熟虑。

接口和协议:清晰的定义,完整地描述。

测试:保证系统的可测试性,而且易于测试。

Google 采用的是 protocol buffer 语言,它与编程语言和平台无关,对结构化数据具有可扩展性,但相比 XML 更小、更快、也更简单。开发人员使用 protocol buffer 的描述语言定义数据结构,然后自动生成源代码。

SET要尽早提供一个可供实施的自动化测试计划。计划必须合情合理而且有影响力。因为投入的越多,维护的成本也会越大,所以需要保证计划规模小而且目的性要强。

SET 会先把容易出错的接口进行隔离,并针对它们创建 mock,这样就可以控制它们之间的交互,从而确保良好的测试覆盖率。

SET 会构建一个轻量级的自动化框架,并使用报表和仪表盘来展示收集到的测试结果以及测试进度,整个过程公开透明,这样获得的代码的质量会大大提高。

SET 要保证系统的可测试性。他是一个质量顾问的角色,为开发人员提供程序结构和代码风格方面的建议,这样开发人员才能更好地做单元测试。SET 还提供测试框架方面的建议,使开发人员能够在测试框架的基础上写测试。

开发人员必须有能力进行代码审查,代码审查有来自工具和公司文化方面的支持。只有被证明是值的信赖的开发者,才能往代码库中提交代码。

Google 把代码审查作为开发流程的中心,因此相对于编写代码而言,代码审查更值的炫耀。

代码已一个“变更列表”(change list,下文会简称为 CL)的单元被编写和封装起来。CL 会被提交审查,Google 使用代码审查工具 Mondrian 发送给具有审核资格的 SWE 或 SET进行审查。

如果 CL 很大,那么审查者会要求把数量较大的 CL 分解为数量较小的几个 CL。有经验和值的信赖的开发人员会得到“可读性”的资格,大家同心协力确保整个代码库看起来像是由一个人编写的一样。

小型测试就是单元测试。它一般集中精力在函数级别的独立操作与调用上,这样的限定可以提供更加全面的底层代码的覆盖率:

范围的隔离而且没有外部依赖,所以小型测试可以在很短的时间内运行结束。这样它们就可以执行的比较频繁,也可以很快发现问题。

中型测试的主要目标是验证指定模块之间的交互,也就是集成测试。鼓励使用模拟技术(mock)来解决外部服务的依赖问题。有的情况下 mock 不能用,那就用轻量级的虚假实现(fake),比如使用常驻内存的数据库。

大型测试就是系统测试,或者端到端测试。它会依赖外部资源,比如数据库、文件系统、网络服务等等。

Google 的测试平台的需要满足的功能是:

谷歌浏览器截图传统:

开发人员编译和运行小型测试,希望立即能够知道运行结果。

开发人员系统运行一个项目中的所有小型测试,并能够快速知道运行结果。

只有在代码变更后,才希望去编译运行所有相关的测试,并能够立即知道运行结果。

看到一个项目的测试覆盖率并查看结果。

对项目的每次代码变更,都能够运行这个项目的小型测试,并将运行结果发送给团队成员以辅助进行代码审查。

在代码变更提高到版本控制系统后,自动运行项目的所有测试。

每周都能得到代码覆盖率,并实时跟踪覆盖率的变化。

当每一个测试都被标注为相应的规模后,调度器可以优化任务队列,达到合理利用的目的。

针对不同测试规模的测试执行时间的目标和限制:

不同测试规模的资源使用情况:

Google 的测试系统会监测某个测试任务是否超时,或者消耗的资源超过了这个测试规模所应使用的资源时,会取消它并报告错误。

因为可以很快运行完毕,所以在有代码变更时就可以立即运行,这样可以较早地发现缺陷并及时反馈。

可以很容易做边界场景与错误条件的测试。

可以很容易地隔离错误。

代码应清晰干净、规模较小且重点集中。

为了便于模拟,系统之间的接口要有良好的定义。

有时候对依赖资源的模拟是有难度的。

是小型测试到大型测试的过渡。

因为运行速度较快,所以也可以频繁地运行它们。

依赖外部资源,所以本身就具有不确定性。

运行速度没有小型测试来得快。

是最根本,也是最重要的,因为它们反应了系统是如何工作的。

依赖外部资源,所以本身就具有不确定性。

因为测试范畴很宽,所以如果测试运行失败,要精确定位到失败的根源比较困难。

准备测试数据很耗时。

大型测试不能像小型测试那样可以走特定的代码路径,所以只能进行功能的常规测试。

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

代码覆盖率的结果会存储在云端,任何开发人员都可以通过内网的网络,使用浏览器来查看这些报告。

总体上的经验法则是:70% 是小型测试,20% 是中型测试,10% 是大型测试。如果项目是面向用户的,拥有较高的集成度,或者用户接口比较复杂,就应该使用更多的中大型测试;如果是基础平台或者面向数据的项目,最好有大量的小型测试。

每个测试与其他测试都是独立的,它们能够以任意顺序运行。

不做持久化方面的工作。当测试用例测试后,要保证测试环境的状态与测试用例开始执行之前的状态是一致的。

文章来源: