14

Mamy wielomodułowy wielojęzyczny program maven java z analizą zasięgu z jacoco. Główną częścią modułów jest backend (kod Java) z interfejsem API REST, a nasz moduł webapp zawiera frontend (AngularJS) i testy integracji w java. Nasz plik Jacoco-IT.exec zawiera około 100 kilobajtów danych, więc możemy zgadnąć, że niektóre dane pokrycia dla testów integracyjnych mogłyby zostać zebrane. Niemniej jednak nie możemy zobaczyć żadnego pokrycia w SonarQube (przy użyciu wersji 5.0 i 4.5)Pokrycie testu integracyjnego w SonarQube z wtyczki JaCoCo Maven pokazujące 0%

Prowadzimy zbudować projekt i uruchomić testy integracji z

mvn clean install 

i analizować dane z

mvn sonar:sonar 

Projekt jest skonfigurowany jako wielojęzykowy, ale po prostu analizujemy kod Java jeszcze (używaliśmy konfiguracji monolanguage, ale nie było różnicy w wynikach związanych z danymi pokrycia)

Nasz nadrzędny POM:

<properties> 
    <hibernate.version>4.2.2.Final</hibernate.version> 
    <spring.version>3.2.3.RELEASE</spring.version> 
    <resteasy.version>3.0.4.Final</resteasy.version> 
    <cucumber.version>1.1.3</cucumber.version> 
    <selenium-java.version>2.33.0</selenium-java.version> 
    <!-- Sonar --> 
    <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin> 
    <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis> 
    <sonar.jacoco.itReportPath>${project.basedir}/../target/jacoco-it.exec</sonar.jacoco.itReportPath> 
    <jacoco.dataFile>${project.basedir}/../target/jacoco-it.exec</jacoco.dataFile> 
</properties> 
<build> 
    <plugins> 
     <plugin> 
      <groupId>org.apache.maven.plugins</groupId> 
      <artifactId>maven-compiler-plugin</artifactId> 
      <configuration> 
       <source>1.7</source> 
       <target>1.7</target> 
       <debug>true</debug> 
      </configuration> 
     </plugin> 
     <plugin> 
      <groupId>org.jacoco</groupId> 
      <artifactId>jacoco-maven-plugin</artifactId> 

      <executions> 
       <execution> 
        <id>default-prepare-agent</id> 
        <goals> 
         <goal>prepare-agent</goal> 
        </goals> 
       </execution> 
       <execution> 
        <id>default-prepare-agent-integration</id> 
        <goals> 
         <goal>prepare-agent-integration</goal> 
        </goals> 
       </execution> 
       <execution> 
        <id>default-report</id> 
        <goals> 
         <goal>report</goal> 
        </goals> 
       </execution> 
       <execution> 
        <id>default-report-integration</id> 
        <goals> 
         <goal>report-integration</goal> 
        </goals> 
       </execution> 
      </executions> 
     </plugin> 
     <plugin> 
      <groupId>org.apache.maven.plugins</groupId> 
      <artifactId>maven-surefire-plugin</artifactId> 
      <version>2.16</version> 
     </plugin> 
    </plugins> 
    <pluginManagement> 
      <plugin> 
       <groupId>org.jacoco</groupId> 
       <artifactId>jacoco-maven-plugin</artifactId> 
       <version>0.7.2.201409121644</version> 
      </plugin> 
    </pluginMangement> 
</build> 

Nasz POM z webapp z testami integracji:

<properties> 
    <sonar.sources>src/main</sonar.sources> 
</properties> 
<build> 
    <finalName>web</finalName> 
    <plugins> 
     <plugin> 
     <groupId>org.mortbay.jetty</groupId> 
     <artifactId>jetty-maven-plugin</artifactId> 
     <version>8.1.7.v20120910</version> 
     <configuration>...</configuration> 
     <executions>...</executions> 
    </plugin> 
     <plugin> 
      <groupId>org.jacoco</groupId> 
      <artifactId>jacoco-maven-plugin</artifactId> 
      <configuration> 
       <!-- The destination file for the code coverage report has to be set to the same value 
       in the parent pom and in each module pom. Then JaCoCo will add up information in 
       the same report, so that, it will give the cross-module code coverage. --> 
       <destFile>${project.basedir}/../target/jacoco-it.exec</destFile> 
      </configuration> 
     </plugin> 
     <plugin> 
      <groupId>org.apache.maven.plugins</groupId> 
      <artifactId>maven-failsafe-plugin</artifactId> 
      <version>2.16</version> 
      <executions> 
       <execution> 
        <id>default</id> 
        <goals> 
         <goal>integration-test</goal> 
         <goal>verify</goal> 
        </goals> 
       </execution> 
      </executions> 
     </plugin> 
    </plugins> 
