Exécution de tests JUnit par programme, à partir d'une application Java

1. Vue d'ensemble

Dans ce didacticiel, nous montrerons comment exécuter des tests JUnit directement à partir du code Java - il existe des scénarios dans lesquels cette option est utile.

Si vous êtes nouveau sur JUnit ou si vous souhaitez mettre à niveau vers JUnit 5, vous pouvez consulter certains des nombreux tutoriels que nous avons sur le sujet.

2. Dépendances de Maven

Nous aurons besoin de quelques dépendances de base pour exécuter les tests JUnit 4 et JUnit 5:

  org.junit.jupiter junit-jupiter-engine 5.2.0 test   org.junit.platform junit-platform-launcher 1.2.0   // for JUnit 4  junit junit 4.12 test 

Les dernières versions de JUnit 4, JUnit 5 et JUnit Platform Launcher sont disponibles sur Maven Central.

3. Exécution des tests JUnit 4

3.1. Scénario de test

Pour JUnit 4 et JUnit 5, nous allons mettre en place quelques classes de test «d'espace réservé» qui suffiront à illustrer nos exemples:

public class FirstUnitTest { @Test public void whenThis_thenThat() { assertTrue(true); } @Test public void whenSomething_thenSomething() { assertTrue(true); } @Test public void whenSomethingElse_thenSomethingElse() { assertTrue(true); } }
public class SecondUnitTest { @Test public void whenSomething_thenSomething() { assertTrue(true); } @Test public void whensomethingElse_thenSomethingElse() { assertTrue(true); } }

Lors de l'utilisation de JUnit 4, nous créons des classes de test en ajoutant l' annotation @Test à chaque méthode de test.

Nous pouvons également ajouter d'autres annotations utiles, telles que @Before ou @After , mais ce n'est pas dans le cadre de ce tutoriel.

3.2. Exécution d'une seule classe de test

Pour exécuter des tests JUnit à partir de code Java, nous pouvons utiliser la classe JUnitCore (avec un ajout de la classe TextListener , utilisée pour afficher la sortie dans System.out ):

JUnitCore junit = new JUnitCore(); junit.addListener(new TextListener(System.out)); junit.run(FirstUnitTest.class);

Sur la console, nous verrons un message très simple indiquant des tests réussis:

Running one test class: .. Time: 0.019 OK (2 tests)

3.3. Exécution de plusieurs classes de test

Si nous voulons spécifier plusieurs classes de test avec JUnit 4, nous pouvons utiliser le même code que pour une seule classe, et ajouter simplement les classes supplémentaires:

JUnitCore junit = new JUnitCore(); junit.addListener(new TextListener(System.out)); Result result = junit.run( FirstUnitTest.class, SecondUnitTest.class); resultReport(result);

Notez que le résultat est stocké dans une instance de la classe Result de JUnit , que nous imprimons à l'aide d'une méthode utilitaire simple:

public static void resultReport(Result result) { System.out.println("Finished. Result: Failures: " + result.getFailureCount() + ". Ignored: " + result.getIgnoreCount() + ". Tests run: " + result.getRunCount() + ". Time: " + result.getRunTime() + "ms."); } 

3.4. Exécution d'une suite de tests

Si nous devons regrouper certaines classes de test afin de les exécuter, nous pouvons créer une TestSuite . Ceci est juste une classe vide où nous spécifions toutes les classes à l'aide d'annotations JUnit:

@RunWith(Suite.class) @Suite.SuiteClasses({ FirstUnitTest.class, SecondUnitTest.class }) public class MyTestSuite { }

Pour exécuter ces tests, nous utiliserons à nouveau le même code que précédemment:

JUnitCore junit = new JUnitCore(); junit.addListener(new TextListener(System.out)); Result result = junit.run(MyTestSuite.class); resultReport(result);

3.5. Exécution de tests répétés

L'une des fonctionnalités intéressantes de JUnit est que nous pouvons répéter les tests en créant des instances de RepeatedTest . Cela peut être très utile lorsque nous testons des valeurs aléatoires ou pour des contrôles de performances.

Dans l'exemple suivant, nous exécuterons les tests de MergeListsTest cinq fois:

