Difference between revisions of "Sonar + maven configuration + Jenkins"

Line 55: Line 55:
 
Key points:  
 
Key points:  
 
* SONAR is configured for ''JAVA'' language and it will use ''Jacoco'' as coverage tool.
 
* SONAR is configured for ''JAVA'' language and it will use ''Jacoco'' as coverage tool.
* Each maven module will have its own Unit Tests results (Surefire reports + .exec file) inside its own <code>target</code> directory
+
* Each Maven module will have its own Unit Tests results (Surefire reports + .exec file) inside its own <code>target</code> directory
 
* The Integration Tests results are common. Meaning, all modules will write in the same directory. That directory is relative to the maven execution.
 
* The Integration Tests results are common. Meaning, all modules will write in the same directory. That directory is relative to the maven execution.
  
  
  
=Maven configuration=
+
=Requirements=
 +
 
 +
* Maven must run on '''Java 7 or +'''
 +
* You must use '''Sonarqube 5.3 or +'''
 +
 
 +
 
 +
 
 +
=Maven / Sonar properties and key points=
 +
 
 +
 
 +
==Maven key properties==
 +
 
 +
Here are some properties you must know and use to configure Sonar:
 +
* <code>${project.reporting.outputDirectory}</code> == module/target/site/
 +
* <code>${project.build.directory}</code> == module/target/
 +
* <code>${session.executionRootDirectory}</code> == root folder where <code>mvn clean install</code> is launched
 +
* <code><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding></code>
  
  
 
==Sonar properties==
 
==Sonar properties==
  
First of all you need to configure SONAR by setting up some properties and paths.  
+
First of all you need to configure SONAR by setting up some properties and paths, see ''Surefire'' and ''Failsafe'' below.
 +
 
 +
To optimize SONAR execution we will set the following behaviour:
 +
* Language == Java
 +
* Coverage tool == JaCoCo
 +
* Behaviour == re-use Surefire and Failsafe reports. Do NOT re-compile for Sonar.
 +
 
 +
 
 +
=='''Surefire''' Unit Tests==
 +
 
 +
Results are saved '''in each Maven module''':
 +
* Results are saved in <code>XML</code> format in <code>$module/target/site/surefire-reports</code>
 +
* Results are saved in <code>HTML</code> format in <code>$module/target/site/jacoco-ut</code>. You can open <code>index.html</code> to browse the results.
 +
* Results are saved in <code>Binary (jacoco format)</code> in <code>$module/target/jacoco.exec</code>
 +
 
 +
 
 +
=='''Failsafe''' Integration tests==
 +
 
 +
Only XML and HTML results are saved in each Maven module. '''Consolidate results are saved in the execution path ./target'''
 +
* Results are saved in <code>XML</code> format in <code>$module/target/site/failsafe-reports</code>
 +
* Results are saved in <code>HTML</code> format in <code>$module/target/site/jacoco-it</code>. You can open <code>index.html</code> to browse the results.
 +
* Results are saved in <code>Binary (jacoco format)</code> in <code>$maven_execution_place/target/jacoco-it.exec</code>
 +
 
  
Technical details:
 
* '''Surefire''' unit tests plugin
 
** Outputs in <code>${project.build.directory}</code>
 
** 1 XML file per test class in: <code>${sonar.junit.reportsPath}</code>
 
** SONAR report file (jacoco-ut.exec) will be available at <code>${sonar.out.unitTestsReport}</code>
 
* '''Failsafe''' integration tests plugin
 
** All outputs in the same directory, relative to the local execution: <code>${session.executionRootDirectory}</code>
 
  
 +
=Set properties=
  
 
POM.xml extract:
 
POM.xml extract:
Line 80: Line 112:
 
<syntaxhighlight lang="xml">
 
<syntaxhighlight lang="xml">
 
     <properties>
 
     <properties>
        ...
+
                <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>   
 
+
               
        <!-- Maven plugins -->
+
                <!-- ================================================================= -->
        <maven-surefire-plugin.version>2.18.1</maven-surefire-plugin.version>
