Nous venons de porter nos tests unitaires sur JUnit5. En réalisant qu'il s'agit encore d'une adoption assez précoce, avec quelques indices sur Google.
Le plus difficile a été d'obtenir une couverture de code jacoco pour les tests Junit5 que nous utilisons sur Jenkins. Comme cela m’a pris presque une journée à comprendre, je pensais partager. Néanmoins, si vous connaissez une meilleure solution, je serais intéressé de le savoir!
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'
Ensuite, le problème semble être que junitPlatformTest, tel que défini dans le fichier org.junit.platform.gradle.plugin, est défini également À la fin de la phase de cycle de vie de Gradle et n'est donc pas connu lors de l'analyse du script.
Le hack suivant est nécessaire pour pouvoir toujours définir une tâche jacoco qui observe la tâche 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
})
}
}
Enfin, il est nécessaire de configurer le plugin junitPlatform. Le code suivant autorise la configuration en ligne de commande des balises Junit 5 à exécuter: Vous pouvez exécuter tous les tests avec la balise 'unit' en exécutant:
gradle clean junitPlatformTest -PincludeTags=unit
Vous pouvez exécuter tous les tests pour lesquels il manque des balises unit et integ en utilisant
gradle clean junitPlatformTest -PexcludeTags=unit,integ
Si aucune balise n'est fournie, tous les tests seront exécutés (par défaut).
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
}
Merci, le hack ressemble maintenant à ceci:
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
})
}
Peut également être résolu par injection directe d’agent:
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"
}
}
}
}
alors le rapport sera disponible avec la tâche jacocoTestReport
Pour obtenir une référence à la tâche junitPlatformTest
, une autre option consiste à implémenter un bloc afterEvaluate
dans le projet, comme suit:
afterEvaluate {
def junitPlatformTestTask = tasks.getByName('junitPlatformTest')
// do something with the junitPlatformTestTask
}
Voir mes commentaires sur GitHub pour JUnit 5 pour d'autres exemples.