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.
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=12345Key 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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