+
                <!-- ==== FAILSAFE (IT tests) + SUREFIRE (Unit tests) + SONARQUBE ==== -->
        <maven-failsafe-plugin.version>2.18.1</maven-failsafe-plugin.version>
+
                <!-- ================================================================= -->
+
                <maven-surefire-plugin.version>2.18.1</maven-surefire-plugin.version>
        <!-- Test frameworks -->
+
                <maven-failsafe-plugin.version>2.18.1</maven-failsafe-plugin.version>
        <junit.version>4.12</junit.version>
+
                <maven.jacoco.version>0.7.4.201502262128</maven.jacoco.version>      
+
               
        <!-- ==== SONARQUBE quality metrics ==== -->
+
                <!-- ========================================== -->
        <maven.jacoco.version>0.7.4.201502262128</maven.jacoco.version>
+
                <!-- Global Sonar settings. Do not change them! -->
        <!-- Global Sonar settings. Do not change them! -->
+
                <!-- ========================================== -->
        <sonar.language>java</sonar.language>
+
                <sonar.language>java</sonar.language>
        <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
+
                <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
        <sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin>
+
                <sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin>
        <jacoco.lib.path>
+
                <jacoco.lib.path>
            ${settings.localRepository}/org/jacoco/org.jacoco.agent/${maven.jacoco.version}/org.jacoco.agent-${maven.jacoco.version}-runtime.jar
+
                    ${settings.localRepository}/org/jacoco/org.jacoco.agent/${maven.jacoco.version}/org.jacoco.agent-${maven.jacoco.version}-runtime.jar
        </jacoco.lib.path>
+
                </jacoco.lib.path>
        <javaagent>${jacoco.lib.path}</javaagent>
+
                <javaagent>${jacoco.lib.path}</javaagent>
        <!-- Don't let Sonar execute tests. We will let Maven do it during build phase -->
+
                <!-- Don't let Sonar execute tests! Maven will run them and produce some reports for Sonar -->
        <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
+
                <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
        <!-- Report -->
+
               
        <!-- IMPORTANT: integration test path must be ABSOLUTE, especially for muli-modules projects -->
+
                <!-- =============== -->
        <!--           ${session.executionRootDirectory} = directory from where the "mvn" command is run -->
+
                <!-- Quality reports -->
        <!-- a) Where sonar will find the standard test reports -->
+
                <!-- =============== -->
        <sonar.surefire.reportsPath>${project.build.directory}/surefire-reports</sonar.surefire.reportsPath>
+
                <!-- XML reports (go to $/target/site/*-reports) -->
        <sonar.failsafe.reportsPath>${session.executionRootDirectory}/target/failsafe-reports</sonar.failsafe.reportsPath>
+
                <sonar.surefire.reportsPath>${project.reporting.outputDirectory}/surefire-reports</sonar.surefire.reportsPath>
        <!-- b) Sonar specific reports -->
+
                <sonar.failsafe.reportsPath>${project.reporting.outputDirectory}/failsafe-reports</sonar.failsafe.reportsPath>
        <sonar.jacoco.reportPath>${project.build.directory}/jacoco-unit.exec</sonar.jacoco.reportPath>
+
                <!-- Web reports (= go to $/target/site/jacoco-*/index.html to browse results) -->
        <sonar.jacoco.itReportPath>${session.executionRootDirectory}/target/reports/jacoco-it.exec</sonar.jacoco.itReportPath>
+
                <jacoco.ut.summary>${project.reporting.outputDirectory}/jacoco-ut</jacoco.ut.summary>
    </properties>
+
                <jacoco.it.summary>${project.reporting.outputDirectory}/jacoco-it</jacoco.it.summary>
 +
                <!-- Binary format [= Sonar format] -->
 +
                <!--    1) Unit tests reports must be in each module $/target/ project -->
 +
                <jacoco.ut.execution.data.file>${project.build.directory}/jacoco.exec</jacoco.ut.execution.data.file>
 +
                <!--    2) Integration tests reports must be consolidated together. If not then you will probably lost multi-project coverage -->
 +
                <jacoco.it.execution.data.file>${session.executionRootDirectory}/target/jacoco-it.exec</jacoco.it.execution.data.file>
 +
            </properties>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
  
  
