Le plugin offre la possibilité d'effectuer un test de mutation et de calculer une couverture de mutation de projets basés sur Gradle avec PIT.
Ajoutez Gradle-Pitest-Plugin à la configuration plugins dans votre fichier build.gradle :
plugins {
id ' java ' // or 'java-library' - depending on your needs
id ' info.solidsoft.pitest ' version ' 1.15.0 '
}plugins {
id( " java " ) // or "java-library" - depending on your needs
id( " info.solidsoft.pitest " ) version " 1.15.0 "
}Appelez Gradle avec la tâche la plus pitoyante:
gradle pitest
Après les mesures, un rapport créé par PIT sera placé dans ${PROJECT_DIR}/build/reports/pitest .
Facultativement, le faire dépendre de la construction:
build . dependsOn ' pitest 'tasks.build {
dependsOn( " pitest " )
} Notez que lors de la création de tâche la plus pitest , il doit être mentionné par son nom. Sinon, Gradle résoudra pitest à la configuration et non à la tâche.
"The plugins Way" a certaines limites. Comme le référentiel principal du plugin est le référentiel central (alias Maven Central), il est également possible d'ajouter le plugin à votre projet en utilisant "The Generic Way":
buildscript {
repositories {
mavenCentral()
// Needed only for SNAPSHOT versions
// maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
}
dependencies {
classpath ' info.solidsoft.gradle.pitest:gradle-pitest-plugin:1.15.0 '
}
}buildscript {
repositories {
mavenCentral()
// Needed only for SNAPSHOT versions
// maven {
// url = uri("https://oss.sonatype.org/content/repositories/snapshots/")
// }
}
dependencies {
classpath( " info.solidsoft.gradle.pitest:gradle-pitest-plugin:1.15.0 " )
}
}Appliquer le plugin:
apply plugin : ' java ' // or 'java-library' - depending on your needs
apply plugin : ' info.solidsoft.pitest ' apply (plugin = " java " ) // or "java-library" - depending on your needs
apply (plugin = " info.solidsoft.pitest " ) Le plugin le plus pitable n'a pas besoin d'être configuré en outre si vous utilisez Junit 4. La personnalisation est effectuée dans le bloc pitest :
pitest {
targetClasses = [ ' our.base.package.* ' ] // by default "${project.group}.*"
pitestVersion = ' 1.15.0 ' // not needed when a default PIT version should be used
threads = 4
outputFormats = [ ' XML ' , ' HTML ' ]
timestampedReports = false
}Configuration idiomatique et plus portable:
pitest {
targetClasses.set( setOf ( " our.base.package.* " )) // by default "${project.group}.*"
pitestVersion.set( " 1.15.0 " ) // not needed when a default PIT version should be used
threads.set( 4 )
outputFormats.set( setOf ( " XML " , " HTML " ))
timestampedReports.set( false )
} À partir de Gradle 8.1, une affectation de propriété simple peut être utilisée pour configurer le plugin (au lieu de la méthode set() ):
pitest {
targetClasses = setOf ( " our.base.package.* " ) // by default "${project.group}.*"
pitestVersion = " 1.15.0 " // not needed when a default PIT version should be used
threads = 4
outputFormats = setOf ( " XML " , " HTML " )
timestampedReports = false
} La configuration de Gradle est le véritable code Groovy qui rend toutes les affectations très intuitives. Toutes les valeurs attendues par PIT doivent être transmises en tant que types correspondants. Il n'y a qu'une seule différence importante. Pour les paramètres où PIT s'attend à une liste de chaînes séparées par le coma dans une configuration de gradle, une liste de chaînes doit être utilisée (voir outputFormats dans l'exemple ci-dessus).
Vérifiez la documentation PIT pour une liste de tous les paramètres de ligne de commande disponibles. Le format de paramètre attendu dans une configuration de plugin peut être prélevé sur PitestPluginextension.
Pour rendre la vie plus facile taskClasspath , mutableCodePaths , sourceDirs , reportDir , verbosity et pitestVersion sont automatiquement définis par le plugin. En outre, sourceDirs , reportDir , verbosity et pitestVersion peuvent être remplacés par un utilisateur.
Il existe quelques paramètres spécifiques du plugin Gradle:
testSourceSets - définit les ensembles de sources de test qui doivent être utilisés par PIT (par défaut SourcesetSeT.Test, mais permet d'ajouter des tests d'intégration situés dans un ensemble de source différent)mainSourceSets - Définit les principaux ensembles de source qui doivent être utilisés par PIT (par défaut SourcesetSeT.Main)mainProcessJvmArgs - Arguments JVM à utiliser lors du lancement du processus de fosse principal; Notez que Pit lui-même lance un autre processus Java pour l'exécution des tests de mutation et que jvmArgs doivent généralement être utilisés pour par exemple augmenter la taille maximale de la mémoire (voir # 7);additionalMutableCodePaths - Classes supplémentaires à muter (utile pour les tests d'intégration avec le code de production dans un module différent - voir # 25)useClasspathFile - permet de passer un ClassPath supplémentaire en tant que contenu de fichier (utile pour les utilisateurs de Windows avec de nombreux éléments de ClassPath, désactivés par défaut)fileExtensionsToFilter - offre la possibilité de filtrer les extensions de fichiers supplémentaires à partir de Pit ClassPath (voir # 53)Par exemple:
pitest {
.. .
testSourceSets = [sourceSets . test, sourceSets . integrationTest]
mainSourceSets = [sourceSets . main, sourceSets . additionalMain]
jvmArgs = [ ' -Xmx1024m ' ]
useClasspathFile = true // useful with bigger projects on Windows
fileExtensionsToFilter . addAll( ' xml ' , ' orbit ' )
}pitest {
.. .
testSourceSets.set( listOf (sourceSets.test.get(), sourceSets.getByName( " integrationTest " )))
mainSourceSets.set( listOf (sourceSets.main.get(), sourceSets.getByName( " additionalMain " )))
jvmArgs.set( listOf ( " -Xmx1024m " ))
useClasspathFile.set( true ) // useful with bigger projects on Windows
fileExtensionsToFilter.addAll( " xml " , " orbit " )
}Pit exécute des tests dans un JVM indépendamment de la JVM utilisée par Gradle pour exécuter des tests. Si vos tests nécessitent certaines propriétés du système, vous devez les passer pour se mettre en puits car le plugin ne le fera pas pour vous:
test {
systemProperty ' spring.test.constructor.autowire.mode ' , ' all '
}
pitest {
jvmArgs = [ ' -Dspring.test.constructor.autowire.mode=all ' ]
}tasks.test {
systemProperty( " spring.test.constructor.autowire.mode " , " all " )
}
pitest {
jvmArgs.set( listOf ( " -Dspring.test.constructor.autowire.mode=all " ))
} Comme indiqué dans l'idée # 170 Intellij affiche des avertissements sur la définition des champs finaux (de la configuration paresseuse) dans build.gradle . Ce n'est pas un vrai problème car Gradle intercepte en interne ces appels et utilise un secteur à la place. Néanmoins, les personnes qui préfèrent n'avoir pas (moins) d'avertissements au prix d'un code moins lisible peuvent utiliser des setters à la place, par exemple:
testSourceSets . set([sourceSets . test, sourceSets . integrationTest])
mainSourceSets . set([sourceSets . main, sourceSets . additionalMain])
jvmArgs . set([ ' -Xmx1024m ' ])
useClasspathFile . set( true ) // useful with bigger projects on Windows
fileExtensionsToFilter . addAll( ' xml ' , ' orbit ' )Gradle-Pitest-Plugin peut être utilisé dans des projets multi-modules. La dépendance Gradle-Pitest-Plugin doit être ajoutée à la configuration de BuildScript dans le projet racine tandis que le plugin doit être appliqué dans tous les sous-projets qui doivent être traités avec Pit. Un exemple d'extrait de build.gradle situé pour le projet racine:
// in root project configuration
plugins {
id ' info.solidsoft.pitest ' version ' 1.15.0 ' apply false
}
subprojects {
apply plugin : ' java '
apply plugin : ' info.solidsoft.pitest '
pitest {
threads = 4
if (project . name in [ ' module-without-any-test ' ]) {
failWhenNoMutations = false
}
}
} // in root project configuration
plugins {
id( " info.solidsoft.pitest " ) version " 1.15.0 "
}
subprojects {
apply (plugin = " java " )
apply (plugin = " info.solidsoft.pitest " )
pitest {
threads.set( 4 )
if (project.name in setOf ( " module-without-any-test " )) {
failWhenNoMutations.set( false )
}
}
} Il est possible d'agréger le rapport le plus pitable pour le projet multi-modules à l'aide du plugin info.solidsoft.pitest.aggregator et de tâche pitestReportAggregate . Le projet racine doit être correctement configuré pour utiliser pitestReportAggregate :
// in root project configuration
plugins {
id ' info.solidsoft.pitest ' version ' 1.15.0 ' apply false
}
apply plugin : ' info.solidsoft.pitest.aggregator ' // to 'pitestReportAggregate' appear
subprojects {
apply plugin : ' java '
apply plugin : ' info.solidsoft.pitest '
pitest {
// export mutations.xml and line coverage for aggregation
outputFormats = [ " XML " ]
exportLineCoverage = true
timestampedReports = false
.. .
reportAggregator { // since 1.9.11 - extra results validation, if needed
testStrengthThreshold . set( 50 ) // simpler Groovy syntax (testStrengthThreshold = 50) does not seem to be supported for nested properties
mutationThreshold . set( 40 )
maxSurviving . set( 3 )
}
}
} // in root project configuration
plugins {
id( " info.solidsoft.pitest " ) version " 1.15.0 "
}
apply (plugin = " info.solidsoft.pitest.aggregator " )
subprojects {
apply (plugin = " java " )
apply (plugin = " info.solidsoft.pitest " )
pitest {
outputFormats.set( setOf ( " XML " ))
timestampedReports.set( false )
exportLineCoverage.set( true )
.. .
reportAggregator {
testStrengthThreshold.set( 50 )
mutationThreshold.set( 40 )
maxSurviving.set( 3 )
}
}
} Après l'exécution ${PROJECT_DIR}/build/reports/pitest tâches pitest pitestReportAggregate
Il est possible de muter le code situé dans différents sous-projets. Gradle en interne ne s'appuie pas sur le répertoire de sortie à partir d'un autre sous-projet, mais construit un pot et utilise des classes à partir de celui-ci. Pour la pit, ce sont deux ensembles différents de fichiers de classe, donc pour le faire fonctionner, il est nécessaire de définir à la fois mainSourceSets et additionalMutableCodePaths . Par exemple:
configure(project( ' :itest ' )) {
apply plugin : ' info.solidsoft.pitest '
dependencies {
implementation project( ' :shared ' )
}
configurations { mutableCodeBase { transitive false } }
dependencies { mutableCodeBase project( ' :shared ' ) }
pitest {
mainSourceSets = [project . sourceSets . main, project( ' :shared ' ) . sourceSets . main]
additionalMutableCodePaths = [configurations . mutableCodeBase . singleFile]
}
}configure( listOf (project( " :itest " ))) {
apply (plugin = " info.solidsoft.pitest " )
dependencies {
implementation(project( " :shared " ))
}
val mutableCodeBase by configurations.creating { isTransitive = false }
dependencies { mutableCodeBase(project( " :shared " )) }
pitest {
mainSourceSets.set( listOf (project.sourceSets.main.get(), project( " :shared " ).sourceSets.main.get()))
additionalMutableCodePaths.set( listOf (mutableCodeBase.singleFile))
}
}Ce qui précède est le moyen recommandé par l'équipe Gradle, mais dans des cas spécifiques, la solution plus simple devrait également fonctionner:
configure(project( ' :itest ' )) {
apply plugin : ' info.solidsoft.pitest '
dependencies {
implementation project( ' :shared ' )
}
pitest {
mainSourceSets = [project . sourceSets . main, project( ' :shared ' ) . sourceSets . main]
additionalMutableCodePaths = project( ' :shared ' ) . jar . outputs . files . getFiles()
}
}configure( listOf (project( " :itest " ))) {
apply (plugin = " info.solidsoft.pitest " )
dependencies {
implementation(project( " :shared " ))
}
pitest {
mainSourceSets.set( listOf (project.sourceSets.main.get(), project( " :shared " ).sourceSets.main.get()))
additionalMutableCodePaths.set(project( " :shared " ).task( " jar " ).outputs.files)
}
}La construction multi-projets de travail minimale est disponible dans la suite de tests fonctionnels.
Les plugins de test sont utilisés pour prendre en charge différents cadres de test que JUnit4.
En commençant par cette version, la configuration requise pour utiliser la fosse avec Junit 5 a été simplifiée à ce qui suit:
plugins {
id ' java '
id ' info.solidsoft.pitest ' version ' 1.15.0 '
}
pitest {
// adds dependency to org.pitest:pitest-junit5-plugin and sets "testPlugin" to "junit5"
junit5PluginVersion = ' 1.0.0 ' // or 0.15 for PIT <1.9.0
// ...
}plugins {
id( " java " )
id( " info.solidsoft.pitest " ) version " 1.15.0 "
}
pitest {
// adds dependency to org.pitest:pitest-junit5-plugin and sets "testPlugin" to "junit5"
junit5PluginVersion.set( " 1.0.0 " )
}Veuillez noter . Pit 1.9.0 nécessite le plus pit-junit5-Plugin 1.0.0+. Junit Jupiter 5.8 (plate-forme JUnit 1.8) nécessite le Plut-Junit5-Plugin 0,15+, tandis que 5,7 (1,7) nécessite 0,14. Définissez la version du plugin à droite pour la version JUnit 5 utilisée dans votre projet pour éviter les erreurs d'exécution (telles que `NosuchMethoDerror: 'java.util.optional org.junit.platform.commons.util.annotationutils.findannotation (java.lang.class, java.lang.class, boolean)').
L'exemple de travail minimal pour JUnit 5 est disponible dans la suite de tests fonctionnels.
Pour mélanger Junit 5 avec d'autres plugins à la fosse, vous pouvez lire cette section dans mon article de blog.
Pour activer les plugins Pit, il suffit de l'ajouter à la configuration la plus pitoyante de la fermeture BuildScript. Par exemple:
plugins {
id ' java '
id ' info.solidsoft.pitest ' version ' 1.15.0 '
}
repositories {
mavenCentral()
}
dependencies {
pitest ' org.example.pit.plugins:pitest-custom-plugin:0.42 '
}plugins {
id( " java " )
id( " info.solidsoft.pitest " ) version " 1.15.0 "
}
repositories {
mavenCentral()
}
dependencies {
pitest( " org.example.pit.plugins:pitest-custom-plugin:0.42 " )
}L'exemple de travail minimal est disponible dans la suite de tests fonctionnels.
Veuillez noter. Dans Gradle-Pitest-Plugin <1.5.0, la configuration pitest a dû être créée dans la portée buildscript pour le projet racine. Veuillez noter. En commençant par la fosse 1.6.7, il n'est plus nécessaire pour définir le paramètre de configuration testPlugin . Il est également obsolète dans le plugin Gradle.
Chaque version Gradle-Pitest-Plugin utilise par défaut une version prédéfinie. Habituellement, la dernière version publiée de Pit disponibles au moment de la publication d'une version de plugin. Il peut être remplacé en utilisant le paramètre pitestVersion dans une fermeture de configuration pitest .
Veuillez noter que dans certains cas, il pourrait y avoir des problèmes lors de l'utilisation de versions Pit non par défaut.
Sinon, autrement, Gradle-Pitest-Plugin 1.9.x par défaut utilise la pit 1.9.x, 1.7.x utilise la pit 1.7.x, etc. La version minimale de pit prise en charge est 1.7.1.
En commençant par la version 1.7.0 Gradle-Pitest-Plugin nécessite Gradle 6.4. La dernière version avec le support Gradle 5.x (5.6+) est de 1,6.0. La version actuelle a été automatiquement testée de fumée avec Gradle 6.4, 6.9.1 et 7.4.2 sous Java 11. Les tests avec Java 11+ sont limités aux versions compatibles de Gradle et Pit.
Le support expérimental de Java 17 peut être testé avec 1,7,0+.
À partir de la version 1.3.0, les binaires produits nécessitent Java 8 (en tant que JDK utilisé pour exécuter une version Gradle). Cependant, avec la sortie de Java 17 LTS en septembre 2021, à commencer par Gradle-Pitest-Plugin 1.9.0, la prise en charge de JDK <11 est dépréciée (voir # 299).
Voir le fichier Changelog pour une liste plus détaillée des modifications dans le plugin lui-même.
Gradle ne fournit pas de moyen intégré de remplacer la configuration du plugin via la ligne de commande, mais Gradle-Override-Plugin peut être utilisé pour le faire.
Après avoir appliqué Gradle-Override-Plugin dans votre projet, il est possible de faire après:
./gradlew pitest -Doverride.pitest.reportDir=build/pitReport -Doverride.pitest.threads=8
Note. Le mécanisme doit fonctionner correctement pour les propriétés de chaîne et numériques, mais il y a des limites avec la prise en charge des listes / ensembles / cartes et des valeurs booléennes.
Pour plus d'informations, voir la page Web du projet.
Gradle-Pitest-Plugin par défaut utilise une version pit correspondante (avec le même numéro). Le plugin est publié uniquement s'il y a des modifications internes ou si il est nécessaire de s'adapter aux modifications dans la version plus récente. Il existe un mécanisme dédié pour permettre d'utiliser la dernière version de Pit (par exemple, une version de BugFix) ou de rétrograder PIT en cas de problèmes détectés. Pour remplacer une version par défaut, il suffit de définir la propriété pitestVersion dans la fermeture de configuration pitest .
pitest {
pitestVersion = ' 2.8.1-the.greatest.one '
}pitest {
pitestVersion.set( " 2.8.1-the.greatest.one " )
}En cas d'erreurs détectées lorsque la dernière version disponible du plugin est utilisée avec une version plus récente, veuillez résoudre un problème.
Placer les rapports de pit directement dans ${PROJECT_DIR}/build/reports/pitest peut être activé avec une propriété timestampedReports :
pitest {
timestampedReports = false
}pitest {
timestampedReports.set( false )
}Parfois, il peut être utile de déboguer une exécution gradle-pipest-plagin ou une exécution de pit elle-même (par exemple NPE dans Pit) pour fournir un rapport d'erreur judicieux.
L'exécution Gradle-Pitest-Plugin peut être débogue à distance avec l'ajout -Dorg.gradle.debug=true à la ligne de commande.
Cependant, à mesure que la PIT est démarrée comme un processus distinct pour déboguer son exécution, les arguments suivants doivent être ajoutés à la configuration du plugin:
pitest {
mainProcessJvmArgs = [ ' -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005 ' ]
}pitest {
mainProcessJvmArgs.set( listOf ( " -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005 " ))
}La réponse courte est: pas directement. En raison de certaines incompatibilités entre les applications Java "standard" et les applications Java Android dans Gradle, le plugin ne prend pas en charge la dernière. Heureusement, il existe une fourche Android du plugin entretenu par Karol Wrótniak qui fournit une version modifiée prenant en charge les applications Android (mais en revanche, elle ne fonctionne pas avec des applications Java standard).
Gradle-Pitest Plugin 1.5.0 a finalement détendu la façon dont (où) la configuration pitest a été placée (# 62) qui générait également des avertissements de dépréciation dans Gradle 6+. Ce changement n'est pas compatible en arrière et, par conséquent, la migration manuelle doit être effectuée - voir les notes de publication. Cela affecte uniquement le projet avec des plugins personnalisés externes.
Important . Comme le plugin JUnit 5 pour PIT est certainement le plus populaire, à commencer par 1.4.7, il existe une façon simplifiée comment elle pourrait être configurée avec junit5PluginVersion (qui est définitivement recommandée ). Voir mon article de blog pour savoir comment migrer (il résout également le problème de compatibilité avec 1.5.0+).
verbosity introduite avec la fosse 1.7.1) Gradle-Pitest-Plugin cloné du référentiel peut être construit à l'aide de la commande gradle:
./gradlew build
Le moyen le plus simple de rendre un pot avec des changements locaux visibles dans un autre projet est de l'installer dans le référentiel Maven local:
./gradlew install
Il existe également des tests fonctionnels de base écrits à l'aide de NEBULA-TEST qui peuvent être exécutés avec:
./gradlew funcTest
Gradle-Pitest-Plugin a été écrit par Marcin Zajączkowski avec l'aide de contributeurs. L'auteur peut être contacté directement par e-mail: MSZPAK ATT WP DOTT PL. Il y a aussi le blog de Marcin disponible: Solid Soft - Le code de travail ne suffit pas.
Le plugin a sûrement des bogues et des fonctionnalités manquantes. Ils peuvent être signalés en utilisant un tracker de problème. Cependant, c'est souvent une meilleure idée d'envoyer d'abord une question à la liste de diffusion des stands.
Le plugin est concédé sous licence de la licence Apache, version 2.0.