jacoco的原理就不进行介绍了,网上资料也比较多,大家可以看看。
原理写的比较好的是这篇,可惜图没了:
https://blog.csdn.net/gc_cg/article/details/53172053
不扯没用的,直接开始:
一、环境说明:
(为了避免暴露公司真实的数据,文中出现的ip和文件路径为笔者虚拟的,但是并不影响大家阅读与实践,请大家谅解。)
tomcat一台:192.168.10.11 -----用于展示最终的测试覆盖率数据报告。
jenkins一台:192.168.10.22-----用于统一获取源码,统一收集代码覆盖率数据。
应用服务器200台:192.168.20.*、192.168.22.* ----用于部署各种java微服务,并且进行jacoco插桩。(各个应用服务器均有配置jenkins服务器的公钥,jenkins服务器能够免密ssh这些应用服务器。)
二、jacoco插桩
step1.首先向200台应用服务器上传jacoco包
下载jacoco并且上传到jenkins的服务器上:
wget "http://search.maven.org/remotecontent?filepath=org/jacoco/jacoco/0.8.3/jacoco-0.8.3.zip"
准备一个host_list文件,里面是这200台服务器的ip。
编写scp脚本
#! /bin/bash
set -x
host_list=$(cat host_list)
for host in ${host_list[@]} ; do
scp -r ./jacoco testuser@${host}:/home/testuser
ssh testuser@${host} "cd /home/testuser;if [ ! -d jacoco ];then exit 1;fi;"
done
把脚本、解压后的jacoco文件夹放在同一路径下面,执行脚本即可。
这些应用服务器上传完毕之后,不再需要做其他操作了。
step2.在jenkins上修改服务的启动脚本:
例如原本脚本是这个样子:
#!/bin/bash
jar=$1
productname=$(echo ${jar%.*})
nohup java -Xmx1024M -Xms1024M -jar /opt/$jar >/opt/logs/${productname}.log 2>&1 &
ps -ef |grep ${productname}
插桩命令:
-javaagent:/home/testuser/jacoco/lib/jacocoagent.jar=includes=*,output=tcpserver,address=0.0.0.0,port=6300
加入jacoco插桩命令之后:
#!/bin/bash
jar=$1
productname=$(echo ${jar%.*})
nohup java -javaagent:/home/testuser/jacoco/lib/jacocoagent.jar=includes=*,output=tcpserver,address=0.0.0.0,port=6300 -Xmx1024M -Xms1024M -jar /opt/$jar >/opt/logs/${productname}.log 2>&1 &
ps -ef |grep ${productname}
jenkins的部署脚本在每次部署时会将这个启动脚本scp到每个应用服务器上,并且执行这个脚本,因此插桩动作到这里就完成了。
三、收集覆盖率信息
我们采用ant收集覆盖率信息,其实jacoco的收集覆盖率信息方法有很多种,大家也可以进行更多的了解。
step1:编写ant的build.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!--
ant脚本参数说明:
appName:业务服务名 report参数
IP:业务服务运行机器IP dump、report必须参数
srcDir:业务服务源码文件存放路径 report参数
classDir:业务服务class文件存放路径 report参数
reportDir:报告生成目录路径 report参数
execFile:覆盖率信息文件 dump、report参数
-->
<project name="JaCoCo coverage report" default="rebuild" xmlns:jacoco="antlib:org.jacoco.ant">
<description>
JaCoCo coverage report
</description>
<property name="appName" value="" />
<property name="srcDir" value="${srcDir}" />
<property name="classDir" value="${classDir}" />
<property name="reportDir" value="${reportDir}" />
<property name="execFile" value="${execFile}" />
<property name="ip" value="${ip}" />
<property name="src.dir" location="${srcDir}" />
<property name="result.classes.dir" location="${classDir}" />
<property name="result.report.dir" location="${reportDir}" />
<property name="result.exec.file" location="${execFile}" />
<!-- Step 1: Import JaCoCo Ant tasks -->
<taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
<classpath path="/opt/jacoco/lib/jacocoant.jar" />
</taskdef>
<target name="report">
<!-- Step 3: Create coverage report -->
<jacoco:report>
<!-- This task needs the collected execution data and ... -->
<executiondata>
<file file="${result.exec.file}" />
</executiondata>
<!-- the class files and optional source files ... -->
<structure name="${appName} JaCoCo coverage report">
<classfiles>
<fileset dir="${result.classes.dir}" />
</classfiles>
<sourcefiles encoding="UTF-8">
<fileset dir="${src.dir}" />
</sourcefiles>
</structure>
<!-- to produce reports in different formats. -->
<html destdir="${result.report.dir}" />
<csv destfile="${result.report.dir}/report.csv" />
<xml destfile="${result.report.dir}/report.xml" />
</jacoco:report>
</target>
<target name="dump">
<jacoco:dump address="${ip}" reset="false" destfile="${result.exec.file}" port="6300" append="
true"/>
</target>
</project>
注意修改一下上面的这一行即可,改成你实际的jacoco文件路径,其他的内容都不用修改,可以直接使用:
<classpath path="/opt/jacoco/lib/jacocoant.jar" />
step2.安装ant
在jenkins所在的服务器上安装ant:
下载地址:https://ant.apache.org/bindownload.cgi
选择:
上传到jenkins服务器上并且解压即可
step3.修改jenkins部署脚本
添加一个收集jacoco覆盖率报告的方法:
function collectjacocoreport()
{
cp /test/build.xml ${workspace} #将build.xml复制到jenkins当前工作空间
ant dump -DexecFile=${workspace}/jacoco.exec -Dip="${ip}" -DappName="${service_name}" #收集当前应用所在服务器的覆盖率信息
mkdir -p /test/jacocoReport/${service_name} #jenkins服务器本地建立报告存储文件夹
ant report -DsrcDir=${workspace}/src/main/java -DclassDir=${workspace}/build/classes/java/main -DreportDir=/test/jacocoReport/${service_name} -DexecFile=${workspace}/jacoco.exec -Dip="${ip}" -DappName=${service_name} #使用ant生成覆盖率报告
ssh saicapp@192.168.10.11 "cd ${tomcatdir}/${service_name};ls | grep -v bak | xargs rm -rf;if [ -d bak ];then find ./bak -mtime +7 -name "build*" | xargs rm -rf;fi" #tomcat服务器上对老旧的覆盖率报告的和备份进行清理
cd /test/jacocoReport/ && scp -r ./${service_name} saicapp@192.168.10.11:${tomcatdir}/${service_name}/build_${BUILD_ID}_report #将jenkins生成的覆盖率报告发送到tomcat服务器
ssh saicapp@192.168.10.11 "cd ${tomcatdir};mkdir -p ${service_name}/bak;cp -r ./${service_name}/build_${BUILD_ID}_report ./${service_name}/bak" #在tomcat服务器上备份本次的覆盖率报告
}
四、实现的效果
jenkins构建过程中jacoco相关日志:
+ collectjacocoreport
+ cp /test/build.xml /app/jenkins/data/workspace/test-project
+ ant dump -DexecFile=/app/jenkins/data/workspace/test-project/jacoco.exec -Dip=192.169.20.132 -DappName=test-project
Buildfile: /app/jenkins/data/workspace/test-project/build.xml
dump:
[jacoco:dump] Connecting to /192.168.20.132:6300
[jacoco:dump] Dumping execution data to /app/jenkins/data/workspace/test-project/jacoco.exec
BUILD SUCCESSFUL
Total time: 0 seconds
+ mkdir -p /test/jacocoReport/test-project
+ ant report -DsrcDir=/app/jenkins/data/workspace/test-project/src/main/java -DclassDir=/app/jenkins/data/workspace/test-project/build/classes/java/main -DreportDir=/test/jacocoReport/tripdispatch -DexecFile=/app/jenkins/data/workspace/test-project/jacoco.exec -Dip=192.168.20.132 -DappName=test-project
Buildfile: /app/jenkins/data/workspace/test-project/build.xml
report:
[jacoco:report] Loading execution data file /app/jenkins/data/workspace/test-project/jacoco.exec
[jacoco:report] Writing bundle 'tripdispatch JaCoCo coverage report' with 115 classes
BUILD SUCCESSFUL
Total time: 1 second
报告展示:
http://192.168.10.11:8080/test-project/ (也可以写一个index.html,将你的微服务清单在页面上做一个索引。)
build_39_report的”39“表示此份报告来自于jenkins的第39次构建。
覆盖率报告展示:
具体的代码文件名称涉及公司业务,做了模糊处理,请大家谅解
如有疑问请留言~