2017-01-19 6 views
2

Я строю сервер SonarQube 6.2, который уже анализирует мои проекты Java 8/Gradle 3.3. При добавлении JaCoCo к многомодульных Gradle проекта, я понял, что SonarQube является измерение покрытия кода на «на-модуле» основе:SonarQube: Покрытие неполное по проекту с многомодульным градиентом с JaCoCo

Если класс находится в модуле A и тест для этого класса находится в модуле B, SonarQube показывает, что класс не включен.

Я хочу измерить покрытие кода по всем модулям, а не по модулю. Как мне это достичь?

Есть много похожих вопросов, но нет полезных ответов, хотя ситуация для меня довольно распространена. Например, Дженкинс делает это по умолчанию.

Я решил построить blueprint on github, чтобы уточнить проблему.

Основной build.gradle состоит из

plugins { id "org.sonarqube" version "2.2.1" } 

subprojects { 
    apply plugin: 'java' 
    apply plugin: 'jacoco' 

    repositories { mavenCentral() } 
    dependencies { testCompile "junit:junit:4.12" } 
} 

modA/build.gradle пуст.

Состоит из 3 классов: TestedInModA, TestedInModATest и TestedViaModB.

modB/build.gradle просто объявляет зависимость к modA:

dependencies { compile project(':modA') } 

Он содержит только один класс: TestedViaModBTest, тестирование класса TestedViaModB, расположенный в modA.

Мой (частный) экземпляр Jenkins показывает 100% -ый охват для двух классов, включенных, пока SonarQube говорит, что только класс TestedInModA (который протестирован в его собственном модуле) покрыт.

Как изменить процесс сборки, чтобы увидеть «кросс-модульное покрытие» в SonarQube?

Я хотел бы обновить свой проект, чтобы будущие посетители этого вопроса могли найти рабочий пример.

Мой рабочий раствор (спасибо @Godin)

  1. добавить следующее в subprojects закрытия

    tasks.withType(Test) { 
        // redirect all coverage data to one file 
        // ... needs cleaning the data prior to the build to avoid accumulating coverage data of different runs. 
        // see `task cleanJacoco` 
        jacoco { 
         destinationFile = file("$rootProject.buildDir/jacoco/test.exec") 
        } 
    } 
    
  2. добавить

    task cleanJacoco(dependsOn: 'clean') { delete "$buildDir/jacoco" } 
    

снаружиsubprojects закрытие.

ответ

4

При выполнении строить JaCoCo Gradle плагин будет производить modA/build/jacoco/test.exec и modB/build/jacoco/test.exe, которые содержат информацию о выполнении тестов в modA и modB соответственно.SonarQube выполняет анализ модулей отдельно, поэтому при анализе modA для файла TestedViaModB он видит только modA/build/jacoco/test.exec.

Наиболее распространенный трюк для пересечения границ - это сбор всей информации о покрытии в одном месте. Это может быть сделано с JaCoCo Gralde плагин

  • либо путем изменения местоположения - см destinationFile и destPath (поскольку информация добавляется к exec файл, не забудьте удалить это единое место перед строить, в противном случае он будет накапливать информацию из разных сборок, а не только из разных модулей),

  • либо путем объединения всех файлов в один - см. JacocoMerge task. Затем укажите это единственное место для SonarQube как sonar.jacoco.reportPath.

Другой уловка: SonarQube 6.2 with Java Plugin 4.4 supports property sonar.jacoco.reportPaths, позволяющая указать несколько местоположений.

+0

Thanks @Godin; «destinationFile», похоже, работает, но как я могу последовательно удалить старые данные exec перед новым запуском? Использование задачи 'jacocoMerge', похоже, имеет тот же результат (... кроме того, что хранятся исходные файлы' * .exec'), но файл автоматически восстанавливается следующей сборкой. Однако мне не удалось интегрировать это в нужное место (см. Комментарий в главном 'build.gradle' в проекте github). –

+0

'sonar.jacoco.reportPaths' выглядит многообещающим, но, похоже, его игнорируют (покрытие по-прежнему 50%, logfile говорит' Property 'sonar.jacoco.reportPath' устарел. Вместо этого используйте 'sonar.jacoco.reportPaths'.) I обновил основную 'build.gradle' с моей попыткой. –

+0

@sk_dev о первом вопросе с первого комментария - почему бы не поместить его в каталог сборки, так что он будет очищен на './gradlew clean build' – Godin