前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一文了解CI/CD的常见问题

一文了解CI/CD的常见问题

作者头像
ITester软件测试小栈
发布2020-12-14 10:07:07
1.3K0
发布2020-12-14 10:07:07
举报
文章被收录于专栏:全栈测试全栈测试

VOL 177

27

2020-11

今天距2021年34天

这是ITester软件测试小栈第177次推文

本文6519字,阅读约需17分钟

一千个人心目中,有一千种DevOps。DevOps最核心的特点,是持续化。CI/CD时代,提倡持续集成和持续交付;而在DevOps时代,软件生命周期的每个阶段都被持续化,因此有了持续计划,持续开发,持续集成,持续测试,持续部署,持续交付和持续监控。

本文主要从持续交集成是什么,为什么要做持续集成,怎么实现持续集成以及什么是持续交付,什么是持续部署,原有的持续集成是怎么样的,持续集成如何优雅落地等方面进行介绍。

持续集成是什么?

持续集成(Continuous Integration)是一种软件开发的实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽快地发现集成错误。许多团队发现这个过程可以大大减少集成的问题,让团队能够更快的开发内聚的软件。

持续集成的目的,就是让产品可以快速迭代,同时还能保持高质量。它的核心措施是,代码集成到主干之前,必须通过自动化测试。只要有一个测试用例失败,就不能集成。

为什么要做持续集成?

实现持续集成的好处如下:

1.降低风险,由于持续集成不断去构建,编译和测试,可以很早期发现问题,所以修复的代价就少;

2.对系统健康持续检查,减少发布风险带来的问题;

3.减少重复性工作;

4.持续部署,提供可部署单元包;

5.持续交付可供使用的版本;

6.增强团队信心;

怎么实现持续集成?

持续集成一般的做法:

  • 通过svn或其他工具拉取代码;
  • 自动化构建;
  • 自动化编译;
  • 自动化测试;
  • 自动化部署;
  • 自动化发布;
  • 邮件发送通知;

Martin Fowler说过,"持续集成并不能消除Bug,而是让它们非常容易发现和改正。

与持续集成相关的,还有两个概念,分别是持续交付和持续部署。

什么是持续交付?

持续交付(Continuous delivery)指的是,频繁地将软件的新版本,交付给质量团队或者用户,以供评审。如果评审通过,代码就进入生产阶段。

持续交付可以看作持续集成的下一步。它强调的是,不管怎么更新,软件是随时随地可以交付。

持续交付的好处:

  • 快速发布,能够应对业务需求,并更快地实现软件价值;
  • 编码->测试->上线->交付,迭代周期缩短,同时获得迅速反馈;
  • 高质量的软件发布标准,整个交付过程标准化、可重复、可靠;
  • 整个交付过程进度可视化,方便团队人员了解项目成熟度;
  • 更先进的团队协作方式,从需求分析、产品的用户体验到设计、开发、测试、运维等角色密切协作,相比于传统的瀑布式软件团队,更少浪费;

什么是持续部署?

持续部署(continuous deployment)是持续交付的下一步,指的是代码通过评审以后,自动部署到生产环境。

“You build it, you run it”。这是 Amazon 一年可以完成 5000 万次部署,平均每个工程师每天部署超过 50 次的核心秘籍。

持续部署的前提是能自动化完成测试、构建、部署等步骤。持续部署的目标是,代码在任何时刻都是可部署的,可以进入生产阶段。

测试是持续集成流程中重要的一环,也是区别传统的软件开发流程中的一个重要的标志。

为什么要有持续集成测试呢?

  • 可以早点发现bug,这时fix bug代价比较小;
  • 可以平滑产品,提高产品质量;
  • 可以让团队的每个人了解产品的质量状态;
  • 每天都有持续集成测试的报告发布;
  • 开发者对自己提交的代码测试情况有比较清晰的了解;
  • 可以有效地解决QA人手不足的情况;
  • 尽可能地把测试自动化,让持续集成测试系统去执行这些自动化测试的case。

