Multi-Modul-Integrationstest-Abdeckung mit Jacoco und Sonar

By Gerald Mücke | May 29, 2015

Multi-Modul-Integrationstest-Abdeckung mit Jacoco und Sonar

In diesem Artikel beschreibe ich, wie man Jacoco für Maven-Multi-Modul-Projekte einrichtet, damit die Coverage von Integrationstests für die gesamte Codebasis berechnet und mit Sonarqube analysiert werden kann.

Gestern hatte ich Schwierigkeiten, die Integration-Test-Coveragesergebnisse in einem Multi-Modul-Projekt-Setup zu erfassen, was ich schließlich gelöst habe.

Nehmen wir also an, ich habe das folgende Setup:

rootModule
+Module1
+Module2
| +SubModule2-1
|    +SubModule2-1-1
| +SubModule2-2
+ITModule
  +ITModule1

Das ITModul enthält nur Integrationstests, wobei ITModul1 ein spezielles Szenario ist, das ein einzelnes Modul benötigt. Modul2 besteht aus verschachtelten Untermodulen. Es gibt mehrere Beispiele, um einen Pfad wie ../target/jacoco-it.exec zu verwenden, aber das funktioniert offensichtlich nicht, wenn man mehr als eine Verschachtelungsebene hat.

Um zu wissen, wie man es löst, muss man verstehen, wie Sonar die Analyse durchführt. Wenn Sonar die Coverage-Informationen analysiert, prüft es den Code jedes Moduls gegen die in der Eigenschaft sonar.jacoco.itReportPath angegebene Coverage-Datei, die standardmäßig auf target/jacoco-it.exec gesetzt ist. Also beim Analysieren von Modul1 prüft es nach Coverage-Informationen in Modul1/target/jacoco-it.exec. Da die Coverage-Daten aber im ITModul, bzw. ITModul1 erfasst werden, muss ich Sonar auf die Datei im ITModul hinweisen.

Der beste Ort, um die Coverage-Daten zu sammeln, ist also das rootModule, d.h. rootModule/target/jacoco-it.exec, und daran werden die Ergebnisse aller IT-Tests angehängt.

Ich verwende die folgende Plugin-Konfiguration, die separate Dateien für die Coverage von Unit-Tests verwendet (den Append-Flag nicht vergessen, sonst wird die Gesamtcoverage falsch sein) und die zentrale Datei für die IT-Coverage.


<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.7.4.201502262128</version>
    <executions>
        <execution>
            <id>prepare-agent</id>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
            <configuration>
                <destFile>target/jacoco.exec</destFile>
                <append>true</append>
                <propertyName>surefireArgLine</propertyName>
            </configuration>
        </execution>
        <execution>
            <id>prepare-it-agent</id>
            <phase>pre-integration-test</phase>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
            <configuration>
                <destFile>${session.executionRootDirectory}/target/jacoco-it.exec</destFile>
                <append>true</append>
                <propertyName>failsafeArgLine</propertyName>
            </configuration>
        </execution>
    </executions>
</plugin>

Das Property ${session.executionRootDirectory} ist die Wurzel der Ausführung, wenn ich das gesamte Projekt baue, wird es auf das rootModule verweisen. Dies ist also der beste Pfad, den man verwenden sollte, wenn man ein Multi-Modul mit mehr als einer Ebene der Verschachtelung hat.

Für die Analyse muss ich Sonar anweisen, diese Datei zu verwenden, wenn die IT-Coverage analysiert wird. Daher muss ich sonar.jacoco.itReportPath auf diese Datei setzen. Leider funktioniert dies nicht mit dem session.executionRootDirectory-Property, und ich muss den absoluten Pfad zur Datei manuell einstellen. Ich empfehle nicht, den absoluten Pfad in der pom.xml anzugeben, da dieser Pfad spezifisch für die Build-Umgebung ist. Stellen Sie den Pfad also entweder in Sonar oder als Systemeigenschaft Ihrer Build-Umgebung ein. Ich habe es direkt in den Sonar-Projekteinstellungen gesetzt (Java > Jacoco), zum Beispiel /opt/buildroot/myProject/target/jacoco-it.exec. Jetzt wird Sonar diese Datei für die IT-Coverage-Analyse jedes Moduls überprüfen.

comments powered by Disqus