通过代码方式使用Jacoco远程统计tomcat服务的代码覆盖率

1)修改远程tomcat下的bin/catalina.sh中JAVA_OPTS的配置
----------------------------------------------------------------
# -javaagent: 的后面跟jacoco的安装路径
# includes= 选项,选择你要覆盖率的服务
# port= 选项,选择你要打开的端口
# address= 选项,tomcat服务所在机器的ip地址(如果想在跟tomcat服务同一台机器上执行ant任务的话,需要改为127.0.0.1)

----- Execute The Requested Command ------------------------------
JAVA_OPTS="-javaagent:/path/to/your/jacoco_0.8.5/lib/jacocoagent.jar=includes=com.*,output=tcpserver,port=8893,address=10.81.14.77"

2)在开发环境pom.xml中引入jacoco的jar包

<!--使用jacoco对web工程生成全部的覆盖率报告-->
        <dependency>
            <groupId>org.jacoco</groupId>
            <artifactId>org.jacoco.core</artifactId>
            <version>0.8.5</version>
        </dependency>

        <dependency>
            <groupId>org.jacoco</groupId>
            <artifactId>org.jacoco.report</artifactId>
            <version>0.8.5</version>
        </dependency>

3)调用代码实现

package com.wangfg.jacoco;

import org.jacoco.core.data.ExecutionDataWriter;
import org.jacoco.core.runtime.RemoteControlReader;
import org.jacoco.core.runtime.RemoteControlWriter;
import org.junit.Test;

import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;

/**
 * 用于生成xxx.exec数据的程序
 */
public class ExecutionDataClient {
    private static final String DESTFILE = "jacoco-client.exec";
 
    private static final String ADDRESS = "127.0.0.1";
 
    private static final int PORT = 8044;
 
    /**
     * Starts the execution data request.
     * 
     * @throws IOException
     */
    @Test
    public  void test() throws IOException {
        final FileOutputStream localFile = new FileOutputStream(DESTFILE);
        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, false);
        reader.read();
 
        socket.close();
        localFile.close();
    }

}

  

package com.wangfg.jacoco;

import org.jacoco.core.analysis.Analyzer;
import org.jacoco.core.analysis.CoverageBuilder;
import org.jacoco.core.analysis.IBundleCoverage;
import org.jacoco.core.tools.ExecFileLoader;
import org.jacoco.report.DirectorySourceFileLocator;
import org.jacoco.report.FileMultiReportOutput;
import org.jacoco.report.IReportVisitor;
import org.jacoco.report.html.HTMLFormatter;
import org.junit.Test;

import java.io.File;
import java.io.IOException;

public class ReportGenerator {

    private final String title = "jacoco-demo";
    private final File executionDataFile = new File("C:\\Users\\Administrator\\Downloads\\jacoco\\jacoco-client.exec");
    private final File classesDirectory = new File("C:\\Users\\Administrator\\Downloads\\jacoco\\target\\classes\\com\\wangfg\\jacoco\\controller");
    private final File sourceDirectory= new File("C:\\Users\\Administrator\\Downloads\\jacoco\\src");
    private final File reportDirectory = new File("C:\\Users\\Administrator\\Downloads\\jacoco\\coveragereport");

    private ExecFileLoader execFileLoader;

    /**
     * Create the report.
     *
     * @throws IOException
     */
    @Test
    public void test() throws IOException {
        // Read the jacoco.exec file. Multiple data files could be merged
        // at this point
        loadExecutionData();

        // Run the structure analyzer on a single class folder to build up
        // the coverage model. The process would be similar if your classes
        // were in a jar file. Typically you would create a bundle for each
        // class folder and each jar you want in your report. If you have
        // more than one bundle you will need to add a grouping node to your
        // report
        final IBundleCoverage bundleCoverage = analyzeStructure();
        createReport(bundleCoverage);

    }

    private void createReport(IBundleCoverage bundleCoverage)
            throws IOException {

        // Create a concrete report visitor based on some supplied
        // configuration. In this case we use the defaults
         HTMLFormatter htmlFormatter = new HTMLFormatter();
         IReportVisitor visitor = htmlFormatter
                .createVisitor(new FileMultiReportOutput(reportDirectory));

        // Initialize the report with all of the execution and session
        // information. At this point the report doesn't know about the
        // structure of the report being created
        visitor.visitInfo(execFileLoader.getSessionInfoStore().getInfos(),
                execFileLoader.getExecutionDataStore().getContents());

        // Populate the report structure with the bundle coverage information.
        // Call visitGroup if you need groups in your report.
        visitor.visitBundle(bundleCoverage, new DirectorySourceFileLocator(
                sourceDirectory, "utf-8", 4));

        // Signal end of structure information to allow report to write all
        // information out
        visitor.visitEnd();

    }

    private void loadExecutionData() throws IOException {
        execFileLoader = new ExecFileLoader();
        execFileLoader.load(executionDataFile);
    }

    private IBundleCoverage analyzeStructure() throws IOException {
         CoverageBuilder coverageBuilder = new CoverageBuilder();
         Analyzer analyzer = new Analyzer(
                execFileLoader.getExecutionDataStore(), coverageBuilder);
        analyzer.analyzeAll(classesDirectory);
        return coverageBuilder.getBundle(title);
    }

}

 4)分别执行以上代码即可得到远程代码的覆盖率。

posted @ 2020-02-14 17:47  wangfg  阅读(601)  评论(0编辑  收藏  举报