当要求品质内建、测试左移、继续集成、DevOps,代码的增量覆盖率简直是必定会被提出来的话题。 这个计划明确了"谁的代码谁负责"的准则,和当年“小岗村包产到户”一样,开发人员只须要为本人的提交/合并申请来提供代码覆盖率数据,而不再须要为整个团队的代码库和历史旧账掉头发了。团队负责人也乐于施行这样的“最佳实际”,建立一个带电的“品质门禁”,没有达标的,一律回绝签入或者合并。
然而始终以来,对于增量覆盖率的计算始终是一个守口如瓶的技术。谈起这个话题,大厂的同学们会悠悠地说一句,咱们是自研的工具。而对于这几个工具的集成,网络上有有数篇教程。但简直所有的教程,无论宣称是做PR/MR触发的流水线,还是做Jacoco覆盖率,都只是介绍了如何将这几个工具进行集成,也就是文章的起点停在了SonarQube上能产生覆盖率报告甚至只是Jenkins能触发构建上。
本文将介绍如何应用上述工具实现残缺的MR/Push闭环,并真正实现增量覆盖率的计算。
首先假如您曾经可能把握GitLab+Jenkins+Jacoco+SonarQube的流水线的搭建,可能实现MR/Push触发Jenkins构建和Sonar扫描。
也就是以下的一个过程:
1)Gitlab通过push event或者merge request event来触发webhook (webhook url指向某个Jenkins工作,也波及到token配置)。
2)该webhook将调用Jenkins 的指定流水线工作,能够是传统的freeStyle或者是pipeline的,也可能是团队自研的DevOps 平台的。
3)流水线工作触发单元测试、集成测试等事后定义好的测试,并生成覆盖率测试报告(maven/gradle +jacoco)。很多自研的计划其实是在这个阶段通过git diff+jacoco报告解析来实现增量剖析。
4)流水线工作触发Sonar Scanner扫描,并由scanner将扫描后果发送给SonarQube进行剖析并产生报告。
以上是参考网络上大部分教程能够实现的内容。在理论的我的项目中,可能还须要以下的过程。
5)Jenkins获取SonarQube扫描后果,如覆盖率等指标未达到“品质门禁”的要求,则Jenkins流水线工作失败。
6)Gitlab获取到上述后果,并依据后果承受或者回绝 push。如果是merge request,则标注本次扫描的后果,供合并评审人员参考,当然这样的merege request个别会被评审人员回绝。
至此,一个残缺的由代码提交所触发的工作流程闭环就造成了,如下图所示:
如本文开篇所说,个别介绍三者集成的文章到第三步就完结了,也就是Gitlab 能通过webhook触发Jenkins构建工作,并且能在sonarqube上查看到扫描后果。而一个残缺的MR/Push触发CI的流程应该要将上述后果回馈到Gitlab当中。这当中就须要实现4和5的步骤了。
SonarQube Webhook
通过给SonarQube上的某个我的项目指定WebHook, 就能在该我的项目被触发并实现扫描后果剖析后,调用该Webhook来实现将后果推送给消费者,如Jenkins。
具体的介绍能够参见SonarQube提供的官网阐明:https://docs.sonarqube.org/la...
以下是该Webhook的内容案例:
{ "serverUrl": "http://localhost:9000", "taskId": "AVh21JS2JepAEhwQ-b3u", "status": "SUCCESS", "analysedAt": "2016-11-18T10:46:28+0100", "revision": "c739069ec7105e01303e8b3065a81141aad9f129", "project": { "key": "myproject", "name": "My Project", "url": "https://mycompany.com/sonarqube/dashboard?id=myproject" }, "properties": { }, "qualityGate": { "conditions": [ { "errorThreshold": "80", "metric": "new_coverage", "onLeakPeriod": true, "operator": "LESS_THAN", "status": "NO_VALUE" } ], "name": "SonarQube way", "status": "OK" } }
以上案例中,SonarQube将上述内容post给指定的url。其中应用了一个最为简略的品质门禁,增量代码覆盖率80%。
通过给SonarQube上的某个我的项目指定WebHook, 就能在该我的项目被触发并实现扫描后果剖析后,调用该Webhook来实现将后果推送给消费者,如Jenkins。
也就是说,在Jenkins Pipeline中,咱们会应用相似这样的脚本来发动扫描并期待SonarQube发回品质门禁的后果。
stage ("SonarQube analysis") { steps { withSonarQubeEnv('SonarQube') { sh "mvn clean test sonar:sonar" } def qualitygate = waitForQualityGate() if (qualitygate.status != "OK") { error "Pipeline aborted due to quality gate coverage failure: ${qualitygate.status}" } }}
而上述SonarQube Webhook就是用来告诉 waitForQualityGate的品质门禁的后果的。
从日志上看,在实现Sonar Scanner扫描并向SonarQube发送后果后,首先会进入短暂的In-Progress状态,
而后是Pending,也就是期待SonarQube实现扫描后果并通过Webhook返回后果。
Jenkins在收到后果后,就能够依据品质门禁的后果进行下一步操作了,如不达标就让整个Jenkins job失败,并最终让MR被拒收。
Gitlab Plugin addGitlabComment & updateCommitStatus
https://docs.gitlab.com/12.10...
https://www.jenkins.io/doc/pi...
前一小段有说到,SonarQube通过Webhook告诉Jenkins本次扫描的品质门禁度量后果后,就须要由Jenkins来告诉Gitlab了。这里,也是应用了Gitlab Plugin中的性能。如以下是告诉Gitlab构建胜利的告诉。
stages { stage('gitlab') { steps { echo 'Notify GitLab' updateGitlabCommitStatus name: 'build', state: 'pending' updateGitlabCommitStatus name: 'build', state: 'success' } } }
增量代码覆盖率
在聊完了整个工作流程和数据流转之后,终于能够来到本文的重点,也就是如何取得增量的代码覆盖率了。一般来说能够有两个计划:
1)在Jenkins构建工作中通过自研工具或者例如diff_cover等开源工具来计算增量的代码覆盖率。
这个计划的外围还是jacoco生成的代码覆盖率报告以及git diff获取到的差量代码这两份报告的解析和计算。如果采取该计划,则后续的SonarQube扫描局部就能够是可选动作了。
2) 通过SonarQube来计算增量代码覆盖率。
这个计划的劣势是不须要额定的开发工作或者引入别的工具,并且覆盖率后果连同代码动态扫描后果等能独特造成品质门禁,依靠代码覆盖率、测试用例、违规等来综合判断MR或者Push是否满足合并要求。
增量代码覆盖率-SonarQube
首先,SonarQube反对基于增量代码(new code)的品质门禁。以下是官网提供的一个报告:https://www.sonarqube.org/son...
咱们能够看到SonarQube提供了增量代码的覆盖率、反复率、缺点、安全漏洞等等的度量,并能够基于上述数据来综合判断是否通过品质门禁。案例中,因为设立了增量代码85%的覆盖率,而理论值为72.2%,因而品质门禁未通过。
有理解SonaqQube的读者可能要说了,这个计划存在问题。个别咱们会在master分支或者是develop分支上计算(增量)代码覆盖率。当咱们把待评审的MR/Push代码的扫描后果间接推送到这些分支上的话,如果这个申请通过评审后被回绝,那这些分支上的数据不是被净化了么?因而,间接利用master分支是有问题的。
这里,咱们须要额定利用一个 SonarQube Branch的插件。具体计划是,将待评审的MR/Push的扫描后果推送到一个约定的分支上,如"mr-xxxx"上,这个分支作为一个短分支(short branch),将基于指定的长分支(long branch)进行计算,失去上图的品质门禁计算结果。当然这里的前提是,长分支上的数据和MR/Push的指标分支是实时对应的,否则会引起计算结果的偏差。
具体来说,就是在sonar扫描时指定分支和基线分支,以maven我的项目为例:
mvn clean test sonar:sonar -Dmaven.test.failure.ignore -Dsonar.branch.name=mr-xxx -Dsonar.branch.target=develop
也就是以develop分支为基线,来计算mr-xxx分支绝对于develop的代码增量覆盖率,以及动态代码扫描后果,并计算品质门禁后果。
因为SonarQube在社区版上并不提供多分支扫描的性能,因而只有洽购develop以上的版本能力具备次性能,或者是在github上应用开源社区提供的sonarqube-community-branch-plugin。
## 总 结
上述计划中,额定利用了
- SonarQube Webhook
- SonarQube 分支插件 和长短分支概念
就能在个别三者集成的计划中实现增量代码覆盖率和品质门禁。
起源:软件测试那些事
作者:IDCF社区 风月同天测试人