Jacoco 是⼀个开源的覆盖率⼯具。Jacoco 可以嵌⼊到 Ant 、Maven 中,并提供了 EclEmma Eclipse 插件,也可以使⽤ Java Agent 技术监控 Java 程序。很多第三⽅的⼯具提供了对 Jacoco 的集成,如 sonar、Jenkins、IDEA。Jacoco 包含了多种尺度的覆盖率计数器,包含指令级(Instructions,C0 coverage),分⽀(Branches,C1 coverage)、圈复杂度(Cyclomatic Complexity)、⾏(Lines)、⽅法(Non-abstract Methods)、类(Classes)
这是对jacoco 的功能和使⽤的简介,我就不需要过多的描述。我的这篇⽂章就是⼀个对docker中服务的⼀个功能测试+⾃动测试覆盖率统计的demo:
我将从以下⼏点进⾏阐述:
1. docker 底层⽂件开放变量2. ⾃助式jenkins JOB创建3. Pipeline ⾃助式覆盖率统计⼀ docker 底层⽂件开放变量:
这⾥开放变量的作⽤是决定 ⾃助式jenkins JOB 是否执⾏jacoco 覆盖率代码扫描。因为我们是通过jacocoAgent 这种⽅式来实现代码覆盖率扫描的。并不是所有的服务都需要进⾏代码覆盖率扫描,所以我们做成了这种参数化,⽅便⾃助决定是否进⾏覆盖率扫描。你可能会有疑问为什么不写死呢?答案是:我们的测试环境中的docker底层⽂件⽤的是同⼀套。
开放变量的参数是:-javaagent:/usr/local/jacoco-agent.jar=includes=*,output=tcpserver,append=true,address=0.0.0.0,port=*****这⾥的这个参数传递是在 第⼆个环节⾃助式jenkins JOB 创建 中设置的⼀个输⼊标签。⼆ ⾃助式jenkins JOB创建:创建:
前期可爱的运维同事,帮助我们创建了⼀个通⽤的⾃助构建服务的模板:
1、jobName <必填>选项,命名格式:环境-服务名
2、service_name <必填>服务名称,请对应gitlab上项⽬名称和⽣成的jar包名称 3、app_repo <必填>项⽬仓库地址,必须以git@开头的ssh地址
4、jvm_opts(开放变量) <可选填>⾃定义jvm参数,除默认配置jvm参数之外的⾃定义jvm参数,默认为空 这⾥由于我们需要运⾏jacoco-agent,所以输⼊:-javaagent:/usr/local/jacoco- agent.jar=includes=*,output=tcpserver,append=false,address=0.0.0.0,port=****
点击build,会⾃动⽣成build后job的地址
点击链接,⾃跳转到job
点击build with parameters
如上图所⽰ 点击build with parameters后 1、2、3会⾃动填上之前的参数,这⾥我们只需要选着4、5 部署的分⽀和部署环境就完成了⾃助式jenkins JOB创建。下⾯你就可以进⾏功能测试和⾃动化测试了。
接下来的重点是如何拉取代码覆盖率报告:
这⾥需要注意的是,jacocoAgent 记录了代码执⾏的轨迹,如果想通过**.exec 获取html报告,我们需要有对应分⽀的.class ⽂件才可能实现。这⾥参照sonar扫描⼀样的⽅式获取class⽂件。我们通过PipeLine的⽅式通过编译对应分⽀的代码获取class⽂件。三 Pipeline ⾃助式覆盖率统计
这⾥的的⼯作主要是通过build 获取class⽂件,通过.exec⽂件⽣成覆盖率报告在jenkins上展⽰出来那么是如何是实现的呢?
1、也需要运维像第⼀部⼀样创建⼀个公共job 作⽤仅仅是build操作,⽽不需要deploy2、需要在git上创建⼀个PipeLine公共脚本 PipleLine 开放⼏个公共标签 标签内容是:
服务名称:service_name 务器地址:address
编译后⽣成的classes⽂件相对路径:classPattern 剔除⽆需统计具体的classes⽂件:exclusionPattern 源码路径:sourcePattern 仓库地址:app_repo
脚本如下:
pipelineJob(\"$jobName\") { parameters {
stringParam(\"service_name\", \"${service_name}\",'服务名称') stringParam('address', \"${address}\", '服务器地址')
stringParam(\"classPattern\", \"${classPattern}\", '编译后⽣成的classes⽂件相对路径')
stringParam('exclusionPattern', \"${exclusionPattern}\", '剔除⽆需统计具体的classes⽂件,多个以英⽂逗号,隔开。') stringParam('sourcePattern', \"${sourcePattern}\", '源码路径。') stringParam('app_repo', \"${app_repo}\", '仓库地址')
gitParameter {
name('branch_name') branch('')
type('PT_BRANCH') defaultValue('master') description('')
branchFilter('origin/(.*)') quickFilterEnabled(true) tagFilter('*')
sortMode('ASCENDING_SMART') selectedValue('TOP')
useRepository(\"$app_repo\") }
}
definition { cpsScm { scm { git {
remote {
url('git@gitlab.***.cn:***/jenkinspipeline.git') credentials('*********************') }
branch('*/master') } }
scriptPath(\"Jenkinsfile-Jacoco\") } }}
jenkinspipeline (git⽂件)
pipeline {
agent {node {label 'k8s-slave'}} environment {
def JAVA_HOME=\"/usr/local/jdk\" def M2_HOME=\"/usr/local/maven\" def MAVEN_OPTS=\"-Xmx1024m\"
def PATH=\"/opt/kube/bin:/bin:/sbin/:/usr/bin:/usr/sbin/:/usr/local/bin:$PATH\"
def dingding_url=\"https://oapi.dingtalk.com/robot/send?access_token=**************************\" def harbor_server=\"***************\" def harbor_auth_id=\"**********************\" def git_auth_id=\"*********************\"
def ansible_repo=\"git@gitlab.*********************.git\" def app_repo=\"git@gitlab.*********************.git\" }
options {
//默认是启⽤并发构建,disableConcurrentBuilds如果开启则为禁⽤并发构建// disableConcurrentBuilds() //保持构建的最⼤个数
buildDiscarder(logRotator(numToKeepStr: '20')) ansiColor('xterm') timestamps() }
parameters {
choice(name: 'service_name', choices: '*********************')
gitParameter(name: 'branch_name', branchFilter: 'origin/(.*)', defaultValue: 'master', type: 'PT_BRANCH', quickFilterEnabled: 'true', description: '选择需要构建的分⽀', sortMode: 'ASCENDING_SMART') }
post{ success{ script {
dingTalk accessToken: \"${env.dingding_url}\", imageUrl: '*********************', jenkinsUrl: \"${env.BUILD_URL}\",message: \"应⽤${service_name}构建成功!\",notifyPeople: '*********************' wrap([$class: 'BuildUser']) {
mail to: \"${BUILD_USER_EMAIL}\", from: \"*********************\",
subject: \"'${JOB_NAME}' 第${BUILD_NUMBER}次,构建结果通知【成功】\",
body: \"本次构建由 ${BUILD_USER} 发起,构建【成功】,构建版本 ${params.service_name}:${params.branch_name} .\\n具体构建细节,可以前往${env.BUILD_URL}进⾏查看。\" }
} cleanWs() }
failure{ script {
dingTalk accessToken: \"${env.dingding_url}\", imageUrl: '*********************', jenkinsUrl: \"${env.BUILD_URL}\",message:\"应⽤${service_name}构建失败!\",notifyPeople: '*********************' wrap([$class: 'BuildUser']) {
mail to: \"${BUILD_USER_EMAIL}\", from: \"*********************\",
subject: \"'${JOB_NAME}' 第${BUILD_NUMBER}次,构建结果通知【失败】\",
body: \"本次构建由 ${BUILD_USER} 发起,构建【失败】 ,构建版本 ${params.service_name}:${params.branch_name} .\\n具体构建细节,可以前往${env.BUILD_URL}进⾏查看。\" }
} }
unstable{ script {
wrap([$class: 'BuildUser']) {
mail to: \"${BUILD_USER_EMAIL}\", from: \"*********************\",
subject: \"'${JOB_NAME}' 第${BUILD_NUMBER}次,构建结果通知【失败】\",
body: \"本次构建由 ${BUILD_USER} 发起,构建【失败】,构建版本 ${params.service_name}:${params.branch_name} .\\n具体构建细节,可以前往${env.BUILD_URL}进⾏查看。\" } } } }
stages {
stage(\"获取代码\") { parallel{
stage('配置构建信息') { steps { script {
wrap([$class: 'BuildUser']){
currentBuild.description = \"本次构建由 ${BUILD_USER} 发起,构建版本 ${params.service_name}:${params.branch_name}stage(\"获取应⽤代码\") { steps { echo \"branch_name: ${params.branch_name}\" sh 'git config --global http.sslVerify false' wrap([$class: 'AnsiColorBuildWrapper', 'colorMapName': 'xterm']) { dir ( \"${env.WORKSPACE}\" ) { git ( branch: \"${params.branch_name}\", credentialsId: \"${env.git_auth_id}\", url: \"${app_repo}\" ) } } } } } } stage(\"jacoco覆盖率统计\") { steps { dir(\"${env.WORKSPACE}\") { sh \"pwd\" sh \"mvn clean install -Dmaven.test.skip=true org.jacoco:jacoco-maven-plugin:0.8.2:dump -Djacoco.address=\\\"${params.address}\\\" -Djacoco.port=********************* -Djacoco.destFile=jacoco_payment.exec -Djacoco.reset=false jacoco(execPattern:'jacoco_payment.exec',classPattern:\"${params.classPattern}\",sourcePattern:\"${params.sourcePattern}\",exclusionPattern:\"${params.exclusionPattern}\") } } } }} 上⾯的PipeLine 配置好了 下⾯ 看看 页⾯ 注:第⼀次只能选择master分⽀。后⾯可以选择对应的分⽀了 好了 到此结束 因篇幅问题不能全部显示,请点此查看更多更全内容