Webinaire en vedette : MISRA C++ 2023 : tout ce que vous devez savoir | Voir le séminaire

Tirer parti des avantages de JUnit 5

Portrait de Brian McGlauflin,
6 mai 2020
8 min lire

En plus d'aider les développeurs à mettre en œuvre des tests unitaires en Java et à améliorer la vitesse de programmation, les tests JUnit offrent de nombreux avantages. Dans cet article, vous découvrirez ces avantages et pourquoi vous devriez utiliser les tests JUnit pour votre développement.

Une version de cet article a été publiée pour la première fois sur le Blog Oracle.

Cela fait quelques années depuis la sortie de Unité 5. Si vous n'avez pas encore commencé à l'utiliser pour vos tests de développement, vous devriez. JUnit 5 est livré avec une multitude de nouvelles fonctionnalités et améliorations qui peuvent vous faire gagner du temps et des maux de tête. Voyons comment démarrer avec JUnit 5 pour profiter des avantages des dernières technologies.

Raisons de migrer de JUnit 4 vers JUnit 5

Si vous utilisez JUnit 4 depuis un certain temps, la migration des tests peut sembler une tâche ardue. La bonne nouvelle est que vous n'avez probablement pas besoin de convertir de test - JUnit 5 peut exécuter des tests JUnit 4 en utilisant le Millésime bibliothèque, vous pouvez donc simplement commencer à écrire de nouveaux tests avec JUnit 5.

Voici quatre bonnes raisons de commencer à utiliser JUnit 5:

  • JUnit 5 exploite les fonctionnalités de Java 8 ou version ultérieure, comme les fonctions lambda, rendant les tests plus puissants et plus faciles à maintenir.
  • JUnit 5 a ajouté de nouvelles fonctionnalités très utiles pour décrire, organiser et exécuter des tests. Par exemple, les tests obtiennent de meilleurs noms d'affichage et peuvent être organisés de manière hiérarchique.
  • JUnit 5 est organisé en plusieurs bibliothèques, de sorte que seules les fonctionnalités dont vous avez besoin sont importées dans votre projet. Avec des systèmes de construction comme Maven et gradle, y compris les bonnes bibliothèques est facile.
  • JUnit 5 peut utiliser plus d'une extension à la fois, ce que JUnit 4 ne peut pas (un seul runner peut être utilisé à la fois). Cela signifie que vous pouvez facilement combiner l'extension Spring avec d'autres extensions (comme votre propre extension personnalisée).

Comment migrer vers JUnit 5

Passer de JUnit 4 à JUnit 5 est assez simple, même si vous avez des tests JUnit 4 existants. La plupart des organisations n'ont pas besoin de convertir d'anciens JUnits en JUnit 5, sauf si de nouvelles fonctionnalités sont nécessaires.

  1. Mettez à jour vos bibliothèques et créez des systèmes de JUnit 4 vers JUnit 5. Assurez-vous d'inclure l'artefact JUnit-vintage-engine dans votre chemin d'exécution de test pour permettre à vos tests existants de s'exécuter.
  2. Commencez à créer de nouveaux tests à l'aide des nouvelles constructions JUnit 5.
  3. (Facultatif) Convertissez les tests JUnit 3 et JUnit 4 en JUnit 5.

Différences importantes entre JUnit 5 et JUnit 4

Les tests JUnit 5 ressemblent à peu près à JUnit 4, mais il y a quelques différences dont vous devez être conscient.

Importations

JUnit 5 utilise le nouveau org.JUnit.jupiter package pour ses annotations et ses classes. Par exemple, org.JUnit.Test devient org.JUnit.jupiter.api.Test.

Annotations

La @Tester l'annotation n'a plus de paramètres; chacun de ceux-ci a été déplacé vers une fonction. Par exemple, pour indiquer qu'un test est censé lever une exception dans JUnit 4:

Dans JUnit 5, cela a changé en:

De même, les délais d'expiration ont changé. Dans JUnit 4, ils ressemblaient à ceci:

Dans JUnit 5, les délais d'attente ressemblent à ceci:

Voici d'autres annotations qui ont changé:

  • @Avant que est devenu @AvantChaque
  • @Après est devenu @Après chaque
  • @Avant les cours est devenu @Avant tout
  • @Après les cours est devenu @Après tout
  • @Ignorer est devenu @Désactivée
  • @Catégorie est devenu @Étiqueter
  • @Régner et @ClassRule sont partis - utilisez @ExtendWith et @RegisterExtension plutôt ;

Affirmations