</build> 

Jak widać w naszym rodzicem POM mamy skonfigurowany itReportPath być w tym samym katalogu dla wszystkich Moduły. Tak więc, gdy Sonar analizuje wszystkie moduły, odczytuje zawsze te same dane pokrycia i powinien dopasować je do informacji debugowania z plików binarnych bieżącego modułu. Podczas fazy analizy Maven (mvn sonar: sonar) otrzymujemy jakieś wiadomości, których nie jesteśmy pewni, czy są one problem:

dla wszystkich modułów java otrzymujemy linie folloing:

[INFO] [17:30:42.992] Sensor SurefireSensor... 
    [INFO] [17:30:42.992] parsing \git\airport-core\rest\target\surefire-reports 
    [INFO] [17:30:43.009] Sensor SurefireSensor done: 17 ms 
    [INFO] [17:30:43.009] Sensor JaCoCoItSensor... 
    [INFO] [17:30:43.010] Analysing \git\airport-core\rest\..\target\jacoco-it.exec 
    [INFO] [17:30:43.018] No information about coverage per test. 
    [INFO] [17:30:43.018] Sensor JaCoCoItSensor done: 9 ms 
    [INFO] [17:30:43.018] Sensor JaCoCoOverallSensor... 
    [INFO] [17:30:43.027] Analysing \git\airport-core\rest\target\sonar\jacoco-overall.exec 
    [INFO] [17:30:43.046] No information about coverage per test. 
    [INFO] [17:30:43.046] Sensor JaCoCoOverallSensor done: 28 ms 

Is "Brak informacji o zasięgu na test." problem? Ok, nie wiemy, który test spowodował pokrycie, ale powinniśmy uzyskać inną wartość w SonarQube niż 0%

i dla naszego modułu webapp, który nie zawiera żadnych źródeł/klas java, z wyjątkiem samych źródeł testu integracji, otrzymujemy następujące linie:

[INFO] [17:30:48.370] Sensor JaCoCoItSensor... 
    [INFO] [17:30:48.370] No JaCoCo analysis of project coverage can be done since there is no class files. 
    [INFO] [17:30:48.370] Sensor JaCoCoItSensor done: 0 ms 

Nie powinno to stanowić problemu, ponieważ w tym module nie ma klas. Czy ta obserwacja jest poprawna?