持续集成原有模式如何?

1

工作模式

以前团队工作方式:

  • 打包,等待maven编译打包;
  • 发布测试环境,手动重启服务;
  • 通知测试组测试(发邮件、连环夺命Call等等方式...);
  • 一顿grep查Exception,修复BUG,然后重复上述步骤;
  • 到达特殊的日子时,配合运维部署团队到测试环境手动copy最新版WAR包到生产环境,23点的一瞬间执行一个脚本,时刻盯住脚本运行结果,最后验证;

2

存在的问题

我们可以发现很多问题: 1.编译打包的过程浪费开发资源,一次测试部署正常10到20分钟,那出现问题的情况不计其数;

2.测试长时间怠工,资源利用不充分,处于一人干活多人旁观低绩效状态;

3.研发与测试的沟通方式高成本低效率;

4.BUG反馈方式低效;

5.生产环境得不到有效的管控以及安全保障,人工浪费如果产品或者销售想要给客户演示测试环境,得到的结果可能是测试暂时不可用或者稍微等15到20分钟,是否能计算出他们的心理阴影面积?

3

解决措施

DevOps的中心思想在于提高产品各个阶段的产出效率,减少或者避开团队间的沟通障碍,推动产品的快速迭代,“快速失败”,从而实现持续交付、持续部署。而持续集成只是DevOps中的一个环节,下图清晰描述了CI各个周期活动。

我们可以发现较多优点:

  • 流程全自动化,减少重复性的手工操作;
  • 持续发布测试,时刻保持可发布的产品;
  • 团队、高层对项目、产品的进展清晰可见,把控风险;
  • 资源效率有效利用,流动效率更快;

持续集成如何优化?

1

基本原则

我们要做到持续集成,我们需要:

1.一套持续集成工具,大体可分为云集成与本地化集成系统,云集成比如Travis CI、cloudbees的云集成等,本地化集成主要是开源Jenkins的搭建,如果需要大规模部署Jenkins且有预算可使用Jenkins商业版;

2.自动化测试工具、良好的测试用例编写;

3.版本控制系统,git、gerrit推荐;

4.构建、测试失败反馈机制,邮件、自动化运维(AI...)、日志收集分析系统;

5.一套需求、产品、开发、测试、部署、运维共同使用的敏捷研发管理系统,市场上有阿里云效、腾讯的TAPD等。

2

流程A

根据持续集成的设计,代码从提交到生产,整个过程有以下六步。

①提交

流程的第一步,是开发者向代码仓库提交代码。所有后面的步骤都始于本地代码的一次提交(commit)。

②第一轮测试

代码仓库对 commit 操作配置了钩子(hook),只要提交代码或者合并进主干,就会跑自动化测试。测试有以下几种:

  • 单元测试:针对函数或模块的测试;
  • 集成测试:针对整体产品的某个功能的测试,又称功能测试;
  • 端对端测试:从用户界面直达数据库的全链路测试;

第一轮至少要跑单元测试。

③构建

通过第一轮测试,代码就可以合并进主干,就算可以交付。交付后,就先进行构建(build),再进入第二轮测试。所谓构建,指的是将源码转换为可以运行的实际代码,比如安装依赖,配置各种资源(样式表、JS 脚本、图片)等等。常用的构建工具如下:

  • Jenkins;
  • Travis;
  • Codeship;
  • Strider;

Jenkins 和 Strider 是开源软件,Travis 和 Codeship 对于开源项目可以免费使用。它们都会将构建和测试,在一次运行中执行完成。

④第二轮测试

构建完成,就要进行第二轮测试。如果第一轮已经涵盖了所有测试内容,第二轮可以省略,当然,这时构建步骤也要移到第一轮测试前面。第二轮是全面测试,单元测试和集成测试都会跑,有条件的话,也要做端对端测试。所有测试以自动化为主,少数无法自动化的测试用例,就要人工跑。需要强调的是,新版本的每一个更新点都必须测试到。如果测试的覆盖率不高,进入后面的部署阶段后,很可能会出现严重的问题。