Les assertions de JUnit 5 sont maintenant disponibles org.JUnit.jupiter.api.Assertions. La plupart des affirmations courantes, comme assertEquals () et assertNotNull () ont le même aspect qu'avant, mais il y a quelques différences clés:

  • Le message d'erreur est maintenant le dernier argument, par exemple: assertEquals ("mon message", 1, 2) serait assertEquals (1, 2, "mon message")
  • La plupart des assertions acceptent désormais un lambda qui construit le message d'erreur, qui n'est appelé que lorsque l'assertion échoue.
  • assertTimeout () et assertTimeoutPreemptively () ont remplacé le @Temps libre annotation (notez qu'il existe une annotation @Timeout dans JUnit 5, mais cela fonctionne différemment de JUnit 4).
  • Il existe plusieurs nouvelles affirmations, décrites ci-dessous.

Notez que vous pouvez continuer à utiliser les assertions de JUnit 4 dans un test JUnit 5 si vous préférez.

Hypothèses

Les hypothèses ont été déplacées vers org.JUnit.jupiter.api.Hypothèses.

Les mêmes hypothèses existent, mais prennent désormais en charge BooléenFournisseur ainsi que les matchers Hamcrest pour correspondre aux conditions. Les lambdas peuvent être utilisés (de type exécutable) pour que le code s'exécute lorsque la condition est remplie.

Voici un exemple dans JUnit 4:

Dans JUnit 5, cela devient ceci:

Extension de JUnit

Dans JUnit 4, personnaliser le framework signifiait généralement utiliser un @Courir avec annotation pour spécifier un runner personnalisé. L'utilisation de plusieurs coureurs était problématique et nécessitait généralement un chaînage ou l'utilisation d'un @Régner. Cela a été simplifié et amélioré dans JUnit 5 à l'aide d'extensions.

Par exemple, la création de tests avec le framework Spring ressemblait à ceci dans JUnit 4:

Avec JUnit 5, vous incluez l'extension Spring à la place:

La @ExtendWith l'annotation est répétable, ce qui signifie que plusieurs extensions peuvent être combinées facilement.
Vous peut également définir facilement nos propres extensions personnalisées en créant une classe qui implémente une ou plusieurs interfaces à partir de org.JUnit.jupiter.api.extension, puis en l'ajoutant à notre test avec @ExtendWith.

 

Conversion de tests en JUnit 5

Pour convertir un test JUnit 3 ou JUnit 4 existant en JUnit 5, les étapes suivantes devraient fonctionner pour la plupart des tests:

  1. Mettez à jour les importations pour supprimer JUnit 4 et ajouter JUnit 5. Par exemple, mettez à jour le nom du package pour le @Tester annotation, ainsi que le nom du package et de la classe pour les assertions (de Assertions à Affirmations). Ne vous inquiétez pas encore s'il y a des erreurs de compilation, les étapes suivantes devraient les résoudre.
  2. Remplacez globalement les anciennes annotations et noms de classes par de nouveaux. Par exemple, remplacez tout @Avant que avec @AvantChaque, et tout Assertions avec Affirmations.
  3. Mettre à jour les assertions. Toutes les assertions qui fournissent un message doivent avoir l'argument du message déplacé à la fin. Faites particulièrement attention lorsque les trois arguments sont des chaînes! En outre, mettez à jour les délais d'expiration et les exceptions attendues (voir ci-dessus pour des exemples).
  4. Mettez à jour les hypothèses si vous les utilisez.
  5. Remplacez toutes les instances de @Courir avec, @Régnerou @ClassRule avec le bon @ExtendWith annotations. Vous devrez peut-être trouver une documentation mise à jour en ligne pour les extensions que vous utilisez pour des exemples.

Notez que la migration des tests paramétrés nécessitera un peu plus de refactorisation, surtout si vous avez utilisé JUnit 4 Paramétré (le format des tests paramétrés JUnit 5 est beaucoup plus proche de JUnitParams).

Nouvelles fonctionnalités

Jusqu'à présent, je n'ai discuté que des fonctionnalités existantes et de la façon dont elles ont changé. Mais JUnit 5 offre de nombreuses nouvelles fonctionnalités pour rendre nos tests plus descriptifs et maintenables.

Afficher les noms

Avec JUnit 5, vous pouvez ajouter le @Afficher un nom annotation aux classes et méthodes. Le nom est utilisé lors de la génération de rapports, ce qui facilite la description de l'objectif des tests ainsi que le suivi des échecs, par exemple:

Vous pouvez également utiliser un générateur de nom d'affichage pour traiter votre classe et / ou méthode de test afin de générer des noms de test dans le format de votre choix. Voir la documentation JUnit pour des détails et des exemples.

Affirmations

JUnit 5 a introduit de nouvelles assertions, telles que:

  • assertIterableEquals () effectue une vérification approfondie de deux itérables, en utilisant equals ()
  • assertLinesMatch () vérifie que deux listes de chaînes correspondent; il accepte les expressions régulières dans l'argument «attendu».
  • assertAll () regroupe plusieurs assertions ensemble. L'avantage supplémentaire est que toutes les assertions sont effectuées, même si les assertions individuelles échouent.
  • assertThrows () et assertDoesNotThrow () ont remplacé le attendu propriété dans le @Tester annotation

Tests imbriqués

Les suites de tests dans JUnit 4 étaient utiles, mais les tests imbriqués dans JUnit 5 sont plus faciles à configurer et à maintenir, et ils décrivent mieux les relations entre les groupes de test, par exemple:

Dans l'examplement ci-dessus, vous pouvez voir que I utiliser une seule classe pour tous les tests liés à Myclass. I peut vérifier que la classe est instanciable dans la classe de test externe, et I utiliser une classe interne imbriquée pour tous les tests où Myclass est instancié et initialisé. Le @AvantChaque La méthode s'applique uniquement aux tests de la classe imbriquée.

La @DisplayNames les annotations pour les tests et les classes indiquent à la fois le but et l'organisation des tests. Cela aide à comprendre le rapport de test car you can voir les conditions dans lesquelles le test est effectué (Vérifier MyClass avec initialisation) et ce que le test vérifie (maMéthode renvoie vrai). C'est un bon modèle de conception de test pour JUnit 5.

Tests paramétrés

Le paramétrage des tests existait dans JUnit 4 avec des bibliothèques intégrées telles que JUnit4Paramétré ou des bibliothèques tierces comme JUnitParams. Dans JUnit 5, les tests paramétrés sont complètement intégrés et adoptent certaines des meilleures fonctionnalités de JUnit4Paramétré et JUnitParams, Par exemple:

Le format ressemble à JUnitParams, où les paramètres sont transmis directement à la méthode de test. Notez que les valeurs à tester peuvent provenir de plusieurs sources différentes. Ici, j'ai juste un seul paramètrer donc il est facile d'utiliser un @ValeurSource. @SourceVide et @NullSource pour indiquer que I souhaitez ajouter une chaîne vide et une valeur nulle à la liste des valeurs à exécuter avec, respectivement (et vous peut les combiner, comme ci-dessus, si vous utilisez les deux). Il existe plusieurs autres sources de valeur, telles que @EnumSource et @ArgumentsSource (un fournisseur de valeur personnalisée). Si vous avez besoin de plus d'un paramètre, vous pouvez également utiliser @SourceMéthode or @CsvSource. Consultez la documentation de JUnit 5 pour plus de détails et d'exemples.

Un autre type de test ajouté dans JUnit 5 est @Test répété, où un seul test est répété un nombre spécifié de fois.

Exécution de test conditionnel

JUnit 5 fournit le ExécutionCondition extension API pour activer ou désactiver un test ou un conteneur (classe de test) de manière conditionnelle. C'est comme utiliser @Désactivée sur un test mais il peut définir des conditions personnalisées. Il existe plusieurs conditions intégrées, telles que:

  • @EnabledOnOs et @DisabledOnOs: Active un test uniquement sur les systèmes d'exploitation spécifiés.
  • @EnabledOnJre et @DisabledOnJre: Indique que le test doit être activé ou désactivé pour des versions spécifiques de Java.
  • @EnabledIfSystemProperty: Active un test basé sur la valeur d'une propriété système JVM.
  • @ActivéSi: Utilise la logique scriptée pour activer un test si les conditions scriptées sont remplies.

Modèles de test

Les modèles de test ne sont pas des tests réguliers. Ils définissent un ensemble d'étapes à effectuer, qui peuvent ensuite être exécutées ailleurs en utilisant un contexte d'appel spécifique. Cela signifie que vous pouvez définir un modèle de test une fois, puis créer une liste de contextes d'appel au moment de l'exécution pour exécuter ce test avec. Trouvez plus de détails et d'exemples dans la documentation de Junit 5.

Tests dynamiques

Les tests dynamiques sont comme des modèles de test: les tests à exécuter sont générés au moment de l'exécution. Cependant, alors que les modèles de test sont définis avec un ensemble spécifique d'étapes et s'exécutent plusieurs fois, les tests dynamiques utilisent le même contexte d'appel mais peuvent exécuter une logique différente. Une utilisation des tests dynamiques serait de diffuser une liste d'objets abstraits et d'effectuer un ensemble distinct d'assertions pour chacun en fonction de leurs types concrets. Pour de bons exemples, consultez la documentation de Junit 5.

Conclusion

JUnit 5 est une mise à jour puissante et flexible du framework JUnit. Il fournit une variété d'améliorations et de nouvelles fonctionnalités pour organiser et décrire les cas de test, ainsi que pour aider à comprendre les résultats des tests. La mise à jour vers JUnit 5 est simple et rapide: il vous suffit de mettre à jour les dépendances de votre projet et de commencer à utiliser les nouvelles fonctionnalités.

Vous voulez voir comment simplifier la création de cas de test JUnit et de stubs/mocks associés avec l'assistant de test unitaire de Jtest ?