Do głównej części nasza konfiguracja bazuje na oficjalnej konfiguracji demo SonarCube (https://github.com/SonarSource/sonar-examples/tree/master/projects/languages/java/code-coverage/combined%20ut-it/combined-ut-it-multimodule-maven-jacoco), właśnie dodaliśmy cel "przygotować-agent-integracja". I oczywiście zmieniono go na projekt wielojęzyczny.

Znaleźliśmy wiele zdeprawowanych informacji w Internecie (ustawienia argLine itd.), Które nic nie zmieniły dla nas.

Linki do dokumentacji i samouczków użyliśmy:

+0

gdzie znajdują się pliki klas? Maven używa domyślnej lokalizacji, która nie zawsze jest mapowana przez wszystkie katalogi wyjściowe wtyczek. Nie jestem pewien, ale myślę, że maven używa "/ target", ale niektóre wtyczki mogą używać "/ bin" (lub odwrotnie). Aby tego uniknąć, można ustawić Krummy

+0

, gdy klasy są w docelach/klasach, z wyjątkiem aplikacji webowej, która właśnie przetestowała. tam klasy są w klasach docelowych/testowych. –

+0

podczas analizy sonaru uruchom również wypisze poprawną ścieżkę do plików binarnych. –

Odpowiedz

0

miałem to samo doświadczenie, kiedy konfigurowania JaCoCo dla Jersey. Skończyło się na zastosowaniu metody bisekcji , aby dowiedzieć się, które moduły powodują obnienie całego projektu o 0%.

Jeśli dobrze pamiętam, największą niespodzianką był maven-shade-plugin, który w jakiś sposób zepsuł skojarzenie między zebranym zasięgiem a lokalizacją klas, co spowodowało, że Sonar pokazywał 0% zasięgu kodu. Wyłączyłem jego wykonanie, wiążąc go z fazą none, aby to naprawić (patrz this commit).

Jako przykład, w ten sposób można rozszerzyć pom.xml podmodułu, aby uzyskać działający sonar (zakładając, że sonar jest wykonywany z profilem maven sonar).

<profile> 
    <id>sonar</id> 
    <build> 
     <plugins> 
      <plugin> 
       <groupId>org.apache.maven.plugins</groupId> 
       <artifactId>maven-surefire-plugin</artifactId> 
       <configuration> 
        <!-- disable parallel execution so that JaCoCo listener can properly work --> 
        <parallel>none</parallel> 
        <perCoreThreadCount>false</perCoreThreadCount> 
        <forkCount>1</forkCount> 
       </configuration> 
      </plugin> 
      <plugin> 
       <artifactId>maven-shade-plugin</artifactId> 
       <executions> 
        <execution> 
         <id>shade-archive</id> 
         <phase>none</phase> 
        </execution> 
       </executions> 
      </plugin> 
     </plugins> 
    </build> 
    <dependencies> 
     <dependency> 
      <groupId>org.ow2.asm</groupId> 
      <artifactId>asm-debug-all</artifactId> 
      <optional>false</optional> 
     </dependency> 
    </dependencies> 
</profile> 
1

Po walce bardzo długo z Jacoco Maven i tylko w ten sposób, że pracuje dla mnie:

  1. utworzyć profil w pom.xml

    <profile> 
        <id>coverage-per-test</id> 
        <build> 
        <plugins> 
         <plugin> 
         <groupId>org.apache.maven.plugins</groupId> 
         <artifactId>maven-surefire-plugin</artifactId> 
         <version>2.19.1</version> 
         <configuration> 
         <!-- disable parallel execution so that JaCoCo listener can properly work --> 
          <parallel>none</parallel> 
          <perCoreThreadCount>false</perCoreThreadCount> 
          <forkCount>1</forkCount> 
          <properties> 
          <property> 
           <name>listener</name> 
           <value>org.sonar.java.jacoco.JUnitListener</value> 
          </property> 
          </properties> 
         </configuration> 
         </plugin> 
        </plugins> 
        </build> 
    
        <dependencies> 
        <dependency> 
         <groupId>org.sonarsource.java</groupId> 
         <artifactId>sonar-jacoco-listeners</artifactId> 
         <version>3.10</version> 
         <scope>test</scope> 
        </dependency> 
        </dependencies> 
    </profile> 
    
  2. Aktualizacja maven wtyczki murowany do najnowszej wersji

  3. Wykonaj polecenia:

    mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent install -Pcoverage-per-test -Dmaven.test.failure.ignore=true 
    
    mvn sonar:sonar 
    

Podobnie jak opisują w github sonar example

0

Biorąc pod uwagę inne odpowiedzi chcę należy dodać jedną rzecz, co jest ważne, aby pokazać zasięg testów na Sonar:

  1. trzeba budować projektu przed Oczekiwanie na pokazanie: mvn clean install
  2. musisz zbudować bez -DskipTests
  3. musisz zachować właściwe konfiguracje wtyczki, która uruchamia testy (surefire, failsafe, ... plugin) - zasięg zostanie pokazany biorąc pod uwagę tylko te testy, które są zawarte w konfiguracjach wtyczek przez <includes> lub podobne konfiguracje.
0

Używam JUnit iw moim przypadku problem był spowodowany uzależnieniem TestNG w moim pom.xml oprócz JUnit. Po usunięciu tej niepotrzebnej zależności wszystko zaczęło działać zgodnie z oczekiwaniami.