Operations 7 min read

Integrating JaCoCo Code Coverage into Jenkins for Multi‑Server Java API Testing

This guide explains how to embed JaCoCo into Tomcat startup, use Ant build scripts to collect and merge execution data across three servers, generate HTML coverage reports, and centralize them for easy viewing in a Jenkins‑driven API testing pipeline.

FunTester
FunTester
FunTester
Integrating JaCoCo Code Coverage into Jenkins for Multi‑Server Java API Testing

To quantify the effectiveness of API test cases, the author introduces code coverage as a key metric and outlines a practical solution involving JaCoCo, Jenkins, and Ant across three separate machines: the service JVM host, the Jenkins build server, and the test script server.

JaCoCo Agent Configuration

The JaCoCo agent is added to the Tomcat container's startup script via the -javaagent option in JAVA_OPTS:

-javaagent:/home/jmsmanager/jacoco/lib/jacocoagent.jar=includes=com.noriental.*,output=tcpserver,address=127.0.0.1,port=12345

Key parameters:

includes : package pattern to instrument (e.g., com.noriental.*).

output : type of output, default is tcpserver.

address : IP address of the service (use 127.0.0.1 for local).

port : chosen TCP port for the JaCoCo server.

Ant build.xml Setup

The Ant script defines properties for paths, the JaCoCo library, and the remote server IP, then declares three main targets: merge, dump, and report.

<?xml version="1.0" ?>
<project name="user-center" basedir="/home/jmsmanager/report/user-center"
         xmlns:jacoco="antlib:org.jacoco.ant"
         xmlns:sonar="antlib:org.sonar.ant" default="all">
    <!-- Project name -->
    <property name="projectName" value="user-center"/>
    <!-- JaCoCo Ant library path -->
    <property name="jacocoantPath" value="/home/jmsmanager/jacoco/lib/jacocoant.jar"/>
    <!-- Report output folder -->
    <property name="reportfolderPath" value="${basedir}/report/"/>
    <property name="server_ip" value="127.0.0.1"/>
    <property name="waterommpClasspath" value="/home/jmsmanager/report/${projectName}/source/BOOT-INF/classes/com/noriental/center/moudle/"/>
    <property name="mcmSrcpath" value="${basedir}/source/src/main/java"/>
    <taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
        <classpath path="${jacocoantPath}"/>
    </taskdef>

    <!-- Merge multiple .exec files into one -->
    <target name="merge" depends="dump">
        <jacoco:merge destfile="jacoco.exec">
            <fileset dir="${basedir}" includes="*.exec"/>
        </jacoco:merge>
    </target>

    <!-- Dump coverage data from the remote JVM -->
    <target name="dump">
        <jacoco:dump address="${server_ip}" reset="false" destfile="${basedir}/jacoco.exec" port="12347" append="true"/>
    </target>

    <!-- Generate HTML, CSV, and XML reports -->
    <target name="report">
        <delete dir="${reportfolderPath}"/>
        <mkdir dir="${reportfolderPath}"/>
        <jacoco:report>
            <executiondata>
                <file file="${basedir}/jacoco.exec"/>
            </executiondata>
            <structure name="JaCoCo Report">
                <group name="User Center Coverage Report">
                    <classfiles>
                        <fileset dir="${waterommpClasspath}">
                            <exclude name="**/request/*.class"/>
                            <exclude name="**/response/*.class"/>
                        </fileset>
                    </classfiles>
                    <sourcefiles encoding="UTF-8">
                        <fileset dir="${mcmSrcpath}"/>
                    </sourcefiles>
                </group>
            </structure>
            <html destdir="${reportfolderPath}" encoding="utf-8"/>
            <csv destfile="${reportfolderPath}/report.csv"/>
            <xml destfile="${reportfolderPath}/report.xml"/>
        </jacoco:report>
    </target>
</project>

The dump target contacts the JaCoCo agent running on the service JVM, retrieves the execution data, and writes it to jacoco.exec. The merge target combines multiple .exec files when testing several modules. Finally, the report target deletes any previous report directory, creates a fresh one, and produces HTML, CSV, and XML reports based on the collected data and the compiled class files.

Centralizing the Report

Because the service runs on a separate machine and multiple machines are involved, the generated HTML report is copied to a designated server where it can be accessed via a web browser, providing a unified view of coverage across all test runs.

For further discussion, readers are invited to view the original article and join the conversation.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Javacode coverageci/cdJaCoCoJenkinsAnt
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.