web-dev-qa-db-fra.com

Exécution de tests en parallèle avec Junit

Je voudrais exécuter chaque méthode annotée avec @Test, à travers plusieurs classes, en même temps. Dans certains cas, j'aimerais limiter cela et dire que seulement 100 au total peuvent être exécutés à la fois. Je souhaite que les méthodes avec des annotations @BeforeClass soient exécutées une fois avant l'exécution de tout test dans une classe, et j'aimerais que les annotations @AfterClass soient exécutées une fois après tous les tests d'une classe. J'aimerais que System.out, System.err et les exceptions soient correctement tamponnés/capturés plutôt qu'écrits, afin qu'ils ne s'entrelacent pas, et que je puisse lire le résultat final et comprendre ce qui s'est passé.

Est-ce que ça existe? J'ai un grand nombre de cas de test indépendants et mon application est (je crois) threadsafe. Aucun de ces tests ne comporte de dépendances hors de la machine virtuelle, et je souhaite les terminer le plus rapidement possible, en fonction de mon matériel.

Si cela n'existe pas, existe-t-il une raison concrète? Combien de temps les utilisateurs junit du monde perdent-ils parce que ce n’est pas facile? Puis-je le construire dans Junit? Dans mon esprit, cela devrait être aussi simple qu'un drapeau unique, et cela "fonctionne".

8
Cory Kendall

Vous pouvez accomplir cela avec la variable ParallelComputer de JUnit (notez qu'elle est toujours considérée comme expérimentale). C'est une implémentation assez simple, soutenue par l'API Java.util.concurrent.ExecutorService.
Si vous êtes curieux de savoir comment cela fonctionne, consultez la source .

En gros, vous appelez JUnitCore.runClasses(Computer, Classes ...) et transmettez un objet ParallelComputer pour le premier argument.

Exemple d'utilisation:

import org.junit.Test;
import org.junit.experimental.ParallelComputer;
import org.junit.runner.JUnitCore;

public class ParallelComputerExample {

    @Test
    public void runAllTests() {
        Class<?>[] classes = { ParallelTest1.class, ParallelTest2.class };

        // ParallelComputer(true,true) will run all classes and methods 
        // in parallel.  (First arg for classes, second arg for methods)
        JUnitCore.runClasses(new ParallelComputer(true, true), classes);
    }

    public static class ParallelTest1 {
        @Test
        public void test1a() {
            lookBusy(3000);
        }

        @Test
        public void test1b() {
            lookBusy(3000);
        }
    }

    public static class ParallelTest2 {
        @Test
        public void test2a() {
            lookBusy(3000);
        }

        @Test
        public void test2b() {
            lookBusy(3000);
        }
    }

    public static void lookBusy(long ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
            System.out.println("interrupted");
        }
    }
}

Le code ci-dessus s'exécutera dans 3 secondes car toutes les méthodes et les classes sont exécutées en parallèle.

Cela fonctionnera en 6 (parce que toutes les classes sont en parallèle) .JUnitCore.runClasses(new ParallelComputer(true, false), classes);

Cela fonctionnera également en 6 (parce que toutes les méthodes sont en parallèle) .JUnitCore.runClasses(new ParallelComputer(false, true), classes);

14
Andy Guibert

Oui, vous pouvez.

Si vous utilisez Maven. Vous pouvez prendre l'aide de 

maven-surefire-plugin

Au printemps,

Vous pouvez vérifier ceci Lien

<build>
    <plugins>
    <plugin>
        <groupId>org.Apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.7.1</version>
        <configuration>
            <parallel>classes</parallel>
            <threadCount>5</threadCount>
        </configuration>
    </plugin>
    </plugins>
</build>

Solution 2: Junit4 fournit une fonctionnalité parallèle à l'aide de ParallelComputer

3
VdeX

JUnit Toolbox fournit des coureurs JUnit pour l'exécution en parallèle de tests.

Afin de ne pas mélanger la sortie à System.err et System.out, vous devez démarrer les tests dans des machines virtuelles distinctes, car System.err et System.out sont globaux.

2
Stefan Birkner