web-dev-qa-db-ja.com

Mavenビルドでjunitテストを並行して実行していますか?

私はJUnit 4.4とMavenを使用しており、長時間実行される統合テストが多数あります。

テストスイートの並列化に関しては、単一のテストクラスで各テストメソッドを並列に実行できるソリューションがいくつかあります。しかし、これらはすべて、何らかの方法でテストを変更する必要があります。

XスレッドでX個の異なるテストクラスを並行して実行する方がはるかにクリーンなソリューションになると思います。私には何百ものテストがあるので、個々のテストクラスをスレッド化することはあまり気にしません。

これを行う方法はありますか?

110
krosenvold

Junit 4.7から、TestNGを使用せずにテストを並行して実行できるようになりました。実際、4.6以降は可能ですが、4.7で実行可能なオプションとなる多くの修正が行われています。 springを使用して並列テストを実行することもできます。これについては、 here を参照してください。

40
krosenvold

Mavenプラグインを使用:

<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

JUnitの実験的なParallelComputerランナーに触発されて、自分で構築したParallelSuiteおよびParallelParameterizedランナー。これらのランナーを使用すると、テストスイートとパラメーター化されたテストを簡単に並列化できます。

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);
                }
            }
        });
    }
}

使い方は簡単です。 @ RunWithアノテーション値をこれらのParallel *クラスのいずれかに変更するだけです。

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

tempus-fugit は同様の機能を提供します。詳細についてはドキュメントを確認してください。 JUnit 4.7に依存しており、テストを@RunWith(ConcurrentTestRunner)にマークするだけです。

乾杯

5
Toby

オープンソースライブラリを確認できます- ロードバランサーのテスト 。まさにあなたが求めていることをします-異なるテストクラスを並行して実行します。これはant-junitレベルで統合されるため、テストを変更する必要はありません。私は図書館の著者の一人です。

また、プロセスレベルのサンドボックスが必要になる可能性があるため、スレッドで実行しないことを検討してください。たとえば、統合テストでDBにヒットしている場合、別のテストが別のスレッドにデータを追加したため、あるテストが失敗することは望ましくありません。ほとんどの場合、テストはこれを念頭に置いて書かれていません。

最後に、これまでこの問題をどのように解決しましたか?

3
Pavan

TestNGはそれを行うことができます (これは私の最初の反射でした-そして、私はあなたがすでに多くのテストケースを持っているのを見ました)。

JUnitについては、 parallel-junit をご覧ください。

3
philant

Junit自体が提供するParallelComputerを使用して、テストを並行して実行できます。開始するための小さなスニペットを次に示します。

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

Mavenや他のビルド管理ツールに依存しないため、コードからテストを実行する必要がある場合に役立ちます。

これにより、すべてのテストケースが並行して実行されることに注意してください。異なるテストケースの間に依存関係がある場合、誤検知が発生する可能性があります。とにかく相互依存テストを行うべきではありません。

2
Ashwin Sadeep