dimanche 25 mars 2012

[JUnit] Personnalisez vos tests avec @Rule

Les règles JUnit proposent un mécanisme d'extension du framework. Cette fonctionnalité permet de personnaliser le déroulement des tests :
  • vérifications supplémentaires des résultats,
  • préparation avant et nettoyage après,
  • rapports complémentaires.
Pour ce faire, il suffit d'ajouter un membre publique du type org.junit.rules.TestRule à la classe de test, et de l'annoter avec @org.junit.Rule :
public class MyTestCase {
    @Rule public TestRule myRule;
    ...
}


Règles proposées par JUnit

Pour le développeur, il est donc possible soit d'écrire ses propres règles à partir de l'interface TestRule, soit plus simplement de recourir aux règles proposées nativement par JUnit. Voici ce que propose le package org.junit.rules :
  • ExpectedException : cette règle permet de spécifier, à l'intérieur d'un test, le type et le message de l'exception attendue. Elle permet aussi de généraliser l'utilisation de @Test(expected=...) à une classe de test.
  • ExternalResource : classe de base pour toute règle qui doit préparer une ressource externe avant un test (fichier, socket, serveur, connexion à une base de données, etc), et garantir sa libération par la suite.
    • TemporaryFolder (dérivée de ExternalResource): cette règle permet d'inclure au test la création de fichiers et de répertoires temporaires, qui devront être supprimés à la fin de la méthode de test, que le test passe ou échoue.
  • RuleChain : cette règle permet de construire et d'ordonner une liste de règles.
  • TestWatcher : classe de base pour toute règle qui doit observer l'exécution d'un test sans en modifier les résultats.
    • TestName (dérivée de TestWatcher) : cette règle donne accès au nom du test à l'intérieur de la méthode de test.
  • Timeout : cette règle permet de spécifier le même délai d'exécution pour toutes les méthodes de test de la classe de test. Elle permet aussi de généraliser l'utilisation de @Test(timeout=...) à une classe de test.
  • Verifier : classe de base pour toute règle qui doit vérifier l'état d'un objet de test. Ce type de règle est susceptible de modifier le résultat du test.
    • ErrorCollector : cette règle permet de recueillir les échecs quand ils surviennent, sans interrompre le test. Le cas échéant, les échecs feront l'objet d'un rapport tout à la fin du test. Ça peut être utile lorsque les assertions d'un test sont indépendantes.

Règles personnalisées

Les classes de base ExternalResource, TestWatcher, et Verifier ont été ajoutées afin de faciliter et guider le développement de règles personnalisées :
  • ExternalResource propose d'implémenter des méthodes before() pour préparer des ressources et after() pour les libérer.
  • TestWatcher propose d'implémenter des méthodes :
    • starting() et finished() pour journaliser des informations avant et après le déroulement du test, quelle que soit son issue,
    • succeeded() et failed() pour journaliser des informations si le test réussit ou échoue respectivement.
  • Verifier propose d'implémenter une méthode verify() pour ajouter des vérifications au test.
Et pour qui veut écrire une nouvelle règle relative à un nouveau cas d'usage, l'interface TestRule comporte une unique méthode : Statement apply(Statement base, Description description);
base représente ici la méthode de test, et plus généralement encapsule une étape dans une suite de test : base.evaluate() pour l'exécuter,
description décrit le contenu du test et doit éventuellement servir à construire un message de log,
et où la valeur de retour du type Statement encapsule le traitement spécifique de la règle.

Remarque :
  • Avec les règles, il est possible de faire ce qu'il était déjà faisable dans les méthodes annotées par @Before[Class] et @After[Class], mais de manière plus efficace, et plus facile à partager entre projets : les TestRunners de JUnit reconnaissent intrinsèquement les TestRules, ce qui en fait un mécanisme d'extension naturel et privilégié de JUnit.
  • L'interface org.junit.rules.TestRule remplace l'interface org.junit.rules.MethodRule apparue avec JUnit 4.7 et rendue obsolète depuis la version 4.9 : la méthode apply a été simplifiée.

Code Source

Des exemples d'utilisation des règles JUnit sont proposés sur mon dépôt GitHub UnitTesting4Java, dans le module junit4-features (package xapn.testing.junit.rule).

Aucun commentaire: