For every code that's written in Java, it's always the right thing to "TEST". As part of testing process, we aim at covering maximum implementation lines possible. In order to measure the test coverage we rely on Code Coverage tools. Among the famous code coverage tools, JaCoCo is famous and is very easy to implement.
Below we will develop a very simple code, write test cases (unit tests and integration tests), attach project to SonarQube server and configure the maven JaCoCo plugin to generate code coverage reports.
We will use maven's quickstart archetype for creating project structure. Below is how it looks like:
Step 1: Simple coding in App.java
Step 2: Unit test code in AppTest.java
http://www.goeatlearn.com/2015/06/using-sonar-with-eclipse.html
Step 5: Configure pom.xml
Below is entire pom.xml configuration provided for clarity.
Main points to note are:
a. Configuring sonar properties
b. Mentioning JaCoCo plugin unit tests end with *Test.java and integration tests end with *IT.java
c. Configuing m2e plugin to ignore JaCoCo life cycle execution errors (you'll notice :
Plugin execution not covered by lifecycle configuration: org.jacoco:jacoco-maven-plugin. Add exclusions in m2e plugin to ignore it)
d. Once you configure m2e plugin, still you'll see "x" mark in eclipse's pom - do not worry. Do a maven build by passing "clean install sonar:sonar" goal - it should be successful
Step 7: Launch sonar in browser at http://localhost:9000 and log in as admin
Step 8: Select your project on main dashboard
Step 9: Select "More" -> "Manage Dashboards"
Step 10: Select "Integration Tests Coverage" widget as shown below
Step 11: Select "Back to Dashboard"
Step 12: You are done, you'll see Integration Tests coverage and Unit Test coverage as below:
Play around by clicking the coverage percentage, you'll get detailed reports on line coverage for each java file
Below we will develop a very simple code, write test cases (unit tests and integration tests), attach project to SonarQube server and configure the maven JaCoCo plugin to generate code coverage reports.
We will use maven's quickstart archetype for creating project structure. Below is how it looks like:
Step 1: Simple coding in App.java
package go.eat.learn.springboot.example;
public class App
{
public void sayFruitOrVegetable(String input){
if(input.equalsIgnoreCase("apple")){
System.out.println("It's a fruit");
}else{
System.out.println("It's a vegetable");
}
}
}
Step 2: Unit test code in AppTest.java
Step 3: Integration test coding in AppIT.javapackage go.eat.learn.springboot.example;
import org.junit.Test;
public class AppTest {
@Test
public void testSayFruitOrVegetable() {
App app = new App();
app.sayFruitOrVegetable("apple");
}
}
Step 4: Set up SonarQube and integrate with eclipse - refer our earlier post
package go.eat.learn.springboot.example;
import org.junit.Test;
public class AppIT {
@Test
public void testSayFruitOrVegetable() {
App app = new App();
app.sayFruitOrVegetable("broccoli");
}
}
http://www.goeatlearn.com/2015/06/using-sonar-with-eclipse.html
Step 5: Configure pom.xml
Below is entire pom.xml configuration provided for clarity.
Main points to note are:
a. Configuring sonar properties
b. Mentioning JaCoCo plugin unit tests end with *Test.java and integration tests end with *IT.java
c. Configuing m2e plugin to ignore JaCoCo life cycle execution errors (you'll notice :
Plugin execution not covered by lifecycle configuration: org.jacoco:jacoco-maven-plugin. Add exclusions in m2e plugin to ignore it)
d. Once you configure m2e plugin, still you'll see "x" mark in eclipse's pom - do not worry. Do a maven build by passing "clean install sonar:sonar" goal - it should be successful
Step 6: Run Maven goal "clean install sonar:sonar"
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>go.eat.learn</groupId>
<artifactId>springboot.example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springboot.example</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jacoco.it.execution.data.file>${project.build.directory}/coverage-reports/jacoco-it.exec</jacoco.it.execution.data.file>
<sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin>
<sonar.jacoco.reportPath>${project.build.directory}/coverage-reports/jacoco-ut.exec</sonar.jacoco.reportPath>
<sonar.jacoco.itReportPath>${project.build.directory}/coverage-reports/jacoco-it.exec</sonar.jacoco.itReportPath>
<sonar.surefire.reportsPath>${project.build.directory}/surefire-reports</sonar.surefire.reportsPath>
<maven.surefire.plugin.version>2.18.1</maven.surefire.plugin.version>
<maven.failsafe.plugin.version>2.18.1</maven.failsafe.plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Java Code Coverage Start -->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.6.4.201312101107</version>
<executions>
<execution>
<id>prepare-unit-test-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${sonar.jacoco.reportPath}</destFile>
<propertyName>surefireArgLine</propertyName>
</configuration>
</execution>
<execution>
<id>generate-unit-test-report</id>
<goals>
<goal>report</goal>
</goals>
<configuration>
<!-- Supplying data file of JaCoCo Unit Tests is must -->
<dataFile>${sonar.jacoco.reportPath}</dataFile>
</configuration>
</execution>
<execution>
<id>prepare-integration-test-agent</id>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
<configuration>
<!-- Same explanation as UT's -->
<destFile>${sonar.jacoco.itReportPath}</destFile>
<propertyName>surefireArgLine</propertyName>
</configuration>
</execution>
<execution>
<id>generate-integration-test-report</id>
<goals>
<goal>report-integration</goal>
</goals>
<configuration>
<!-- Same explanation as UT's -->
<dataFile>${sonar.jacoco.itReportPath}</dataFile>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<!-- Version declaration for surefire is not mandatory at this place
- present for reference purpose -->
<version>${maven.surefire.plugin.version}</version>
<executions>
<execution>
<id>run-unit-tests</id>
<goals>
<goal>test</goal>
</goals>
<configuration>
<argLine>-Xmx1024m -XX:MaxPermSize=256m ${surefireArgLine}</argLine>
<skipTests>${skip.unit.tests}</skipTests><!-- Defaults to false -->
<excludes>
<!-- By default Sonar's JaCoCo expects Integration Tests to be *IT.java
or *ITCase.java -->
<exclude>**/IT*.java</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven.failsafe.plugin.version}</version>
<executions>
<execution>
<id>run-integration-tests</id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<argLine>-Xmx1024m -XX:MaxPermSize=256m ${surefireArgLine}</argLine>
<skipTests>${skip.integration.tests}</skipTests><!-- Defaults to false -->
<excludes>
<!-- By default Sonar's JaCoCo expects Unit tests to be **Test.java -->
<exclude>**/Test*.java</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>
<!--This plugin's configuration is used to store Eclipse m2e settings
only. It has no influence on the Maven build itself. -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<versionRange>[0.5,)
</versionRange>
<goals>
<goal>prepare-agent</goal>
</goals>
</pluginExecutionFilter>
<action>
<!-- m2e doesn't know what to do with jacoco, let's ignore it or
annoying error markers appear see http://wiki.eclipse.org/M2E_plugin_execution_not_covered -->
<ignore></ignore>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
<!-- Java Code Coverage End -->
</plugins>
</build>
</project>
Step 7: Launch sonar in browser at http://localhost:9000 and log in as admin
Step 8: Select your project on main dashboard
Step 9: Select "More" -> "Manage Dashboards"
Step 10: Select "Integration Tests Coverage" widget as shown below
Step 11: Select "Back to Dashboard"
Step 12: You are done, you'll see Integration Tests coverage and Unit Test coverage as below:
Play around by clicking the coverage percentage, you'll get detailed reports on line coverage for each java file
Wonderful. Was looking for something similar - which version of JDK you used?
ReplyDeleteAny JDK higher than 1.5 should do. I've used JDK 6. Thank you for comment :)
DeleteThank you..It's encouraging to us :)
ReplyDelete