Gradle Jacoco и JUnit5

Мы просто портировали наши юнит-тесты на JUnit5. Понимая, что это все еще довольно раннее принятие с небольшими намеками на Google.

Самым сложным было получить покрытие кода jacoco для тестов Junit5, которые мы используем на jenkins. Поскольку это заняло у меня почти день, чтобы понять, я решил поделиться. Тем не менее, если вы знаете лучшее решение, мне было бы интересно узнать!

buildscript {

    dependencies {
       // dependency needed to run junit 5 tests
       classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.0-M2'
   }
}

// include the jacoco plugin
plugins {
    id 'jacoco'
}

dependencies {
    testCompile "org.junit.jupiter:junit-jupiter-api:5.0.0-M2"
    runtime "org.junit.jupiter:junit-jupiter-engine:5.0.0-M2"
    runtime "org.junit.vintage:junit-vintage-engine:4.12.0-M2"
}

apply plugin: 'org.junit.platform.gradle.plugin'

Тогда проблема, по-видимому, заключается в том, что junitPlatformTest, как определено в org.junit.platform.gradle.plugin, определен слишком поздно на этапе жизненного цикла gradle и, следовательно, неизвестен при синтаксическом анализе сценария.

Следующий хак нужен для того, чтобы все еще иметь возможность определить задачу jacoco, которая наблюдает за задачей junitPlatformTest.

tasks.whenTaskAdded { task ->
    if (task.name.equals('junitPlatformTest')) {
        System.out.println("ADDING TASK " + task.getName() + " to the project!")

    // configure jacoco to analyze the junitPlatformTest task
    jacoco {
        // this tool version is compatible with
        toolVersion = "0.7.6.201602180812"
        applyTo task
    }

    // create junit platform jacoco task
    project.task(type: JacocoReport, "junitPlatformJacocoReport",
            {
                sourceDirectories = files("./src/main")
                classDirectories = files("$buildDir/classes/main")
                executionData task
            })
    }
}

Наконец, необходимо настроить плагин junitPlatform. Следующий код разрешает настройку командной строки, из которой должны запускаться теги junit 5: Вы можете запустить все тесты с тегом "unit", выполнив:

gradle clean junitPlatformTest -PincludeTags=unit

Вы можете запустить все тесты, в которых отсутствует как единичный тег, так и тег целых

gradle clean junitPlatformTest -PexcludeTags=unit,integ

Если теги не указаны, будут запущены все тесты (по умолчанию).

junitPlatform {

    engines {
        include 'junit-jupiter'
        include 'junit-vintage'
    }

    reportsDir = file("$buildDir/test-results")

    tags {
        if (project.hasProperty('includeTags')) {
            for (String t : includeTags.split(',')) {
                include t
            }
        }

        if (project.hasProperty('excludeTags')) {
            for (String t : excludeTags.split(',')) {
                exclude t
            }
        }
    }

    enableStandardTestTask false
}

4 ответа

Спасибо, так что хак теперь выглядит так:

project.afterEvaluate {
    def junitPlatformTestTask = project.tasks.getByName('junitPlatformTest')

    // configure jacoco to analyze the junitPlatformTest task
    jacoco {
        // this tool version is compatible with
        toolVersion = "0.7.6.201602180812"
        applyTo junitPlatformTestTask
    }

    // create junit platform jacoco task
    project.task(type: JacocoReport, "junitPlatformJacocoReport",
            {
                sourceDirectories = files("./src/main")
                classDirectories = files("$buildDir/classes/main")
                executionData junitPlatformTestTask
            })
}

Можно также решить с помощью прямой инъекции агента:

subprojects {
   apply plugin: 'jacoco'

   jacoco {
        toolVersion = "0.7.9"
   }

   configurations {
        testAgent {
            transitive = false
        }
   }

   dependencies {
        testAgent("org.jacoco:org.jacoco.agent:0.7.9:runtime")
   }

   tasks.withType(JavaExec) {
        if (it.name == 'junitPlatformTest') {
            doFirst {
                jvmArgs "-javaagent:${configurations.testAgent.singleFile}=destfile=${project.buildDir.name}/jacoco/test.exec"
            }
        }
    }
}

тогда отчет будет доступен с jacocoTestReport задача

Чтобы получить ссылку на junitPlatformTest задача, другой вариант заключается в реализации afterEvaluate блок в проекте так:

afterEvaluate {
  def junitPlatformTestTask = tasks.getByName('junitPlatformTest')

  // do something with the junitPlatformTestTask
}

Смотрите мои комментарии на GitHub для JUnit 5 для дальнейших примеров.

Вам просто нужно добавить @RunWith(JUnitPlatform.class) в ваш пакет

@RunWith(JUnitPlatform.class)
public class ClassTest {
}
Другие вопросы по тегам