撸主最近在做CI这块的东西,需要通过jacoco获取远程机器上的覆盖率,于是做了一些实践,做完之后顺便博客上记录一下。
注入jacoco有很多种方法,官网上提供了ant,maven,agent代理等方法,这里主要还是用到agent代理,请查看文档http://www.jacoco.org/jacoco/trunk/doc/agent.html
一、下载agent jar包
进入页面 http://www.jacoco.org/jacoco/trunk/index.html,下载jacocoagent.jar, 然后放置到tomcat所在的服务器上。
二、修改tomcat启动脚本
进入tomcat的bin目录下,打开 catalina.sh ,然后在最上面加入如下代码
JAVA_OPTS="-server -javaagent:/home/test/app/tmp/jacocoagent.jar=includes=*,output=tcpserver,port=8494,address=*,append=false"
其中参数的意思请参考文档http://www.jacoco.org/jacoco/trunk/doc/agent.html
我大概解释下我这边参数的意思,
-javaagent 表明指定java代理
includes=* 表示获取覆盖率的包名,通常使用com.xxx.xx, *表示计算所有覆盖率
output=tcpserver 表示启动tcp服务,对外暴露,客户端通过连接tcp服务获取jacoco.exec
address=* 表示绑定tcp服务绑定的ip地址
三、编写dump小工具,从远程服务器上将jacoco覆盖率文件dump下来
接下来就可以通过代码的方式拿到jacoco覆盖率文件了,java代码如下
public void dump(String ADDRESS, int PORT) throws IOException {
final FileOutputStream localFile = new FileOutputStream("jacoco.exec");
final ExecutionDataWriter localWriter = new ExecutionDataWriter(
localFile);
// Open a socket to the coverage agent:
final Socket socket = new Socket(InetAddress.getByName(ADDRESS), PORT);
final RemoteControlWriter writer = new RemoteControlWriter(
socket.getOutputStream());
final RemoteControlReader reader = new RemoteControlReader(
socket.getInputStream());
reader.setSessionInfoVisitor(localWriter);
reader.setExecutionDataVisitor(localWriter);
// Send a dump command and read the response:
writer.visitDumpCommand(true, true); //reset置为true,表示每次执行dump之后重置覆盖率
if (!reader.read()) {
throw new IOException("Socket closed unexpectedly.");
}
socket.close();
localFile.close();
}
这样跑完程序之后,就会在本地生成jacoco.exec文件
四、使用jenkins生成jacoco报表
拿到jacoco.exec之后,想生成覆盖率报告,前提条件是一定要能拿到源码,覆盖率报告也是基于源码的,所以正确的步骤如下
1. 拿到jacoco.exec
2.拿到对应系统的源代码
3. 编辑打包源码
4. 基于源码和打包文件,以及jacoco生成覆盖率
这一些列步骤正好可以使用jenkins来帮助我们完成,看jenkins配置如下
最后附上Integration-tool的源码