您的当前位置:首页正文

功能+自动化测试代码覆盖率统计(jacoco-demo)

2021-03-06 来源:步旅网
功能+⾃动化测试代码覆盖率统计(jacoco-demo)

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分⽀。后⾯可以选择对应的分⽀了

好了 到此结束

因篇幅问题不能全部显示,请点此查看更多更全内容