You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

95 lines
7.3 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 19 | 持续交付中流水线构建完成后就大功告成了吗?别忘了质量保障
上期文章我结合自己的实践经验介绍了持续交付中流水线模式的软件构建以及在构建过程中的3个关键问题。我们可以看出流水线的软件构建过程相对精简、独立只做编译和打包两个动作。
但需要明确的是,在持续交付过程中,我们还要做很多与质量保障相关的工作,比如我们前面提到的各类功能测试和非功能测试。
所以,今天我们聊一聊在流水线构建过程中或构建完成之后,在质量保障和稳定性保障方面,我们还需要做哪些事情。
首先,我们回顾一下之前总结的这张流程图:
![](https://static001.geekbang.org/resource/image/ea/da/ea926382484f49fb6a9250a07fc4a5da.jpeg)
可以看出在流水线构建过程中我们尤其要重视以下3个方面的工作内容。
## 依赖规则限制
主要是对代码依赖的二方包和三方包做一些规则限制。比如严格限定不允许依赖Snapshot版本不允许引入有严重漏洞的版本如Struts2的部分版本检测JAR包冲突如我们常用的Netty、Spring相关的包限定某些软件包的最低版本发布如内部提供的二方包以确保版本收敛降低维护成本。
过滤规则上通过Maven构建软件包过程中生成的dependency:list文件将GroupID和ArtifactID作为关键字与我们设定的版本限制规则进行匹配。
两个示例如下(真实版本信息做了修改):
检测JAR包冲突
> \[WARNING\] 检测到jar包冲突: io.netty:netty-all, 版本: 4.0.88.Final, 当前使用:
> 4.0.22.Final
限定最低版本:
> \[WARNING\] 检测到 mysql:mysql-connector-java, 版本 5.0.22, 版本不符合要求, 需要大于等于
> 5.0.88。旧版存在已知兼容性bug导致连不上数据库, 请在2018-01-15 00:00:00前升级完成, 否则将被禁止发布,如有疑问,请联系@发布助手
JAR包依赖以及维护升级通常是一件令我们比较头疼的事情特别是在运行时出现的冲突异常更是灾难性的。为了从技术角度更好地进行管理我们需要做好隔离这一点可以利用JVM类加载机制来实现。
如果你有兴趣可以在网上参考阿里的潘多拉Pandora容器设计资料这里我们就不作详细介绍了。
## 功能测试
包括单元测试、接口测试、联调测试和集成测试。这里的每个测试环节起到的作用不同,联调测试和集成测试依赖的主要手段还是手工验证,所以这里我们分享下可以通过自动化手段完成的单元测试和接口测试。
这里主要用到的几个工具:
* JUnit 和TestNG分别做单元测试和接口测试
* Maven插件maven-surefire-plugin用来执行JUnit或TestNG用例
* JaCoCo分析单元测试和接口测试后的代码覆盖率
* Jenkins自动化测试任务执行报表生成和输出与Maven、JUnit、GitLab这些工具结合非常好。
关于上述这几种工具,我在此就不展开详细介绍了,你可以自行上网查询和学习。
下面,我们分析一下功能测试中的两个重要环节:单元测试和接口测试。
* **单元测试**由开发完成测试用例的开发对于需要连接DB的用例可以用DBUnit这样的框架。用例的自动执行每次代码开发完成开发执行mvn test在本地进行自测通过然后提交到GitLab。可以在GitLab中设置hook钩子和回调地址提交的时候在commitMsg增加钩子标识如unitTest这样提交后就触发回调自动化单元测试用例执行接口确保提交后的代码是单元测试通过的最终可以通过JaCoCo工具输出成功率和代码覆盖率情况。
* **接口测试**用例编写上使用TestNG这个测试框架相比JUnit功能更全面也更灵活一些。但是过程上与单元测试类似当然也可以不通过hook方式出发可以通过手工触发进行测试。
上述自动化测试环节结束,软件包就可以发布到我们之前说的项目测试环境或集成测试环境进行功能联调和测试了,这时就需要部分人工的介入。
## 非功能测试
在功能验证的同时,还需要并行进行一些非功能性验证,包括安全审计、性能测试和容量评估 。分别介绍如下:
* **安全审计**由安全团队提供的源代码扫描工具在构建的同时对源代码进行安全扫描支持Java和PHP语言。可以对源代码中的跨站脚本、伪造请求、SQL注入、用户名密码等敏感信息泄露、木马以及各类远程执行等常见漏洞进行识别对于高危漏洞一旦发现是不允许构建出的软件包发布的。而且实际情况是不审不知道一审吓一跳我们前面几次做代码扫描时各种漏洞触目惊心但是随着工具的支持和逐步改进基本已经将这些常见漏洞消灭在萌芽状态。
下面是扫描结果的简单示例(目前扫描工具已经开源,请见文末链接):
![](https://static001.geekbang.org/resource/image/f2/ba/f23e8221f44961933cea0cf17404c8ba.png)
* **性能和容量压测**主要针对核心应用进行发布前后的性能和容量比对如果出现性能或容量差异较大就会终止发布。关于这一点我在后面稳定性保障的文章中会详细介绍到。这个验证工作会在预发或Beta环境下进行验证因为这两个环境是最接近线上真实环境的。
下图是一张发布前后的效果比对示意图,正常情况下,性能曲线应该是基本重叠才对,不应该出现较大的偏差。
![](https://static001.geekbang.org/resource/image/f0/a9/f0f7fb90f2b67b9136aeebebfe987ba9.jpeg)
## 最后
到这里,我们稍作一个总结。
关于持续交付中的流水线模式,我们在前面两期文章以及本期的分享中,相对完整地介绍了从需求分解开始,到代码提交、软件构建,再到功能和非功能测试验证的整个过程。这个过程就是我们常说的持续集成。
之所以我没有在一开始引入这个概念,是因为,如果我们将注意力集中到这一过程中具体的动作和问题上,会更有利于我们理解,而不是一开始就被概念性的术语和框架束缚住。
流水线模式功能测试和非功能测试的整个过程可以总结如下:
![](https://static001.geekbang.org/resource/image/0b/83/0b305f4deb787c3f272c5267c22c6683.jpeg)
同时,我们在上面持续集成的过程中,要基于前面介绍的各类环境和基础配置管理,比如功能验证就需要在线下环境中的开发环境、项目环境以及集成测试环境上进行验收。
而非功能验证的性能和容量评估就需要在线上环境里的预发或Beta环境中完成。这里就已经涉及到了软件的部署发布。
下一期文章,我将分享线上发布的整个过程,并对整个持续交付体系内容做一个收尾。欢迎你留言与我讨论。
如果今天的内容对你有帮助,也欢迎你分享给身边的朋友,我们下期见!
附:源代码安全审计工具
[https://github.com/wufeifei/cobra](https://github.com/wufeifei/cobra%5Breference_end%5D)