⑤部署

通过了第二轮测试,当前代码就是一个可以直接部署的版本(artifact)。将这个版本的所有文件打包( tar filename.tar * )存档,发到生产服务器。生产服务器将打包文件,解包成本地的一个目录,再将运行路径的符号链接(symlink)指向这个目录,然后重新启动应用。这方面的部署工具有 Ansible,Chef,Puppet等。

⑥回滚

一旦当前版本发生问题,就要回滚到上一个版本的构建结果。最简单的做法就是修改一下符号链接,指向上一个版本的目录。

3

流程B

实现持续集成,一般需要以下四方面的内容:

①具有版本控制的代码库

例如:SVN, Git。相信现在的项目没有不对代码进行版本管理的,这里不再详述。

②构建工具

在持续集成的过程中,需要对已存在的或者新提交的代码进行编译、打包等操作。这样,就需要构建工具帮助构建一个编译环境,并对代码进行编译、集成、打包等操作。而构建的方式越简单越好,最好是一句命令就可以启动构建。现在,各种语言都有自己的构建工具,例如Java中的Maven、Gradle、Ant,前端中的Grunt、Gulp等等,好好利用这些工具,就能帮你完成这部分工作。

③测试

测试是持续集成中重要的一环。代码提交前,需要在本地运行单元测试,通过测试后再提交代码。构建完成后,需要运行全部测试(单元测试,功能测试,端到端测试)以确保产品质量。如果有一个测试没有通过,那么这次提交的代码不能进入主干;或者这次构建的产物是一个失败的构建品,不能用于发布。另外,由于持续集成依赖于这些测试去保证产品质量,所以测试的覆盖率要尽可能高。测试覆盖率不够高(包含代码覆盖率和功能覆盖率),就无法充分反映代码的变动是否对系统带来影响。而低覆盖率的测试,压根就无法保证产品质量。当上线的时候才发现问题就太迟了。

④CI工具

CI工具的作用是将整个CI过程管理起来并自动化,结果可视化。部分工具还结合了CD(持续交付)的功能。现在已经有很多CI工具去满足你不同的需求,例如Jenkins,专为Github开源项目提供的Travis,.Net用的CruiseControl.Net。他们各有特色,根据自己的需求选择适合自己的工具即可。

4

小结

以上两种流程A,B都是一些公司常用的模式,大同小异,供自行参考。

持续集成如何优雅落地?

1

背景描述

假设现在有一个产品P,以war包形式发布,由三个模块module A, module B, module C构建而成。三个模块的关系为:A和B为独立模块提供不同功能。C依赖A和B,然后构成产品P。我们使用了Git作为我们代码库的版本管理工具,用Java进行开发,maven作为我们的构建工具。在每个模块里,有我们基于JUnit写的单元测试代码。独立于三个模块外,有一块代码,也是基于JUnit写的,作为我们的功能测试代码(集成测试)。

2

实现步骤

①集成代码

当我们完成开发工作,需要提交代码到代码库前,我们至少需要在本地跑一次单元测试,在保证全部测试通过后,才可以将代码提交至我们的代码库Git上面去。例如,在我们上面描述的项目中,我对module A的代码进行了修改,那我最起码得在本地运行一次mvn test(执行Maven命令,test代表将会执行到maven default生命周期中从validate到test阶段), 执行成功后,我才会将代码commit and push到远程Git库上去。要做到这样效果的话,就需要保证单元测试代码也同步完成。而在极限编程中(XP),人们比较倾向于测试驱动开发(TDD, Test-driven Development)的实践,通过提前写好自动化的单元测试,保证好每一步功能开发的质量。

②自动构建

