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:

а / сборки / отчеты / jacoco / тест / html / index.html

b/build/reports/jacoco/test/html/index.html:

б / сборки / отчеты / jacoco / тест / 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
    }
}
Другие вопросы по тегам