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 и, следовательно, неизвестно при анализе script.

Следующий хак необходим для того, чтобы все еще можно было определить задачу 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

Вы можете запускать все тесты, в которых отсутствуют теги unit и integing, используя

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
}

Ответы

Ответ 1

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

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
            })
}

Ответ 2

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

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 задачей

Ответ 3

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

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

  // do something with the junitPlatformTestTask
}

Подробнее см. мои комментарии по GitHub для JUnit 5.

Ответ 4

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

@RunWith(JUnitPlatform.class)
public class ClassTest {
}