Gradle, Android, Jacoco и JUnit5
Теперь, с выпуском JUnit 5.0, я изо всех сил пытаюсь получить данные покрытия кода, используя jacoco.
Мой проект является многомодульным, и моя проблема в том, что для каждого модуля нет файла exec. Только один в корневом проекте (который кажется почти пустым). Я не смог найти актуальное руководство для этого.
Я пробовал разные подходы, описанные здесь: Gradle Jacoco и JUnit5, но безуспешно.
У кого-нибудь есть рабочая установка в многомодульном (не Android) проекте Gradle с JUnit5 и Jacoco?
Или проект Gradle Android с JUnit5 и Jacoco? Любые советы высоко ценится. Приветствуются даже уродливые хаки, пока не будет официальной документации.
Соответствующая часть моего кода (где запуск JUnit5 работает как в командной строке, так и из IDE по крайней мере):
<Root> build.gradle:
buildscript {
dependencies {
...
classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.0'
classpath "de.mannodermaus.gradle.plugins:android-junit5:1.0.0"
}
}
...
apply plugin: 'org.junit.platform.gradle.plugin'
ext.junitVintageVersion = '4.12.0'
ext.junitPlatformVersion = '1.0.0'
ext.junitJupiterVersion = '5.0.0'
subprojects {
apply plugin: "jacoco"
jacoco {
toolVersion = "0.7.6.201602180812"
}
...
junitPlatform {
filters {
engines {
include 'junit-jupiter', 'junit-vintage'
}
tags {
exclude 'slow'
}
includeClassNamePatterns '.*Test', '.*Tests'
}
}
}
...
dependencies {
// org.junit.platform.commons.util.PreconditionViolationException:
// Cannot create Launcher without at least one TestEngine; consider adding an engine implementation JAR to the classpath
testCompile("org.junit.jupiter:junit-jupiter-engine:${junitJupiterVersion}")
}
2 ответа
Я пробовал разные подходы, описанные здесь: Gradle Jacoco и JUnit5, но безуспешно.
Для не Android-проектов эти подходы выглядят хорошо.
У кого-нибудь есть рабочая установка в многомодульном (не Android) проекте Gradle с JUnit5 и Jacoco?
Но в любом случае ниже приведен полный рабочий пример не Android- проекта.
Или проект Gradle Android с JUnit5 и Jacoco?
Имейте в виду, что проекты Android - совершенно разные звери по сравнению с не Android, включая, но не ограничиваясь, настройку / выполнение тестов и вычисление покрытия.
В частности - по умолчанию библиотека JaCoCo ( http://www.jacoco.org/jacoco/index.html) изменяет классы для записи покрытия "на лету" во время выполнения приложения с использованием агента Java. И этот режим - именно то, что обеспечивает стандартный плагин JaCoCo Gradle ( https://docs.gradle.org/4.1/userguide/jacoco_plugin.html).
Агенты Java не могут использоваться на Android, поэтому для Android смена классов происходит в автономном режиме ( http://www.jacoco.org/jacoco/trunk/doc/offline.html) во время сборки с помощью плагина Android Gradle. ( https://developer.android.com/studio/releases/gradle-plugin.html).
Также кажется, что org.junit.platform:junit-platform-gradle-plugin
неприменимо к проектам Android - там есть https://github.com/aurae/android-junit5 и в настоящее время открытое обсуждение освещения в https://github.com/aurae/android-junit5/issues/4
Не будучи ежедневным разработчиком проектов Android, я не могу предоставить больше информации, чем эта.
settings.gradle
:
include 'a'
include 'b'
build.gradle
:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.0'
}
}
ext.junitJupiterVersion = '5.0.0'
subprojects {
repositories {
mavenCentral()
}
apply plugin: 'java'
apply plugin: 'org.junit.platform.gradle.plugin'
apply plugin: 'jacoco'
jacoco {
toolVersion = '0.7.9'
applyTo junitPlatformTest
}
junitPlatformTest {
jacoco {
destinationFile = file("$buildDir/jacoco/test.exec")
}
}
dependencies {
testCompile("org.junit.jupiter:junit-jupiter-api:${junitJupiterVersion}")
testRuntime("org.junit.jupiter:junit-jupiter-engine:${junitJupiterVersion}")
}
}
task wrapper(type: Wrapper) {
gradleVersion = '4.1'
}
a/src/main/java/A.java
:
public class A {
}
a/src/test/java/ATest.java
:
public class ATest {
@org.junit.jupiter.api.Test
public void test() {
new A();
}
}
b/src/main/java/B.java
:
public class B {
}
b/src/test/java/BTest.java
:
public class BTest {
@org.junit.jupiter.api.Test
public void test() {
new B();
}
}
После исполнения gradle test jacocoTestReport
файлы a/build/jacoco/test.exec
а также b/build/jacoco/test.exec
генерируются также отчеты, показанные ниже.
a/build/reports/jacoco/test/html/index.html
:
b/build/reports/jacoco/test/html/index.html
:
Благодаря руководству примера Godin мне удалось заставить работать * покрытие кода (проверьте, открыв сгенерированный файл.exec в вашей IDE и убедитесь, что покрытие отображается):
* Некоторые значения охватывают тесты JUnit4, выполняемые под JUnit5
gradlew junitPlatformTestDebug
-> $buildDir/jacoco/junitPlatformTestDebug.exec
settings.gradle:
include 'a'
include 'b'
build.gradle (родительский):
buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
classpath 'de.mannodermaus.gradle.plugins:android-junit5:1.0.0'
}
}
subprojects {
apply plugin: 'jacoco'
jacoco {
toolVersion = '0.7.9'
}
}
build.gradle (a - основное приложение):
apply plugin: 'com.android.application'
apply plugin: 'de.mannodermaus.android-junit5'
android {
testOptions {
unitTests.all {
jacoco {
includeNoLocationClasses = true
}
}
}
junitPlatform {
jupiterVersion '5.0.0'
vintageVersion '4.12.0'
}
}
dependencies {
testCompile junit5()
}
project.afterEvaluate {
// Workaround: https://stackru.com/questions/39362955/gradle-jacoco-and-junit5/39386661#39386661
apply plugin: "jacoco"
jacoco {
applyTo junitPlatformTestDebug
}
}
build.gradle (b - модуль библиотеки Android):
apply plugin: 'com.android.library'
apply plugin: 'de.mannodermaus.android-junit5'
android {
testOptions {
unitTests.all {
jacoco {
includeNoLocationClasses = true
}
}
junitPlatform {
jupiterVersion '5.0.0'
vintageVersion '4.12.0'
}
}
dependencies {
testCompile junit5()
}
project.afterEvaluate {
// Workaround: https://stackru.com/questions/39362955/gradle-jacoco-and-junit5/39386661#39386661
apply plugin: "jacoco"
jacoco {
applyTo junitPlatformTestDebug
}
}