Покрытие кода Jacoco прекратилось с переходом на Java 11 - PullRequest
1 голос
/ 25 апреля 2019

У меня есть несколько проектов Gradle, которые были построены с использованием Java 8, и после недавнего преобразования их в Java 11 отчеты об охвате кода Jacoco сообщали о гораздо более низком процентном соотношении, чем раньше. В одном проекте, сразу после перехода, мое покрытие упало с 81% до 16%.

Я пытался обновить плагин Jacoco до 0.8.3 (который имеет официальную поддержку JDK 11 ), Gradle до 5.4 и TestNG до 6.14.3 (не уверен, что это имеет какой-либо эффект; думал, что это не могло больно быть на последней версии). Даже после этих изменений упомянутый выше проект имеет 16% охват. Я вручную проверил несколько классов, в которых было зарегистрировано 0% покрытия, и обнаружил, что у них действительно есть тестовое покрытие.

Например, я добавил этот метод в один из моих классов:

public String helloWorld(){
        return "hello";
    }

Затем я использовал его в тесте:

@Test(groups = IntegrationTest.INTEGRATION_GROUP)
    public void testHelloWorld() {
        String helloWorld = authManager.helloWorld();
        assertEquals(helloWorld, "hello");
    }

И покрытие сообщается как 0:

enter image description here

Если это полезно, вот мои настройки Jacoco Gradle. Я использую пользовательский плагин для их настройки.

  class ManagedJacocoPlugin implements ManagedPlugin {
  @Override
  void apply(PluginManager pluginManager) {
    pluginManager.apply(JacocoPlugin.class)
  }

  @Override
  void configure(Project project, GradlePluginConfig pluginConfig) {
    def jacoco = project.extensions.getByName("jacoco")
    jacoco.toolVersion = "0.8.3"

    def jacocoTestReport = project.tasks.getByName('jacocoTestReport')
    jacocoTestReport.reports {
      xml.enabled false
      csv.enabled false
    }

    project.tasks.withType(Test).each { t ->
      t.jacoco {
        destinationFile = project.file("$project.buildDir/jacoco/test.exec")
      }
    }

    jacocoTestReport.dependsOn "integrationTest"
  }
}

Насколько я могу понять, Java 11 должна полностью поддерживаться для покрытия Jacoco, учитывая версии инструментов, которые я использую. Что мне здесь не хватает?

1 Ответ

3 голосов
/ 01 мая 2019

Вот что страница https://stackoverflow.com/help/mcve говорит о том, как создать минимальный, полный и проверяемый пример:

Убедитесь, что он завершен

Скопируйте код изВаш вопрос в новый файл или проект, затем запустите его.Если он не работает для вас, то он не будет работать для кого-либо еще.

Однако кто знает, что такое ManagedPlugin в вашем примере?

Но хорошо, давайтепопробуйте следовать приведенному выше совету и использовать то, что у нас есть, притворяясь, что у нас есть время угадать, и что нам повезет правильно угадать.

Все, кроме ManagedPlugin после добавления множества пропущенных фигур, становится следующимbuild.gradle

apply plugin: 'java'
apply plugin: 'jacoco'

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'org.testng', name: 'testng', version: '6.14.3'
}

test {
    useTestNG() {
        includeGroups('unit')
    }
}

task integrationTest(type: Test, dependsOn: ['test']) {
    useTestNG() {
        includeGroups('integration')
    }
}


def jacoco = project.extensions.getByName("jacoco")
jacoco.toolVersion = "0.8.3"

def jacocoTestReport = project.tasks.getByName('jacocoTestReport')
jacocoTestReport.reports {
    xml.enabled false
    csv.enabled false
}

project.tasks.withType(Test).each { t ->
    t.jacoco {
        destinationFile = project.file("$project.buildDir/jacoco/test.exec")
    }
}

jacocoTestReport.dependsOn "integrationTest"

метод helloWorld входит в src/main/Example.java

class Example {
    public String helloWorld() {
        return "hello";
    }
}

метод testHelloWorld входит в src/test/ExampleTest.java

import org.testng.annotations.Test;
import static org.testng.Assert.*;

class ExampleTest {
    Example authManager = new Example();

    @Test(groups = "integration")
    public void testHelloWorld() {
        String helloWorld = authManager.helloWorld();
        assertEquals(helloWorld, "hello");
    }
}

Выполнениеgradle clean jacocoTestReport с использованием Gralde 5.4 и JDK 11.0.1 создает следующий отчет

report 1

Таким образом, мы можем заключить, что приведенный пример определенно не завершен.

Давайте попробуем угадать и добавить в src/main/java/Example.java

    public void anotherMethod() {
    }

и в src/test/java/ExampleTest.java

    @Test(groups = "unit")
    public void test() {
       new Example().anotherMethod();
    }

Теперь выполнение gradle clean jacocoTestReport дает следующий отчет

report 2

Кажется, что теперь мы можем воспроизвести вашу проблему.

Почему anotherMethod не покрывается?Давайте последуем другому замечательному совету из https://stackoverflow.com/help/mcve:

Разделяй и властвуй. Если у вас есть небольшой объем кода, но источник проблемы совершенно неясенначинайте постепенно удалять код, пока проблема не исчезнет, ​​- затем добавьте последнюю часть обратно.

, которая также работает не только для кода, но и для изменений в версиях - давайте попробуем отменить ваше изменениеверсии Gradle с 5.4 до 4.10.3, и с ее помощью выполнение gradle clean jacocoTestReport дает

report 3

Таким образом, мы можем сделать вывод, что что-то вGradle был изменен .Давайте проверим его журнал изменений - https://docs.gradle.org/5.0/release-notes.html содержит очень интересное утверждение:

Плагин JaCoCo теперь работает с кэшем сборки и параллельным выполнением теста

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

Задача integrationTest удаляет данные, собранные задачей test.Давайте попробуем не использовать один и тот же файл:

//project.tasks.withType(Test).each { t ->
//    t.jacoco {
//        destinationFile = project.file("$project.buildDir/jacoco/test.exec")
//    }
//}

jacocoTestReport.executionData(test)
jacocoTestReport.executionData(integrationTest)

Теперь выполнение gradle clean jacocoTestReport даже с Gradle 5.4 дает

report 4

...