Friday, November 20, 2020

Add Code Coverage Reports to Eclipse, Maven, and Jenkins

Code coverage may provide some insights in your tests. They show which classes, lines of codes, and conditional branches are called by your tests. A high percentage of coverage does not automatically mean that your tests are great - as you might not have a single assertion in your test code - but at least they can give you an impression of dark areas in your code base.

This article is heavily based on the article of Lorenzo Bettini on JaCoCo Code Coverage and Report of multiple Eclipse plug-in projects, so the credits for this setup are his!

Step 1: Eclipse IDE Setup

Coverage in Java projects is typically tracked with the JaCoCo library. The according plugin for Eclipse is called EclEmma and is available via the Eclipse Marketplace.

After installation you have a new run target 

that adds coverage information to your execution. Only thing to do is to rerun your unit tests and check out the Coverage view.


Multiple coverage sessions can be combined into one. That allows to accumulate the results of multiple unit tests into a single coverage report.

Step 2: Tycho integration

For the next steps I expect that you basically followed my tycho tutorials and have a similar setup.

First we need to enable JaCoCo in our builds:

	<build>
		<plugins>
			<!-- enable JaCoCo code coverage -->
			<plugin>
				<groupId>org.jacoco</groupId>
				<artifactId>jacoco-maven-plugin</artifactId>
				<version>0.8.6</version>

				<configuration>
					<output>file</output>
				</configuration>

				<executions>
					<execution>
						<id>jacoco-initialize</id>
						<phase>pre-integration-test</phase>
						<goals>
							<goal>prepare-agent</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>

Tycho surefire executes unit tests in the maven integration-test phase, therefore we start the agent right before. This plugin needs to be active for any plugin of type eclipse-plugin-test (see tycho tutorial), but it is safe to put it in the master pom of your *.releng project.

Now each test run creates coverage reports. For analysis purposes we need to merge them into a single one. Therefore create a new General/Project in your workspace, named *.releng.coverage. In the pom.xml file we need to add a step to aggregate all reports into one:

	<build>
		<plugins>
			<plugin>
				<groupId>org.jacoco</groupId>
				<artifactId>jacoco-maven-plugin</artifactId>
				<version>${jacoco.version}</version>
				<executions>
					<execution>
						<phase>verify</phase>
						<goals>
							<goal>report-aggregate</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>

Afterwards we need to define dependencies for the projects containing our source code:

	<dependencies>
		<!-- Code dependencies to show coverage on -->
		<dependency>
			<groupId>com.example</groupId>
			<artifactId>com.example.plugin1</artifactId>
			<version>0.1.0-SNAPSHOT</version>
			<scope>compile</scope>
		</dependency>

		<dependency>
			<groupId>com.example</groupId>
			<artifactId>com.example.plugin2</artifactId>
			<version>0.1.0-SNAPSHOT</version>
			<scope>compile</scope>
		</dependency>
		...
	</dependencies>

Further we need dependencies to our test fragments (mind the different scope) :

	<dependencies>
		...
		<!-- Test dependencies -->
		<dependency>
			<groupId>com.example</groupId>
			<artifactId>com.example.project1.test</artifactId>
			<version>0.1.0-SNAPSHOT</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>com.example</groupId>
			<artifactId>com.example.project2.test</artifactId>
			<version>0.1.0-SNAPSHOT</version>
			<scope>test</scope>
		</dependency>
		...
	</dependencies>

If unsure, have a look at a complete pom file.

Finally add the new project as a module to your master pom:

	<modules>
		...
		<module>../your.project.releng.coverage</module>
		...
	</modules>

The maven build now generates *.releng.coverage/target/site/jacoco-aggregate/jacoco.xml which can be picked up by various tools. Further you get a nice HTML report in the same folder for free.

Step 3: Jenkins reports

While you may directly publish the HTML report on your jenkins builds, I prefer to use the Code Coverage plugin. With a single instruction in your pipeline

	publishCoverage adapters: [jacocoAdapter(path: 'releng/com.example.releng.coverage/target/site/jacoco-aggregate/jacoco.xml')], sourceFileResolver: sourceFiles('STORE_LAST_BUILD')

it generates nice, interactive reports like these:

You may also have a look at this live report to play around with.

No comments:

Post a Comment