第5章持续集成实践——京东系统质量保障技术实战(5)

发表于:2017-11-22 17:12

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:商城研发POP平台    来源:51Testing软件测试网原创

  第5章持续集成实践
  5.1 持续集成介绍
  5.1.1 持续集成的起源与发展
  持续集成并不是最近才出现的新事物,这个术语最早是由Grady Booch 在1994年提出的。当时提出的持续集成并没有提倡一天内进行多次构建。到了1997 年,Kent Beck 和 Ron Jeffries 创建XP(极限编程)理论时,把持续集成这个工程实践也囊括进来了。Kent Beck 的观点是持续集成的实施过程中,团队文化要比技术更重要。
  到目前看到最多的关于持续集成的描述是来源于Martin Fowler 发表的关于持续集成的论文。他为持续集成总结出了一些规则:
  维护一个单一的代码库;
  . 使构建自动化;
  . 使测试自动化;
  . 每人每天向主干提交代码;
  每次提交都应在集成机上进行构建;
  . 快速构建;
  . 在与生产环境相同的环境中运行测试;
  . 使任何人能轻易获得可执行文件;
  . 人人都能看到正在发生什么;
  . 实现自动化部署。
  随着互联网行业的发展,硅谷一些公司先进的软件开发方法受到国内企业的追捧。2011 年出版的《Google 软件测试之道》更是让大家认识到了Google 这家典型的互联网企业是如何通过高度自动化和优秀的持续集成实践来实现质量保证的。而国内大部分的互联网公司大都面临着同样的问题:一方面为了在激烈的竞争中立于不败之地,就必须尽早地发布产品,不得不把速度和效率放在第一位;另一方面系统的稳定性、安全性及用户体验越来越重要,软件质量也不得不重视。这时持续集成理论的引入,正契合了所有人的要求。
  持续集成包含自动编译、自动化的代码审查、自动部署和自动化测试这些步骤。整个过程可以通过提升软件研发过程中的自动化程度来提高效率。持续集成遵循“早集成,早失败”的原则,能在第一时间发现问题,并及时修复,从而达到降低风险的目的。越来越多的公司开始引入持续集成实践,并且为之组建专门的团队(很多公司的持续集成团队成员最初都是来源于测试或者质量管理团队)。
  随着对持续集成的关注度不断提高,在各大技术网站不断有关于持续集成的优秀文章出现,并且在一些技术沙龙会议上越来越多的工程师开始讨论持续集成这个话题。从0 到1 的过程会让人感觉非常有成就感,然而在各个公司开始实施持续集成以后,也逐渐地暴露了一些问题。主要体现在文化的冲突:没有形成持续集成实践所要求的工程师文化,无法遵守每个人都要优先处理构建失败的纪律,以及对于代码质量意识的重视程度不够等现状。
  2011 年,在Google TestAutomation Conference(谷歌自动化测试大会)上 AlbertoSavoia 发表了《测试已死》的演讲,引起了不小的轰动。接着越来越多的矛头指向了专职测试工程师是否还值得存在这个话题,2012 年个人博主陈浩(@左耳朵耗子)发表文章《我们需要专职的QA 吗》,也引发了大量的争论。对于专职测试工程师的质疑主要体现在独立的软件测试过程需要花费大量的成本,但是并不一定能够百分百地保证线上产品质量,而且还有可能拖慢整个软件研发的进度。很多人在质疑“我们需要为之付出如此大的成本吗?”。
  大多数的测试团队都在探寻除功能测试之外还能做些什么,从而为部门为公司提供更大的价值。一些测试团队中原本就有一些人是专门来做自动化测试和测试工具开发的,有些公司称之为“自动化测试工程师”或者“测试开发工程师”。原来仅仅为了服务测试而开发工具慢慢转向了为整个软件研发过程提供工具支持,那么对于持续集成的支持正符合这个需求。有些公司学习Google 开始成立“工程生产力部门”,还有很大一部分情况仍然是由测试开发团队来为持续集成/持续交付提供工具支持。比如百度腾讯、京东等公司,开始都是测试开发团队主导持续集成工具开发。随着容器技术的发展,持续集成、持续交付、DevOps 出现了新的契机,基于容器技术的持续集成实践在技术上有先天的优势,更容易实现。
  5.1.2 持续集成常用工具
  持续集成的理论发展也是随着软件技术的发展而不断变化的。最初的软件也是以单体软件为主,当然也没有什么好的持续集成工具。直到2001 年Cruise Control的出现,极大地方便了工程师们构建持续集成。 到了互联网越来越发达的今天,很多互联网企业都是大型的分布式Web 系统,持续集成实践又面临一些新的挑战,因此又不断涌现出了一些新的工具。比如Jenkins、TeamCity 和Travis CI 等。
  下面还列出了一些其他的持续集成工具。
  AnthillPro:商业的构建管理服务器,提供CI 功能;
  Bamboo:商业的CI 服务器,但对于开源项目是免费的;
  Build Forge:多功能的商业构建管理工具,提供高性能、分布式构建;
  Cruise Control:基于Java 实现的持续集成构建工具;
  CruiseControl.NET:基于C#实现的持续集成构建工具;
  Gauntlet:提供了沙箱的功能;
  Hudson:Jenkins 的前身;
  Lunt build:开源的自动构建工具;
  Para Build:商业的自动化软件构建管理服务器;
  PMEase QuickZBild:Luntbuild 的专业版。
  5.2 为什么要做持续集成
  软件研发的模式一直在发生着变化,最初的瀑布式研发流程,只有到各个子模块开发完成后,才会集成到一起进行测试。这时出现问题的几率是非常大的,而且常常解决集成过程中遇到的各种各样的问题就需要好几天,还有可能由于在子模块开发期间未考虑到的一些问题而引起整体返工,这样的问题不在少数。
  随着互联网的发展,软件交付的生命周期越来越短,需要快速完成交付,那就需要更早地发现问题并解决问题,而不是把问题留在最后阶段再来解决。因此持续集成这种能够尽早反馈问题,帮助研发团队实现快速交付的实践就越来越重要了。
  5.2.1 避免集成地狱
  在2009 年前后,笔者在过往公司经历过一次由于集成问题造成的架构重新设计,最终导致系统整体返工的案例。当时开发的是一个基于Java 的分布式系统,为了缩短交付周期,采取了三个团队并行开发的方式。需求分析、需求拆分、架构设计、详细设计、系统编码、模块测试等各个阶段都进行得比较顺利。但是当整体项目进行了4 个月,也就是到了整体研发进度2/3 阶段的时候,系统联调阶段发现了重大的问题。其中两个子系统之间的数据交互存在较大的逻辑问题,不仅不能满足用户需求,而且系统都无法正常运转。经过分析发现主要问题在于,在项目架构设计的时候,一些具体的业务场景考虑不够周全,而在开发阶段发现无法满足实际业务场景,因此开发工程师对于其中一个子模块的服务接口做了变更,然而并没有及时通知其他子模块的开发人员,这样就导致了问题的发生。如果站在自己子模块的角度来看,是发现不了问题的。可是一旦三个子系统联合起来运行,就会出现比较严重的问题。那么最后这些问题也只有我们研发人员自己来买单,又通过连续4 个月的攻坚,终于完成了整个项目。最终的情况是项目延期2 个月,导致客户满意度降低,研发人员经过高强度的工作也导致身体疲惫。
  由此可见,这种大型子系统之间的集成问题可以称之为集成地狱。避免出现这种情况的做法是,首先是要做系统拆分,并且按照迭代方式进行软件开发,各个子系统能够尽早独立运行,并进行集成验证,有问题及早发现,及早解决。
  当然,我们日常工作中每天的持续集成,是要达到从根本上解决集成问题的关键步骤。首先解决团队内部每个成员提交的代码之间的集成问题,确保一个人一天辛苦编写的代码,不会在最后和主干代码集成的时候出现大的问题而要推翻重做。然后可通过每日构建来确保主干版本的持续稳定性。还要在每个迭代周期做比较长流程的集成,比如各个子模块的集成和联调测试。
  5.2.2 如何做到快速交付
  互联网时代,信息的传播速度可谓是光速的。如果有一个好的想法,那么势必需要做到尽快实现,如若不然,一旦竞争对手早一步实现,那么就会前功尽弃了。所以已经不可能像原来那样,以年为单位,或者以季度为单位来计时,而是需要以天来计算交付时间。因此才会有人说互联网行业的诀窍是“唯快不破”。又要快速交付,又要有较高的质量,怎么才能实现呢?只依靠人工来实现是不可能了,这就需要一些流程通过计算机来自动执行。持续集成所包含的持续编译、构建、自动部署和自动测试都能大大地节省时间和人力。
  持续集成能够提升交付效率,主要体现在以下两个方面:
  . 及时反馈,尽早发现问题;
  . 自动化来代替手工。
  如果问题能够在开发阶段就反馈出来,那么效果一定是最好的,软件开发人员就能够第一时间将其修改掉,这就是本地构建。在软件开发工程师的本地开发环境中执行与待合并代码分支的预合并、编译、打包、单元测试等操作。
  次之是能够在把代码合并到主干或者基线分支之前把问题反馈出来。通过代码扫描把代码级别的问题发现出来,比如逻辑问题、安全风险和性能缺陷等。还可以执行编译、打包和单元测试等步骤。
  在系统真正上线之前的一个重要环节就是提测环节。在软件开发人员把程序交给测试人员进行测试之前,能够先执行提测标准的验证,就能够避免冒烟失败或者由于较严重的问题而导致返工的现象。当然这里的提测标准可以包含代码扫描、编译打包、单元测试和冒烟测试等内容。
  除了尽早发现问题,及时反馈问题,还有很重要的一点就是持续集成的一些自动化步骤可以很大程度上节约人工成本。比如测试环境的自动化部署、自动化单元测试、自动化冒烟测试、自动化的主流程回归测试和生产环境的自动化验证测试,都能够节省很多人力及时间成本。
  按照持续集成的方式来开发软件,可以时刻保持有待发布的系统,在选择发布
  时机的时候就会比较有主动权。
  5.3 如何实施持续集成
  如何实现从零开始构建自己的持续集成系统和流程呢?有人说要构建自己的持续集成系统,就要有完善的持续集成流程,包含编译打包、代码扫描、自动部署和自动化测试等阶段。如果一开始就设置这么高的门槛,便会吓退一些人了。那么笔者根据自身的经历来讲述下当时所在的小团队是如何从零开始构建自己的持续集成系统,并且逐渐形成完善的持续集成流程的。除了技术上如何构建持续集成系统,还有流程与实施方面的一些心得体会一并介绍给大家。
  5.3.1 从零开始构建持续集成
  无论是实施持续集成或者其他工程实践,都需要团队做出改变。因此改变的动
  机很重要,当然最好的动机是团队自发产生的,而不是自上而下强压下来的。
  从2014 年开始,京东商城研发部下属的京麦研发团队开始针对京东商城的第三方商家开发一款移动端的操作后台。在一个大的研发体系内,对于已经成型的团队来说,改变的成本是比较大的。相反,对于正处于新产品开发阶段的创新型团队来说,没有历史的包袱,便可以轻装上阵地开始尝试改变。做出众多改变的其中之一便是持续集成的实施。由于新加入的一些研发人员技术水平参差不齐,而又要实现快速迭代的项目,在迭代过程中不断试错,不断演进。那么如何从源头上确保每天开发工程师提交的代码都不会引入新的错误呢?比如,一个迭代(两周左右)下来大家都提交了很多代码,到了想要给需求方演示的时候,需要合并代码,发现存在很多冲突,而解决冲突就要花费很多时间。
  那么怎么来解决这种问题呢?首先从代码库的管理方式来看,现在用得比较多的是GIT 或者SVN。一般会采用主干发布,而在其他分支上开发。笔者当时所在团队用的还是SVN 来管理代码。选择的是主干发布,单分支开发的模式。如图5.3.1所示。
  团队中所有的开发人员都在开发分支上做修改和提交,在迭代结束时把开发分支合并到主干上去,经常会出现代码冲突。那么在第一时间通过持续集成要解决的问题就是合并主干时的代码冲突。通过频繁集成,既可以尽早发现代码的冲突问题,又可以及时发现代码编译问题,及时通知开发人员修改,避免后期修改的代价越来越大。
  看到这里大家是否会问,“那这样就算持续集成了吗?这和持续集成理论里面包
  含的持续构建、单元测试、代码审查、持续部署,可差得远了”。
  笔者想说的是持续集成也是一步步发展起来的,最初的时候也仅仅是解决冲突和编译的问题而已。而且从0 到1 的过程是比较难的,实施最简单但是最有效的规则是非常有助于实践的应用和推广的。
  5.3.2 持续集成演进
  在项目最初的阶段,仅仅实现持续的编译构建是可以的。但是随着项目逐渐稳定,进入比较稳定的开发阶段,团队成员无论对于需求的把握,还是一些技术栈的应用都比较熟练了。那么就需要加入新的验证环节,如图5.3.2 所示,编译打包、代码检测、自动部署、自动化测试,加入哪个环节呢?
  在这里是把单元测试的执行和覆盖率检查和代码检测放在一起实现了。因为SonarQube 平台是能够支持代码检测和单元测试覆盖率统计的。
  随着项目的发展,一些功能模块也开发完成了,这时测试工程师就要开始介入了。测试工程师会执行一些冒烟测试和主要功能的验证测试,由于刚开始交给测试人员测试,应该会有不少的问题。首先遇到的应该是能否正常部署的问题,未提交测试之前,都是开发工程师自己在本地编译构建,然后进行本地测试,这可能都是没有问题的。一旦测试工程师参与进来,就需要把项目部署到测试环境中去,而部署到测试环境就会遇到各种各样的问题了。打包的正确性、配置的合理性还有测试环境对于依赖的基础服务网络互通性等都会影响到应用程序是否能正常在测试环境运行起来。如果一旦测试环境无法正常使用,便会影响测试工作的进展。因此在这个阶段我们就首先在持续集成流程中加入自动部署。
  实现自动部署比较简单有效的方案是基于Jenkins 来实现,Jenkins 是扩展性非常强的持续集成工具平台。自动部署可以通过Deploy Plugin 插件来实现,如图5.3.3所示。
  自动部署的执行频率,开始可以不用设置太高。如果开发工程师每次的提交都要执行部署,那么可能会有很多不稳定的版本,因此最初实现每日部署即可。如图5.3.4 所示。
  每天早上来到办公室,开发工程师和测试工程师都可以收到部署是否成功的邮件,或者通过显示器的监控屏幕来看到结果。这样如果一旦出现部署失败,就能够及时找到问题并修复,不耽误当天的测试工作,如图5.3.5 所示。
  持续部署执行了一段时间后,极大节省了在测试环境上花费的时间,提高了研发和测试效率。那么大家可能会有疑问,为何从头到尾都没有加入持续代码扫描和单元测试环节呢?UI、接口和兼容性的自动化测试又什么时候加入进来呢?团队其实是有确保代码质量的实践活动的,比如code review。code review 一般在以下几种情况下进行:
  . 新人提交代码前
  . 比较重要的特性代码提交前
  . 包含比较复杂算法和逻辑的代码提交前
  . 特性分支合并到主干分支之前
  那么,为什么没有在一开始就加入自动的持续代码扫描流程呢?代码能够正常编译打包、能够被正确部署到测试环境,是在迭代周期中的关键节点上的两个必要活动。关键必要节点的自动化实现能够最大程度提升效率,而自动代码扫描属于关键节点,但是非必要环节。如果通过code review 已经能够较好保证代码的质量,那么就可以放在持续集成演进的后续阶段加入进来。而关于持续代码扫描的实现可以参考第6 章内容,如图5.3.6 所示。
  5.3.3 工程师文化的重要性
  持续集成的核心在于及时反馈,当团队应用该实践比较成熟的时候,可以设置构建频率为提交构建(提交代码后立刻执行持续集成构建任务)。笔者所在团队就有过这样的经历,刚开始实施提交构建时,由于功能开发的任务量很大,大部分开发人员都在忙着写新的功能代码,这时就常常不能够及时修复失败的持续集成任务。那么最开始有一个任务失败了,由于对应的开发人员没及时修复,那么破窗效应就会显现出来,很快就会有下一个任务失败,如果也没有及时修复,长此以往,持续集成就成了摆设。
  5.3.4 持续集成流程优化
  随着构建任务逐渐变多,任务执行的速度就会慢慢下降。当每一个任务执行都要超过10 分钟时,开发人员就无法忍受了。提交一次代码,需要等候10 分钟甚至20 分钟才能够给出反馈,有可能开发工程师在未完成构建任务时就去做其他工作了,而当真正构建执行失败时,又无法及时响应。
  因此第一个优化点就是构建效率的提升,缩短构建时间。可是如何来做呢?经
  过分析可以从以下两个方面去优化:
  . 增加执行机,减少排队现象;
  . 拆分较长的任务,减少单个任务执行时间。
  后台是应用了Jenkins 的Master(主机)—Slave(执行机)的机制,每个Slave上可以同时启动的任务数量是有限的,如果太多了则会降低单个任务的执行效率,而设置少了又会造成排队现象。因此在有资源的情况下适当增加执行机器是个很好的提升构建效率的策略。
  一开始为了方便,把编译打包和代码检查两个步骤放到一个任务里,这样单个任务执行时间达到10 分钟以上。而且有时由于前置步骤的编译打包出现问题而导致整个任务失败,这时并不能很清晰地看到是因为编译出了问题,还是代码检查出了问题。比较好的办法就是做任务拆分,每个步骤作为一个任务单独存在。既能够提高单个任务执行效率,又能够很明确地知道该任务的关键性步骤是否执行成功。
  5.3.5 小团队的成功因素
  最初从0 到1 实现持续集成,在十几个人的小团队实施过程中,积累了一些经验和心得。团队的研发效率得到了提升,无论是内在质量还是外在质量都得到了改善。分析一下有以下几点有利的因素:
  . 是由团队自发去应用持续集成实践;
  . 最初流程和系统不成熟时,由专人来持续跟进;
  . 基于团队的现状不断去调整和优化方案和流程,使其不断适应团队现状;
  . 小团队比较容易形成工程师文化;
  . 团队领导的支持。
  5.3.6 规模化实施持续集成的一些困境
  持续集成实践在小团队中取得成功,极大提高了交付效率和研发质量。因此大
  家希望把该实践推广到百人团队,那么就遇到一些问题了。
  首先随着项目数量的增多,构建任务的数量激增。由于初期基于开源方案构建的持续集成系统是支持小团队用的,那么到了大团队应用时就开始水土不服了,各种问题暴露了出来。维护任务爆发性增长,导致最初在小团队中负责跟进持续集成的人,到了大团队实施的时候根本忙不过来。
  其次就是各个团队的差异化。由于各团队负责不同的项目,有的是偏向于前端的,有的是大数据项目,还有的是算法密集型的项目。那么在实施持续集成过程中,各个团队的关注点不同,各个团队的成员的工作习惯也不一样,很难一刀切地做到统一化和标准化。为了适应不同团队的现状,持续集成系统就需要具备很高的灵活性和定制性。
  5.3.7 分步骤实现持续集成
  正如罗马不是一天建成的,也不可能一下子就完成持续集成全流程的实现。前面章节也提到过,持续集成全流程包含持续编译、代码检查、持续部署和自动化测试。那么从哪个环节开始实施持续集成性价比较高呢?
  当然,入门阶段可以尝试持续编译打包,来及时反馈代码版本库的编译问题和冲突问题。真正开始实施的时候可以优先选择性价比较高的持续部署和代码检查。因为自动化测试会涉及大量的脚本维护工作量,以及依赖于基础测试环境和测试数据的稳定性。因此可以把自动化测试放在比较靠后的阶段来实施。
  5.4 小结
  本章的内容主要介绍了持续集成理论、工具和实践的应用。根据笔者所在团队的真实案例做了一些阐述,希望大家在开始实践持续集成的过程中能有所参考。下面的章节将比较详细地介绍持续代码扫描的实现过程。

本文选自《京东系统质量保障技术实战》第五章,本站经机械工业出版社和作者的授权。
版权声明:51Testing软件测试网获机械工业出版社和作者授权连载本书部分章节。
任何个人或单位未获得明确的书面许可,不得对本文内容复制、转载或进行镜像,否则将追究法律责任。
 相关文章
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号