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

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

1. Vue d'ensemble

Dans ce didacticiel, nous allons montrerhow to run JUnit tests directly from Java code - il existe des scénarios où cette option est utile.

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

2. Dépendances 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 deJUnit 4,JUnit 5 etJUnit 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 cela n'entre pas dans le cadre de ce didacticiel.

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

Pour exécuter des tests JUnit à partir de code Java, nous pouvons utiliser la classeJUnitCore (avec un ajout de la classeTextListener, utilisée pour afficher la sortie enSystem.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 la réussite des tests:

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

3.3. Exécution de plusieurs classes de test

Si nous voulonsto specify multiple test classes 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 classeResult 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 avons besoin de regrouper certaines classes de test afin de les exécuter, nous pouvons créer unTestSuite. Ceci est juste une classe vide où nous spécifions toutes les classes utilisant des 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 pouvonsrepeat tests by creating instances of 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 à partir deMergeListsTest 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 utilisonsJUnit4TestAdapter comme wrapper pour notre classe de test.

Nous pouvons même créer des suites par programme, 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 etSecondUnitTest, avec quelques différences mineures dues à une version différente du framework JUnit, comme le package pour@Test et méthodes d'assertion.

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

Pour exécuter des tests JUnit 5 à partir de code Java, nous allons configurer une instance deLauncherDiscoveryRequest. 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 souhaitons 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.

Ces deux éléments 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 à la demande pour 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.example.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éthodemain(), 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 deTestExecutionSummary.

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 à la fois pour lesJUnit 5 examples, ainsi que pour lesJUnit 4.