==Jacoco plugin (coverage agent)==
+
=Jacoco plugin (coverage agent)=
  
 
This is how you should configure this plugin:
 
This is how you should configure this plugin:
Line 122: Line 160:
 
     <build>
 
     <build>
 
         <plugins>
 
         <plugins>
            <!-- == Jacoco agent configuration == -->
+
                    <!-- #################### -->
            <!-- This will auto-generate the right jacoco command for Unit | Integration tests -->
+
                    <!-- SONAR # CODE METRICS -->
            <plugin>
+
                    <!-- #################### -->
                <groupId>org.jacoco</groupId>
+
                    <!-- This will auto-generate the right jacoco command for Unit | Integration tests -->
                <artifactId>jacoco-maven-plugin</artifactId>
+
                    <plugin>
                <version>${maven.jacoco.version}</version>
+
                        <groupId>org.jacoco</groupId>
                <executions>  
+
                        <artifactId>jacoco-maven-plugin</artifactId>
                    <!-- Unit tests configuration -->
+
                        <version>${maven.jacoco.version}</version>
                    <execution>
+
                        <executions>
                        <id>prepare-unit-test-agent</id>
+
                       
                        <phase>process-test-classes</phase>
+
                            <!-- #- - - - - - - - - - - - # -->
                        <goals>
+
                            <!-- Unit tests configuration -->
                            <goal>prepare-agent</goal>
+
                            <!-- #- - - - - - - - - - - - # -->         
                        </goals>
+
                            <!-- JaCoCo runtime agent which is passed as VM argument when Maven Surefire plugin is executed. -->
                        <configuration>
+
                            <execution>
                            <destFile>${sonar.surefire.reportsPath}</destFile>
+
                                <id>pre-unit-test</id>                 
                            <propertyName>jacoco.agent.ut.arg</propertyName>
+
                                <goals>
                            <append>true</append>
+
                                    <goal>prepare-agent</goal>
                        </configuration>
+
                                </goals>
                    </execution>
+
                                <configuration>
                    <!-- Integration tests configuration -->
+
                                    <!-- Surefire (Unit tests) reports will be saved as XML in... -->
                    <execution>
+
                                    <destFile>${jacoco.ut.execution.data.file}</destFile>
                        <id>prepare-integration-test-agent</id>
+
                                    <propertyName>surefireArgLine</propertyName>
                        <phase>pre-integration-test</phase>
+
                                    <append>true</append>
                        <goals>
+
                                </configuration>
                            <goal>prepare-agent</goal>
+
                            </execution>
                        </goals>
+
                            <!-- Ensures code coverage report for unit tests is created after unit tests have been run. -->
                        <configuration>
+
                            <execution>
                            <destFile>${sonar.jacoco.itReportPath}</destFile>  
+
                                <id>post-unit-test</id>
                             <propertyName>jacoco.agent.it.arg</propertyName>
+
                                <phase>test</phase>
                            <append>true</append>                 
+
                                <goals>
                        </configuration>
+
                                    <goal>report</goal>
                    </execution>
+
                                </goals>
                </executions>
+
                                <configuration>
            </plugin>