Test test = new JUnit4TestAdapter(FirstUnitTest.class); RepeatedTest repeatedTest = new RepeatedTest(test, 5); JUnitCore junit = new JUnitCore(); junit.addListener(new TextListener(System.out)); junit.run(repeatedTest);

Ici, nous utilisons JUnit4TestAdapter comme wrapper pour notre classe de test.

Nous pouvons même créer des suites par programmation, en appliquant des tests répétés:

TestSuite mySuite = new ActiveTestSuite(); JUnitCore junit = new JUnitCore(); junit.addListener(new TextListener(System.out)); mySuite.addTest(new RepeatedTest(new JUnit4TestAdapter(FirstUnitTest.class), 5)); mySuite.addTest(new RepeatedTest(new JUnit4TestAdapter(SecondUnitTest.class), 3)); junit.run(mySuite);

4. Exécution des tests JUnit 5

4.1. Scénario de test

Avec JUnit 5, nous utiliserons les mêmes exemples de classes de test que pour la démo précédente - FirstUnitTest et SecondUnitTest , avec quelques différences mineures dues à une version différente du framework JUnit, comme le package pour @Test et les méthodes d'assertion.

4.2. Exécution d'une classe de test unique

Pour exécuter les tests JUnit 5 à partir du code Java, nous allons configurer une instance de LauncherDiscoveryRequest . Il utilise une classe de générateur dans laquelle nous devons définir des sélecteurs de package et des filtres de nom de classe de test, pour obtenir toutes les classes de test que nous voulons exécuter.

Cette requête est ensuite associée à un lanceur et, avant d'exécuter les tests, nous allons également mettre en place un plan de test et un écouteur d'exécution.

Les deux fourniront des informations sur les tests à exécuter et sur les résultats:

public class RunJUnit5TestsFromJava { SummaryGeneratingListener listener = new SummaryGeneratingListener(); public void runOne() { LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request() .selectors(selectClass(FirstUnitTest.class)) .build(); Launcher launcher = LauncherFactory.create(); TestPlan testPlan = launcher.discover(request); launcher.registerTestExecutionListeners(listener); launcher.execute(request); } // main method... }

4.3. Exécution de plusieurs classes de test

Nous pouvons définir des sélecteurs et des filtres sur la demande d'exécuter plusieurs classes de test.

Voyons comment nous pouvons définir des sélecteurs de package et tester des filtres de nom de classe, pour obtenir toutes les classes de test que nous voulons exécuter:

public void runAll() { LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request() .selectors(selectPackage("com.baeldung.junit5.runfromjava")) .filters(includeClassNamePatterns(".*Test")) .build(); Launcher launcher = LauncherFactory.create(); TestPlan testPlan = launcher.discover(request); launcher.registerTestExecutionListeners(listener); launcher.execute(request); } 

4.4. Sortie de test

Dans la méthode main () , nous appelons notre classe, et nous utilisons également l'écouteur pour obtenir les détails du résultat. Cette fois, le résultat est stocké sous forme de TestExecutionSummary .

Le moyen le plus simple d'extraire ses informations consiste simplement à imprimer sur un flux de sortie de la console:

public static void main(String[] args) { RunJUnit5TestsFromJava runner = new RunJUnit5TestsFromJava(); runner.runAll(); TestExecutionSummary summary = runner.listener.getSummary(); summary.printTo(new PrintWriter(System.out)); }

Cela nous donnera les détails de notre test:

Test run finished after 177 ms [ 7 containers found ] [ 0 containers skipped ] [ 7 containers started ] [ 0 containers aborted ] [ 7 containers successful ] [ 0 containers failed ] [ 10 tests found ] [ 0 tests skipped ] [ 10 tests started ] [ 0 tests aborted ] [ 10 tests successful ] [ 0 tests failed ]

5. Conclusion

Dans cet article, nous avons montré comment exécuter des tests JUnit par programmation à partir de code Java, couvrant JUnit 4 ainsi que la version récente JUnit 5 de ce framework de test.

Comme toujours, l'implémentation des exemples présentés ici est disponible sur GitHub pour les exemples JUnit 5, ainsi que JUnit 4.