功能测试+自动化测试代码覆盖率统计
是一个开源的覆盖率工具。Jacoco 可以嵌入到 Ant 、Maven 中,并提供了 EclEmma Eclipse 插件,也可以使用 Java Agent 技术监控 Java 程序。很多第三方的工具提供了对 Jacoco 的集成,如 sonar、Jenkins、IDEA。
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:
我将从以下几点进行阐述:
- docker 底层文件开放变量
- 自助式jenkins JOB创建
- 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操作,而不需要deploy
2、需要在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 = "本次构建由<strong><span style='color:#E53333;'> ${BUILD_USER} </span></strong>发起,构建版本 <strong><span style='color:#E53333;'>${params.service_name}:${params.branch_name}</span></strong>"
}
}
}
}
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分支。后面可以选择对应的分支了

这篇贴子到这里就结束了,最后,希望看这篇帖子的朋友能够有所收获。
学习上
作为一个软件测试的过来人,我想尽自己最大的努力,帮助每一个伙伴都能顺利找到工作。所以我整理了下面这份资源,现在免费分享给大家,有需要的小伙伴可以关注【公众号:开心螺蛳粉】自提!

软件测试面试文档
我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

行动吧,在路上总比一直观望的要好,未来的你肯定会感谢现在拼搏的自己!如果想学习提升找不到资料,没人答疑解惑时,请及时加入群:1150305204,里面有各种测试开发资料和技术可以一起交流哦。
更多推荐




所有评论(0)