+
                                    <!-- Surefire (Unit tests) reports will be saved as Binary in... -->
 +
                                    <dataFile>${jacoco.ut.execution.data.file}</dataFile>
 +
                                    <outputDirectory>${jacoco.ut.summary}</outputDirectory>
 +
                                    <append>true</append>
 +
                                </configuration>
 +
                            </execution>
 +
                           
 +
                            <!-- #- - - - - - - - - - - - # -->
 +
                            <!-- Integration tests configuration -->
 +
                            <!-- #- - - - - - - - - - - - # -->
 +
                            <!-- JaCoCo runtime agent which is passed as VM argument when Maven Failsafe plugin is executed. -->                 
 +
                            <execution>
 +
                                <id>pre-integration-test</id>
 +
                                <phase>pre-integration-test</phase>
 +
                                <goals>
 +
                                    <goal>prepare-agent</goal>
 +
                                </goals>
 +
                                <configuration>
 +
                                    <!-- Failsafe (Integration tests) reports will be saved as XML in... -->
 +
                                    <destFile>${jacoco.it.execution.data.file}</destFile>
 +
                                    <propertyName>failsafeArgLine</propertyName>                           
 +
                                    <append>true</append>               
 +
                                </configuration>
 +
                            </execution>
 +
                            <!-- Ensures code coverage report for integration tests is created after integration tests have been run. -->
 +
                             <execution>
 +
                                <id>post-integration-test</id>
 +
                                <phase>post-integration-test</phase>
 +
                                <goals>
 +
                                    <goal>report</goal>
 +
                                </goals>
 +
                                <configuration>
 +
                                    <!-- Failsafe (Integration tests) reports will be saved as Binary in... -->
 +
                                    <dataFile>${jacoco.it.execution.data.file}</dataFile>
 +
                                    <outputDirectory>${jacoco.it.summary}</outputDirectory>                        
 +
                                    <append>true</append>                 
 +
                                </configuration>
 +
                            </execution>
 +
                        </executions>
 +
                    </plugin>
  
 
             <plugin> Surefire (UT) </plugin>
 
             <plugin> Surefire (UT) </plugin>

Revision as of 20:07, 19 July 2016


SonarQube requires quite some configuration to be fully useful!

This article explains how to configure your maven projects to produce reports + how to configure Jenkins with SonarQube, bringing both Unit and Integration tests coverage.


Principle

What are Unit / Integration tests ?

By default "code coverage" only consider the tests from the same projects.


Let's take an example to make things easier...

Consider a project with 4 modules such as:

Project structure


Then consider the following inter-dependencies:

Project inter-dependencies


Definition:

  • Unit Tests coverage (UT) = code coverage for each module only. == How much tests of 'module A' test 'module A' ??
  • Integration Tests coverage (IT) = overall code coverage. == Once global compilation and all the tests have been run, how much of 'module A' was used and covered ?


... In our example:

  • For "Module A" only the jUnit in "Module A" are computed in unit test coverage
  • The coverage provided by the Module C "tests" is NOT taken into account by default! You need to enable and configure the integration test coverage.


... Why ?!? This limitation comes from the default SONAR behaviour. By default it creates 1 coverage report per component (maven project). To get the overall coverage you need a common report that each project can improve and use.


Process overview

To work well SonarQube requires a bit of Maven configuration + Jenkins build adjustment:

  • Maven specific properties
  • Maven build plug-ins
    • Maven-jacoco (code coverage tool)
    • Maven-surefire (unit tests reports)
    • Maven-failsafe (integration tests reports)
  • Maven jacoco dependency


Key points:

  • SONAR is configured for JAVA language and it will use Jacoco as coverage tool.
  • Each Maven module will have its own Unit Tests results (Surefire reports + .exec file) inside its own target directory
  • The Integration Tests results are common. Meaning, all modules will write in the same directory. That directory is relative to the maven execution.


Requirements

  • Maven must run on Java 7 or +
  • You must use Sonarqube 5.3 or +


Maven / Sonar properties and key points

Maven key properties

Here are some properties you must know and use to configure Sonar:

  • ${project.reporting.outputDirectory} == module/target/site/
  • ${project.build.directory} == module/target/
  • ${session.executionRootDirectory} == root folder where mvn clean install is launched
  • <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>


Sonar properties

First of all you need to configure SONAR by setting up some properties and paths, see Surefire and Failsafe below.

To optimize SONAR execution we will set the following behaviour:

  • Language == Java
  • Coverage tool == JaCoCo
  • Behaviour == re-use Surefire and Failsafe reports. Do NOT re-compile for Sonar.


Surefire Unit Tests