通过CI工具,可以设置一个勾子,当代码提交后触发相应构建。例如,我们提交了module A的代码时,Jenkins会扫描到我们这次提交,勾子触发module A的构建。这个过程会做如下操作:

1.Jenkins调用Git插件,从Git库上下载最新代码;

2.Jenkins调用Maven插件,执行Maven命令(一般为mvn install,如果需要上传至远端Maven库,也可以执行mvn deploy)对该模块进行构建。经过编译、通过单元测试后,便可以打包并安装到本地Maven库,以供其它依赖所用。这次构建成功,意味module A在模块自身的单元测试范围内是正常的。

3.因为module A是包含在产品P里面,所以,也需要进行产品功能的回归测试。由于module C依赖A,并构建成产品。所以在CI工具里面,我们需要配置好在module A构建成功后,自动触发module C的构建,经过类似步骤1、2这样的构建后,最终会生成产品P的war包。而C的构建成功,只代表着通过了module C自身的单元测试,还不能对生成的war包进行功能测试。然后就要看我们下一步的工作-自动部署。

③自动部署

在功能测试之前,我们需要在CI工具里配置一项任务,用于将最新构建出来的产品包部署到测试环境中去。这个任务由产品构建任务成功而被触发,而部署方式根据不同使用方式及不同的实际情况而多种多样。例如通过脚本将新构建的war包上传至指定位置,等待web容器自动扫描及部署。或者产品有自己的安装脚本,我们在任务中配置好运行安装脚本,就可以自动将产品部署到指定的测试环境中去。

④功能测试/集成测试

当部署成功后,真正的功能测试就可以开始了。一般情况下,我们可以独立出一块代码,基于JUnit编写好我们的功能测试代码(JUnit是作为测试的入口以及基本测试框架。如果你的需求比较复杂,那你完全可以将其它三方框架与JUnit集成使用)。功能测试过程和构建过程非常相似,均是依赖Git和Maven去完成:

1.Jenkins调用Git插件,从Git库上下载最新代码;

2.Jenkins调用Maven插件,执行Maven命令:mvn clean test。

区别在于功能测试阶段,Maven只执行到default生成周期的test阶段,不会执行后面的package和install。因为它只需要Maven帮忙运行测试代码即可,它本身没有什么可以构建的。

如果还需要更复杂的端到端测试的话,可能就需要准备更复杂的部署脚本,或者预先准备好整套端到端测试环境,之后只需要部署好war包即可。但无论怎样,最终原理还是相同。

⑤交付

当新提交代码构建出来的产品包,通过了各种各样残酷的测试后,就说明这个包是稳定的,能达到基本交付条件的(前提是自动化测试的覆盖率足够高,当然,有一些极端的情况需要人工测试的另说)。那么,我们就可以将这个包放到指定目录作为交付品,供其它测试团队获取并进行进一步的测试,甚至供生产环境部署使用。

4

总结

持续集成(Continuous Integration)、持续交付(Continuous Delivery)和持续部署(Continuous Deployment)提供了一个优秀的 DevOps 环境,对于整个团队来说,好处与挑战并行。

持续集成作为极限编程中的一个实践,是敏捷开发中快速迭代的重要保证,现在已被很多公司使用。但是使用持续集成并不是说要接受极限编程的全部东西,相反,它可以独立开来,与其它实践结合使用。

自动化测试是持续集成中重要一环,要真正用好持续集成,就要尽量提高自动化测试的覆盖率。

以上

That‘s all

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-11-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ITester软件测试小栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 持续集成一般的做法:
  • 以前团队工作方式:
相关产品与服务
持续集成
CODING 持续集成(CODING Continuous Integration,CODING-CI)全面兼容 Jenkins 的持续集成服务,支持 Java、Python、NodeJS 等所有主流语言,并且支持 Docker 镜像的构建。图形化编排,高配集群多 Job 并行构建全面提速您的构建任务。支持主流的 Git 代码仓库,包括 CODING 代码托管、GitHub、GitLab 等。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档