it-swarm.com.de

Parallele Ausführung von Junit-Tests in einem Maven-Build?

Ich benutze JUnit 4.4 und Maven und habe eine große Anzahl von langjährigen Integrationstests.

Wenn es um die Parallelisierung von Testsuiten geht, gibt es einige Lösungen, mit denen ich jede Testmethode in einer einzelnen Testklasse parallel ausführen kann. Aber all dies erfordert, dass ich die Tests auf die eine oder andere Weise ändere.

Ich denke wirklich, dass es eine viel sauberere Lösung wäre, X verschiedene Testklassen in X-Threads parallel auszuführen. Ich habe Hunderte von Tests, daher ist es mir eigentlich egal, ob ich einzelne Testklassen einfädle.

Gibt es eine Möglichkeit, dies zu tun?

110
krosenvold

Ab Version 4.7 ist es jetzt möglich, Tests ohne TestNG parallel auszuführen. Eigentlich ist es seit 4.6 möglich, aber es gibt eine Reihe von Korrekturen in 4.7, die es zu einer praktikablen Option machen. Sie können auch parallele Tests mit spring durchführen. Lesen Sie dazu hier

40
krosenvold

Benutze das maven Plugin:

<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>
70
Oleksandr

Inspiriert von JUnits experimentellem ParallelComputer Läufer, den ich selbst gebaut habe ParallelSuite und ParallelParameterized Läufer. Mit diesen Läufern können Testsuiten und parametrisierte Tests einfach parallelisiert werden.

ParallelSuite.Java

public class ParallelSuite extends Suite {

    public ParallelSuite(Class<?> klass, RunnerBuilder builder) throws InitializationError {

        super(klass, builder);

        setScheduler(new RunnerScheduler() {

            private final ExecutorService service = Executors.newFixedThreadPool(4);

            public void schedule(Runnable childStatement) {
                service.submit(childStatement);
            }

            public void finished() {
                try {
                    service.shutdown();
                    service.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
                } catch (InterruptedException e) {
                    e.printStackTrace(System.err);
                }
            }
        });
    }
}

ParallelParameterized.Java

public class ParallelParameterized extends Parameterized {

    public ParallelParameterized(Class<?> arg0) throws Throwable {

        super(arg0);

        setScheduler(new RunnerScheduler() {

            private final ExecutorService service = Executors.newFixedThreadPool(8);

            public void schedule(Runnable childStatement) {
                service.submit(childStatement);
            }

            public void finished() {
                try {
                    service.shutdown();
                    service.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
                } catch (InterruptedException e) {
                    e.printStackTrace(System.err);
                }
            }
        });
    }
}

Die Bedienung ist einfach. Ändern Sie einfach den Wert @ RunWith Annotations in eine dieser parallelen * Klassen.

@RunWith(ParallelSuite.class)
@SuiteClasses({ATest.class, BTest.class, CTest.class})
public class ABCSuite {}
10
Mustafa Ulu

tempus-fugit bietet etwas Ähnliches an. Weitere Informationen finden Sie in der Dokumentation. Es basiert auf JUnit 4.7 und Sie markieren Ihren Test einfach mit @RunWith(ConcurrentTestRunner).

Prost

5
Toby

Sie können die Open Source-Bibliothek auschecken - Test Load Balancer . Es macht genau das, wonach Sie fragen - führen Sie verschiedene Testklassen parallel durch. Dies wird auf der Ant-Junit-Ebene integriert, sodass Sie Ihre Tests ohnehin nicht ändern müssen. Ich bin einer der Autoren der Bibliothek.

Denken Sie auch daran, sie nicht in Threads auszuführen, da Sie möglicherweise eine Sandbox auf Prozessebene benötigen. Wenn Sie beispielsweise in Ihren Integrationstests auf eine Datenbank treffen, soll ein Test nicht fehlschlagen, da ein anderer Test einige Daten in einem anderen Thread hinzugefügt hat. In den meisten Fällen werden Tests nicht in diesem Sinne geschrieben.

Schließlich, wie haben Sie dieses Problem bis jetzt gelöst?

3
Pavan

TestNG kann das (das war mein erster Reflex - dann habe ich gesehen, dass du schon viele Testfälle hast).

Schauen Sie sich für JUnit parallel-junit an.

3
philant

Sie können die Tests mit dem von Junit bereitgestellten ParallelComputer parallel ausführen. Hier ist ein kleiner Ausschnitt, um Ihnen den Einstieg zu erleichtern.

Class[] cls = { TestCase1.class, TestCase2.class };
Result result = JUnitCore.runClasses(ParallelComputer.classes(), cls);
List<Failure> failures = result.getFailures();

Dies ist hilfreich, wenn Sie Tests über Code ausführen müssen, da dieser weder von Maven noch von anderen Build-Management-Tools abhängig ist.

Beachten Sie, dass dies alle Testfälle parallel ausführt, wenn Sie Abhängigkeiten zwischen verschiedenen Testfällen haben, kann dies zu falsch positiven Ergebnissen führen. Sie sollten sowieso keine voneinander abhängigen Tests haben.

2
Ashwin Sadeep