Results are saved in each Maven module:

  • Results are saved in XML format in $module/target/site/surefire-reports
  • Results are saved in HTML format in $module/target/site/jacoco-ut. You can open index.html to browse the results.
  • Results are saved in Binary (jacoco format) in $module/target/jacoco.exec


Failsafe Integration tests

Only XML and HTML results are saved in each Maven module. Consolidate results are saved in the execution path ./target

  • Results are saved in XML format in $module/target/site/failsafe-reports
  • Results are saved in HTML format in $module/target/site/jacoco-it. You can open index.html to browse the results.
  • Results are saved in Binary (jacoco format) in $maven_execution_place/target/jacoco-it.exec


Set properties

POM.xml extract:

    <properties>
                <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>    
                
                <!-- ================================================================= -->
                <!-- ==== FAILSAFE (IT tests) + SUREFIRE (Unit tests) + SONARQUBE ==== -->
                <!-- ================================================================= -->
                <maven-surefire-plugin.version>2.18.1</maven-surefire-plugin.version>
                <maven-failsafe-plugin.version>2.18.1</maven-failsafe-plugin.version>
                <maven.jacoco.version>0.7.4.201502262128</maven.jacoco.version>        
                
                <!-- ========================================== -->
                <!-- Global Sonar settings. Do not change them! -->
                <!-- ========================================== -->
                <sonar.language>java</sonar.language>
                <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
                <sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin>
                <jacoco.lib.path>
                    ${settings.localRepository}/org/jacoco/org.jacoco.agent/${maven.jacoco.version}/org.jacoco.agent-${maven.jacoco.version}-runtime.jar
                </jacoco.lib.path>
                <javaagent>${jacoco.lib.path}</javaagent>
                <!-- Don't let Sonar execute tests! Maven will run them and produce some reports for Sonar -->
                <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
                
                <!-- =============== -->
                <!-- Quality reports -->
                <!-- =============== -->
                <!-- XML reports (go to $/target/site/*-reports) -->
                <sonar.surefire.reportsPath>${project.reporting.outputDirectory}/surefire-reports</sonar.surefire.reportsPath>
                <sonar.failsafe.reportsPath>${project.reporting.outputDirectory}/failsafe-reports</sonar.failsafe.reportsPath>
                <!-- Web reports (= go to $/target/site/jacoco-*/index.html to browse results) -->
                <jacoco.ut.summary>${project.reporting.outputDirectory}/jacoco-ut</jacoco.ut.summary>
                <jacoco.it.summary>${project.reporting.outputDirectory}/jacoco-it</jacoco.it.summary>
                <!-- Binary format [= Sonar format] -->
                <!--    1) Unit tests reports must be in each module $/target/ project -->
                <jacoco.ut.execution.data.file>${project.build.directory}/jacoco.exec</jacoco.ut.execution.data.file>
                <!--    2) Integration tests reports must be consolidated together. If not then you will probably lost multi-project coverage -->
                <jacoco.it.execution.data.file>${session.executionRootDirectory}/target/jacoco-it.exec</jacoco.it.execution.data.file>
            </properties>


Jacoco plugin (coverage agent)

