Jacoco is an open-source code coverage library for Java distributed under the Eclipse Public License. The library is often used in Java projects to measure the coverage of unit or integration tests. But it's also possible to measure the coverage of any test, using a running application, with the Jacoco agent.
The first step is to download the latest release build in zip format and extract the zip file. After that, the jacocoagent.jar file and the jacococli.jar file from the lib directory should be placed in a known directory, such as the root directory of the Java project.
A simple Spring Boot controller class with a GET and a POST endpoint is used to demonstrate the Jacoco agent:
@RestController
public class CarRestController {
List<Car> carList = new ArrayList<>();
public CarRestController() {
Car huayra = new Car("Pagani", "Huayra");
carList.add(huayra);
}
@GetMapping("/car")
public List<Car> retrieveCar() {
return carList;
}
@PostMapping(path = "/car")
public Car addCar(@RequestBody Car car) {
carList.add(car);
return car;
}
}
Alternatively, any Java framework can be used with any interface; REST is not required. Now the Java application should be started while attaching the Java agent to the Java process:
java -javaagent:jacocoagent.jar=destfile=target/jacoco.exec,append=false,
includes=com.example.* -jar target/jacoco-agent-0.0.1-SNAPSHOT.jar
The destination file, which will eventually contain the coverage results, is specified in the destfile argument. In order to recreate the destination file every time the application is started, the append=false is used. By default, the coverage for all classes is measured including all Java and Spring packages. The argument includes=com.example.* is used to only measure the coverage for the example project. Lastly, the jar file of the example application with the REST controller is supplied. The Java Agent documentation for Jacoco provides more information about the configuration options.
At this point, the example application is running and can be tested by opening the URL http://localhost:8080/car
in a browser or by executing curl http://localhost:8080/car
on the command line. The coverage file target/jacoco.exec
is already created, but it's still empty. The test application with the /car
endpoint should be stopped and then the coverage information is automatically written to the destination file.
Unfortunately, the coverage file isn't human readable, however it may be converted to HTML pages with the Jacoco Command Line Interface (CLI) tool:
java -javaagent:jacocoagent.jar=destfile=target/jacoco.exec,append=false,
includes=com.example.* -jar target/jacoco-agent-0.0.1-SNAPSHOT.jar
Both the class files and source files are required for a proper coverage report. The above command creates a HTML report, but it's also possible to create a XML report, which may be imported in tools such as SonarQube. The Command Line Interface documentation provides a complete overview of all the options.
Now, the index.html from the target folder may be displayed in a browser to view the code coverage of the application:
After clicking on the com.example package, the various classes of the application are shown:
Clicking on the CarRestController
class
shows the methods of that class
:
Now clicking on any of the methods shows the code coverage of the CarRestController
class
. Most of the logic is covered by our test, except for the addCar()
method, as we didn't send a POST
request to the application:
The example demonstrates how the Jacoco agent is used to measure the code coverage of a running application. This can be used to measure the coverage of a system test, performance test, a feature test, a test which interacts with Java via some frontend language, etcetera.
This supports various use cases, for example if a project has a feature test that covers all the features, then measuring the coverage shows potential dead code. Of course, the feature test doesn't test all corner cases, but if large parts of the code aren't tested, then either the feature test is incomplete, or dead code may be removed. The agent also makes it possible to measure the code coverage of external libraries, frameworks and Java itself. That may be used to determine the actual usage of third party tools, for example when there's a need to update or replace one of them. It's even possible to measure the code coverage of real user interactions on acceptance or even production environments, however this might decrease the performance of the application.
Sebastian Daschner, co-founder and CTO at Fairsource, created an interesting blog and video to explain the Jacoco agent.