当要求品质内建、测试左移、继续集成、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 社区 风月同天测试人