This is how you should configure this plugin:

    <build>
        <plugins>
                    <!-- #################### -->
                    <!-- SONAR # CODE METRICS -->
                    <!-- #################### -->
                    <!-- This will auto-generate the right jacoco command for Unit | Integration tests -->
                    <plugin>
                        <groupId>org.jacoco</groupId>
                        <artifactId>jacoco-maven-plugin</artifactId>
                        <version>${maven.jacoco.version}</version>
                        <executions>
                        
                            <!-- #- - - - - - - - - - - - # -->
                            <!-- Unit tests configuration -->
                            <!-- #- - - - - - - - - - - - # -->           
                            <!-- JaCoCo runtime agent which is passed as VM argument when Maven Surefire plugin is executed. -->
                            <execution>
                                <id>pre-unit-test</id>                  
                                <goals>
                                    <goal>prepare-agent</goal>
                                </goals>
                                <configuration>
                                    <!-- Surefire (Unit tests) reports will be saved as XML in... -->
                                    <destFile>${jacoco.ut.execution.data.file}</destFile>
                                    <propertyName>surefireArgLine</propertyName>
                                    <append>true</append>
                                </configuration>
                            </execution>
                             <!-- Ensures code coverage report for unit tests is created after unit tests have been run. -->
                            <execution>
                                <id>post-unit-test</id>
                                <phase>test</phase>
                                <goals>
                                    <goal>report</goal>
                                </goals>
                                <configuration>
                                    <!-- Surefire (Unit tests) reports will be saved as Binary in... -->
                                    <dataFile>${jacoco.ut.execution.data.file}</dataFile>
                                    <outputDirectory>${jacoco.ut.summary}</outputDirectory>
                                    <append>true</append>
                                </configuration>
                            </execution>
                            
                            <!-- #- - - - - - - - - - - - # -->
                            <!-- Integration tests configuration -->
                            <!-- #- - - - - - - - - - - - # -->
                            <!-- JaCoCo runtime agent which is passed as VM argument when Maven Failsafe plugin is executed. -->                   
                            <execution>
                                <id>pre-integration-test</id>
                                <phase>pre-integration-test</phase>
                                <goals>
                                    <goal>prepare-agent</goal>
                                </goals>
                                <configuration>
                                    <!-- Failsafe (Integration tests) reports will be saved as XML in... -->
                                    <destFile>${jacoco.it.execution.data.file}</destFile>
                                    <propertyName>failsafeArgLine</propertyName>                            
                                    <append>true</append>                 
                                </configuration>
                            </execution>
                             <!-- Ensures code coverage report for integration tests is created after integration tests have been run. -->
                            <execution>
                                <id>post-integration-test</id>
                                <phase>post-integration-test</phase>
                                <goals>
                                    <goal>report</goal>
                                </goals>
                                <configuration>
                                    <!-- Failsafe (Integration tests) reports will be saved as Binary in... -->
                                    <dataFile>${jacoco.it.execution.data.file}</dataFile>
                                    <outputDirectory>${jacoco.it.summary}</outputDirectory>                         
                                    <append>true</append>                 
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>

            <plugin> Surefire (UT) </plugin>
            <plugin> Failsafe (IT) </plugin>

        </plugins>
    </build>


This will defined 2 properties, depending on the maven phase:

Phase ArgLine Value
Unit Tests process-test-classes jacoco.agent.ut.arg -javaagent:${jacoco.lib.path}=destFile=${sonar.jacoco.reportPath},append=true
Integration Tests pre-integration-test jacoco.agent.it.arg -javaagent:${jacoco.lib.path}=destFile=${sonar.jacoco.itReportPath},append=true

These properties will be re-use in the corresponding maven plugin.


Surefire (UT tests)

Surefire will process the Unit Tests.

