看到这个标题,是不是有点云里雾里? 没有关系,且听我慢慢道来。
这里的QE是Quality Engineer的缩写,其实指的就是软件测试工程师。那么“去QE”又是什么意思呢?字面意思可以简单理解为不再需要测试工程师,本质上指的是测试工作不会再有专职的测试工程师来做,而是由开发工程师自己来完成,通常会遵循“谁开发、谁测试、谁上线、谁On Call”的“一条龙”原则。所以“去QE”的核心理念就是开发自己做测试。显然,如果软件开发流程按照这个模式运作,原本的QE,也就是测试工程师和测试开发工程师在项目中就会很尴尬,如果不能找到突破点并为项目或公司带来价值,极端情况下就会面临被淘汰的窘境,现实是很残酷,在一些推行“去QE”的互联网巨头公司,已经有很多活生生的例子了,一些原本做功能测试以及自动化测试的工程师已经被迫离开了原本的岗位,甚至是离开了公司。
所以本文将针对势不可挡的“去QE”趋势,探讨测试工程师应该如何积极面对并拥抱这样的变化,让QE能够在“去QE”的时代背景下破茧重生。
1. “去QE”的原始驱动力
首先让我们看一下“去QE”这件事情到底因何而起。这还得要从Google举办的GTAC大会说起,GTAC大会的主要议题围绕测试工程师在自动化测试以及其他的测试技术创新,自2006年开始已经连续在北美,欧洲以及亚洲举办了10届。可是到了2017年,Google突然宣布取消原本计划在伦敦举行的会议,Google的理由是“相比自动化测试技术,他们更关心工程效能的提升”。工程效能(Engineering Productivity)在实践中的落地通常就体现在“开发人员完成开发工作的基础上,还需要承担测试、上线和运维的全部工作”,而工程效能应该为开发人员的“一条龙”工作提供所有必要的全链路工具链支持,包括静态代码检测、CI/CD流水线、自动化测试框架、部分测试用例的自动生成、测试执行环境和测试数据准备等。
的确,由开发人员自己完成测试工作,这件事本身是能提高研发的效率。为什么这么说呢?
从流程层面来看,原本软件产品在发布前,通常会经过两个部门:开发部门和测试部门,而现在只会经过开发部门,环节变少了,沟通成本低了,自然可以提高效率。
从实际操作层面看,也会得出同样的结论,在有专职测试的时候,当开发完成了新功能或者是缺陷修复之后,他们自己只会做很少的测试,有些小的改动甚至都不测试,而直接“扔”给测试,这并不是说开发人员没有责任意识,通常开发手头也会有大量的开发任务,而且开发工作量的估算本身也不包含系统性测试的工作量,因为在流程上,后续有专职且更专业的测试。所以当测试提测的时候,时常会发现开发递交的被测版本或者因为最基本的冒烟测试通不过,或者缺陷只是部分修复,或者有新的缺陷引入等原因需要打回让开发重新递交被测版本,由于是跨部门沟通,为此测试人员还要提交新的缺陷报告,这样一来一回,有时还会有多次反复,可想而知,整体的研发效率一定上不去。
基于以上原因,现在国际上的一线互联网技术巨头公司,包括Google,Facebook和eBay等,都在推行“开发自己测试,而不再会有专职测试”的模式,这也就是本文标题中提到的“去QE”。但凡是都有两面性,“去QE”也会带来很多新的问题,我大概总结了以下几点。
2. “去QE”带来的问题
**1) ****由开发人员自己测试自己开发的功能和代码,会存在“思维惯性”,**也就是说在设计和开发过程中没有考虑到的分支和组合,在自己做测试的时候一样不会考虑到。比如对于一个函数,其中有一个String类型的输入参数,如果开发人员在做功能实现的时候压根没有考虑到String存在Null值得可能性,那么函数实现里面也不会对Null值做特殊处理,当然自己做测试的时候就更不会想到要去尝试Null值,这样就留下了很大的盲区。
2) 刚才是从技术上讲的,如果从人性的角度讲,开发人员通常是属于“创造性思维”,自己开发的代码就像是亲儿子一样,怎么看都觉得实现很棒;而测试人员是属于“破坏性思维”,测试人员的职责就是要尽可能多的找到潜在的缺陷,所以测试人员比起开发人员往往更能客观且全面做好充分的测试。
**3) **“去QE”之前,测试工作是专职测试人员完成的,专职测试人员通常还会负责搭建被测试环境以及管理测试执行环境,被测试环境很好理解,就是System Under Test(SUT)。而测试执行环境是指用于执行测试用例的机器,比如对于Web GUI测试,最简单的测试执行环境就是你本地机器上的浏览器。但是对于大型软件企业,尤其是大型互联网企业,测试执行环境远远要比你想象的更复杂。通常都是一些大型的测试执行集群,甚至是内部的测试执行私有云,比如用Selenium Grid搭建的GUI测试执行环境,往往这样的集群都会有成百上千台机器,再比如用Appium+Selenium Grid搭建的移动设备测试集群,也往往会有上千台设备。现在没有了专职的测试人员,那就需要开发人员自己去管理、维护和搭建这些测试基础架构,这样做其实是得不偿失的,工作量本身并没有减少,只是换了一批人来做同样的事情,而且开发的精力往往更应该花在构建新的业务功能上,而不是用在维护测试基础设施。
**4) **测试数据准备是测试过程中必不可少的关键步骤,“去QE”之前,是由测试人员来准备测试数据的,一方面测试人员往往比开发人员在全局层面上更了解被测系统,所以对于测试数据的设计与生成也会更高效,另一方面测试人员在以往的测试过程中已经积累了很多测试数据生成的方法和小工具。现在这些都需要开发人员自己来完成了,无疑进一步加大了开发人员的工作量,而且开发人员往往对跨模块,跨系统的测试数据准备缺乏系统性的理解,往往为了生成一条非自己业务领域的数据而花费大量的学习成本。举个例子,假设现在“买家模块”的开发人员需要测试“商品买入”的操作,那么就需要事先准备好“可以被卖的商品”,这就意味着“买家模块”的开发人员需要明确知道“卖家模块”和“商品模块”的细节,才能生成“可以被卖的商品”。这类问题在目前主流的微服务架构面前会更严重,原因是为了产生一条测试数据,可能会需要依次调用很多个服务。
**5) **对于不同的业务开发团队,各个阶段采用的自动化测试框架可能都不同,比如有些会使用基于Java的Selenium,也有些会使用基于JavaScript的Nightwatch等,在“去QE”之前,各种不同的测试框架与CI/CD的集成,都是由各个业务团队的测试人员和CI/CD的人员一起完成的,现在没有了专职QE,这部分工作就需要开发人员自己和CI/CD人员一起完成,这就要求开发人员不仅需要非常熟悉自动化测试框架的细节(很多时候为了更好地和CI/CD集成,会对开源测试框架或者是自研测试框架做二次开发,比如改进retry机制,增加覆盖率统计等等),还必须了解CI/CD的流水线设计以及脚本设计,然后再将需要支持的自动化测试框架的运行命令行和需要暴露的参数(测试用例Git路径、测试执行环境、测试报告路径等等)写进CI/CD的脚本。这些工作在很大程度上分散了开发的精力,对于提高开发自身效率是非常不利的。
6) “去QE”之前,开发人员往往只关注自己修改部分相关的测试用例,模块或者服务的全回归测试中如果有失败的测试用例,通常是由测试人员跟进去分析具体原因,并协调解决然后才能发布上线。但是现在开发人员负责所有测试,他就必须关注全局的测试。举个实际的例子来看,比如“用户登录”服务的开发工程师修复了一个缺陷,然后本地自测通过后递交了代码,然后很不幸,在CI/CD的流水线上全回归测试却发现有部分用例失败了,虽然这些失败的用例和这次的代码修改没有任何关系,但是为了保证自己的修改能够顺利上线(CI/CD的流水线要求只有全回归测试100%通过才可以上线),他必须挨个去分析失败的测试用例然后自己去找到对应的人去协调解决,这显然是非常不合理和不敏捷的做法。
这样的问题我还能举出很多例子,基于篇幅原因,就不再一一展开了,归根结底,这些问题的本质都会直接影响开发人员本质工作的进度和效率,那么我们应该如何解决或者在一定程度上缓解这些问题呢?
3. “去QE”引入问题的解决思路
基本思路就是要在“去QE”的大背景下,能够让开发人员从这些非业务功能开发相关的事务上解放出来**,这些非业务功能开发相关的事务由“工程效能”服务或者相关支持工具链来统一解决**。这个思想和和目前非常流行的Service Mesh的设计思想不谋而合,Service Mesh也是可以让服务的开发人员可以把所有的精力集中在业务功能的实现上,而不需要去关心服务间通信的基础设施,像类似于服务的注册与发现,熔断机制等都会统一由Service Mesh以对业务应用透明的方式来实现。
那么接下来的问题就是这些“工程效能”服务或者相关支持工具链应该由谁来提供最合适呢?你可能已经想到了,是的,就是原来QE团队中的测试开发工程师,这将是QE团队成功转型“工程效能团队”的最直接突破口。那么我们接下来看一下QE可以提供哪些“工程效能”服务或者相关支持工具链,并且可以以什么样的方式来解决或缓解“去QE”带来的问题。为此,我总结了以下几个方面。
1)统一测试执行服务(Test Execution Service)
CI/CD各个阶段所有的测试执行发起都通过统一测试执行服务(TES,Test Execution Service),TES通过统一的Web Service接口与CI/CD以解耦的方式进行集成。无论是CI/CD流水线,还是开发人员执行测试,都通过TES来发起,唯一的区别是开发人员一般使用TES的UI界面发起测试,而CI/CD是直接在流水线脚本里面调用TES的Restful API发起测试。统一测试执行服务的输入参数也很简单直观,通常只包括测试框架名字、测试用例集版本号、测试用例路径、 测试报告获取方式、同步/异步执行开关等。一旦调用TES发起测试,后续如何调用Jenkins job、如何打包下载test jar、如何找到适合的测试执行环境、如何发起测试以及如何收集测试报告等都****对使用者完全透明。可以想象,现在,开发人员在和CI/CD集成以及执行测试的时候,已经可以完全不需要去关心执行测试的命令行、发起测试的Jenkins job以及配置、测试的具体执行环境、测试报告获取等信息。这将大大提高开发人员自己执行测试的效率和便利程度。
2)统一测试数据服务(Test Data Service)
前面提到过,跨模块,跨系统的测试数据准备对于开发自己做测试是个挑战,尤其是现在大量采用微服务架构,这个问题就会更突出。统一测试数据服务(TDS,Test Data Service)将会以Web Service接口的形式为所有类型的测试提供一致的测试数据准备入口。无论开发是要做API测试,还是GUI测试,或者是性能测试,都可以通过调用TDS的Web Service或者UI来准备各种组合类型和量级的测试数据。TDS本身还是个开发平台,任何开发人员都可以通过脚手架代码来贡献新的数据类型支持,并且TDS平台本身借助自己的Core Service和内建数据库具有元数据管理能力,能够提供诸如测试数据数量以及质量的管理。下图展示了eBay所采用的TDS的架构设计简图供参考。
3)统一测试执行环境服务(Test Bed Service)
正如前面提到的,测试执行环境对于大型企业来说是很庞大复杂的,为了方便开发人员使用测试执行环境,或者说为了使测试执行环境对于开发人员透明,就需要引入统一测试执行环境服务(TBS,Test Bed Service)。TBS的主要职责是负责管理、创建,扩容/收缩测试执行集群。一个常见的测试执行环境架构如下图所示,TBS会根据等待执行的测试用例的排队情况,动态决策测试执行集群的节点数量和类型,通常会使用Docker和Kubernetes来实现TBS的Gird管理。
4) 构建工程效率工具链仓库(Engineering Productivity Tools Store)
类似于App Store的概念,可以把各种测试小工具以及提高效率的工具集统一在Engineering Productivity Tools Store里面集中版本化管理。比如文章开头我们提到过开发自己做测试的时候存在思维盲区,对于像String这样的参数可能遗漏Null值得用例,我们就可以开发一个小工具对被测函数的输入参数类型基于边界值自动生成边界测试用例,比如String类型的参数一定会生成Null,SQL注入攻击字符串,非英文字符,超长的字符串等,这样就可以系统性地避免开发的盲区。诸如此类的工具还有很多,以后有机会再和大家一一分享。
5)测试即服务(TaaS,Test as a Service)的全局架构
除了以上的内容,其实还有诸如统一测试报告服务(TRS,Test Report Service)、全局测试配置服务(GRS,Global Registry Service)和基于API测试解耦的Mock服务(Unified Mock Service),由于篇幅无法一一展开。需要强调是的是,这里谈到的很多服务已经在eBay等企业内部有了落地实践,并取得了很好地效果。原本的测试开发和测试人员也在这些“工程效率”服务和工具链仓库的设计、开发和运维上找到了适合自己,并且能给公司带来全局利益最大化的职位。最后,以Test as a Service的全局架构图来结束本文。
转自:https://mp.weixin.qq.com/s/laAiGFtJIUVpoRAn6Y3lJw