!! Do not use Surefire for your integration tests because Surefire produce different outputs per maven module !! Integration tests requires to use 1 output for all !

    <build>
        <plugins>

            <plugin> Maven-jacoco </plugin>

            <!-- == process UNIT tests == -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${maven-surefire-plugin.version}</version>
                <configuration>
                    <!-- Do not run if no tests -->
                    <skipTests>${skipTests}</skipTests>
                    <!-- a) Surefire must create junit reports where sonar can find it later during analysis --> 
                    <reportsDirectory>${sonar.jacoco.reportPath}</reportsDirectory>
                    <!-- b) Jacoco specific settings (command auto-generate by Sonar plugin) -->
                    <argLine>${jacoco.agent.ut.arg}</argLine>
                    <!-- Exclude integration tests -->
                    <excludes>
                        <exclude>**/*IT.java</exclude>
                        <exclude>**/*IntegrationTest.java</exclude>
                        <exclude>**/*Gwt.java</exclude>
                    </excludes>
                </configuration>
            </plugin>

            <plugin> Failsafe (IT) </plugin>

        </plugins>
    </build>


Notes:

  • No tests will be run if mvn clean install -DskipTests
  • Each module has its own surefire-reports + Sonar report
  • The exclusion list is something that depends on your own situation


Failsafe configuration (IT tests)

Failsafe will process the Integration Tests.

!! Do not use Surefire for your integration tests because Surefire produce different outputs per maven module !! Integration tests requires to use 1 output for all !

    <build>
        <plugins>

            <plugin> Maven-jacoco </plugin>
            <plugin> Surefire (UT) </plugin>

            <!-- == process INTEGRATION tests == -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>${maven-failsafe-plugin.version}</version>
                <configuration>
                    <!-- Do not run if no tests -->
                    <skipTests>${skipIntegrationTests}</skipTests>
                    <!-- a) Failsafe must create junit reports where sonar can find it later during analysis -->
                    <reportsDirectory>${sonar.failsafe.reportsPath}</reportsDirectory>
                    <!-- JVM settings -->
                    <argLine>-Xmx1024m -XX:maxPermSize:256m</argLine>
                    <forkCount>1</forkCount>
                    <reuseForks>true</reuseForks>
                    <!-- <runOrder>alphabetical</runOrder> -->
                    <!-- Sonar specific settings (command auto-generate by Sonar plugin) -->                  
                    <argLine>${jacoco.agent.it.arg}</argLine>
                    <includes>
                        <include>**/*IntegrationTest.java</include>
                        <include>**/*IT.java</include>
                    </includes>
                    <excludes>
                        <exclude>**/*Gwt.java</exclude>
                    </excludes>
                </configuration>
                <!-- Only run failsafe when required -->
                <executions>
                    <execution>
                        <id>integration-test</id>
                        <phase>integration-test</phase>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

        </plugins>
    </build>


Notes:

  • No tests will be run if mvn clean install -DskipIntegrationTests
  • Only 1 report for all modules, that depends on the ${session.executionRootDirectory}
  • The exclusion | inclusion list is something that depends on your own situation
  • The JVM settings can be arranged


Maven dependencies

At last, you need to add the jacoco dependency:


    <dependencies>
        ...
        <!-- SonarQube dependencies -->
        <dependency>
            <groupId>org.jacoco</groupId>
            <artifactId>org.jacoco.agent</artifactId>
            <version>${maven.jacoco.version}</version>
            <classifier>runtime</classifier>
            <scope>test</scope>
        </dependency>
    </dependencies>


Now your Maven configuration is complete at last.


Jenkins configuration

Now that you can generate these reports, especially the integration results, you need to configure Jenkins to use them!

Jenkins SonarQube configuration


To set up the Sonar Jenkins plugin to process already generated JaCoCo data files, the following properties must be specified in the "Additional properties" text box, under the Sonar installation being configured:

  • -Dsonar.dynamicAnalysis=reuseReports ==> Tells SonarQube to reuse existing reports for unit tests execution and coverage reports
  • -Dsonar.jacoco.itReportPath={ABSOLUTE_PATH_TO_JENKINS}/workspace/target/reports/jacoco-it.exec => integration tests report to process



Real life example

You can check out one of my GitHub project:


Even better, you can check out this excellent tutorial:


Appendices

Run tests in specific order

If for some reasons you need to run your tests in a particular order you can say do so in Maven and/or Java

Reminder : if you have to run your tests in a particular order then you should refactor your tests! These tricks should not let you escape from that!


Maven

The runOrder is a nice trick.

    <build>
        <plugins>
            <plugin>
                SUREFIRE or FAILSAFE

                <configuration>
                    <!-- JVM settings -->
                    <argLine>-Xmx1024m -XX:maxPermSize:256m</argLine>
                    <forkCount>1</forkCount>
                    <reuseForks>true</reuseForks>
                    <runOrder>alphabetical</runOrder>
                    <!-- Jacoco execution -->                 
                    <argLine>${jacoco.agent.it.arg}</argLine>
                    ...
                </configuration>
            </plugin>

        </plugins>
    </build>


Java

Since jUnit 4.11 you can set the order of your tests.


References

This article is based on my daily work in VEHCO.

To update to SonarQube I used the following articles and code examples:

Jenkins configuration: