1.はじめに

テストを連続的に実行することは、ほとんどの場合、問題なく動作します。

時にはスピードを上げる必要があるかもしれません。このような状況では、並列テストが役に立ちます。

  • JUnit 4.7以降のバージョンでは、MavenのSurefire Plugin ** を使用してテストを並行して実行できます。一言で言えば、Surefireはテストを並行して実行する2つの方法を提供します。

  • 最初のアプローチは単一のJVMプロセス内でマルチスレッドを使用する

  • 2番目のアプローチは複数のJVMプロセスを使用しますが

このチュートリアルでは、単一のJVMプロセス内でJUnitテストを並行して実行するようにSurefireを設定する方法について説明します。次に、Mavenマルチモジュールプロジェクト内でテストを並行して実行する方法について説明します。

2. Mavenの依存関係

必要な依存関係をインポートすることから始めましょう。


JUnit 4.7以降

を一緒に使用する必要があります。

Surefire 2.16以降:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.22.0</version>
</plugin>

3.並列テストを実行する

  • テストを並行して実行するには、

    org.junit.runners.ParentRunner

    を拡張するテストランナーを使用する必要があります。

ただし、デフォルトランナーがこのクラスを拡張するため、明示的なテストランナーの動作を宣言していないテストでさえもです。

次に、並列テスト実行を実証するために、それぞれがいくつかのメソッドを持つ2つのテストクラスを持つテストスイートを使用します。実際、JUnitテストスイートの標準実装であれば問題ありません。

3.1. 並列パラメータの使用

まず、Surefireで

__parallel

__パラメータを使用して並列動作を有効にしましょう。これは、並列処理を適用したい粒度のレベルを示しています。

可能な値は次のとおりです。


  • __methods –

    __runsテストメソッドを別々のスレッドで実行する


  • classes –

    はテストクラスを別々のスレッドで実行します。


  • classesAndMethods –

    は、クラスとメソッドを別々のスレッドで実行します。


  • __suites – r

    __unsスイートを並行して

  • ____suitesAndClasses – スイートとクラスを別々のスレッドで実行する

  • ____suitesAndMethods – クラスとクラス用に別々のスレッドを作成する

方法
**

all –

はスイート、クラス、メソッドを別々のスレッドで実行します。

この例では、

all

を使用します。

<configuration>
    <parallel>all</parallel>
</configuration>

次に、Surefireに作成させたいスレッドの総数を定義しましょう。それには2つの方法があります。

Surefireが作成するスレッドの最大数を定義する

threadCount

を使用する:

<threadCount>10</threadCount>

あるいは、CPUコアごとに1つのスレッドが作成される

useUnlimitedThreads

パラメーターを使用します。

<useUnlimitedThreads>true</useUnlimitedThreads>

デフォルトでは、

threadCount

はCPUコアごとです。この動作を有効または無効にするには、

perCoreThreadCount

パラメータを使用します。

<perCoreThreadCount>true</perCoreThreadCount>

3.2. スレッド数制限の使用

それでは、メソッド、クラス、スイートの各レベルで作成するスレッドの数を定義したいとしましょう。 ** これは

threadCountMethods



threadCountClasses

、および

threadCountSuites

パラメータを使用して実行できます。

これらのパラメータを前の設定の

threadCount

と組み合わせてみましょう:

<threadCountSuites>2</threadCountSuites>
<threadCountClasses>2</threadCountClasses>
<threadCountMethods>6</threadCountMethods>


all

を____parallelで使用したので、クラス、メソッド、スイートのスレッド数を定義しました。ただし、リーフパラメータを定義することは必須ではありません。 Surefireは、リーフパラメータが省略された場合に使用するスレッド数を推測します。

たとえば、

threadCountMethods

が省略されている場合は、

threadCount

>

__threadCountClasses



threadCountSuites.__を確認する必要があります。

無制限のスレッド数を使用している場合でも、クラス、スイート、またはメソッド用に作成されるスレッド数を制限したい場合があります。

そのような場合にもスレッド数の制限を適用できます。

<useUnlimitedThreads>true</useUnlimitedThreads>
<threadCountClasses>2</threadCountClasses>

3.3. タイムアウトを設定する

テストの実行に時間制限があることを確認する必要があるかもしれません。

  • これを行うには、

    __parallelTestTimeoutForcedInSeconds

    __parameterを使用できます。** これは、現在実行中のスレッドを中断し、タイムアウトが経過した後にキューに入れられたスレッドを実行することはありません。

<parallelTestTimeoutForcedInSeconds>5</parallelTestTimeoutForcedInSeconds>

  • 別のオプションは

    parallelTestTimeoutInSeconds

    を使用することです。

この場合、キューに入れられたスレッドだけが実行を停止します。

<parallelTestTimeoutInSeconds>3.5</parallelTestTimeoutInSeconds>

それにもかかわらず、どちらのオプションでも、タイムアウトが経過するとテストはエラーメッセージで終了します。

3.4. 注意事項

Surefireは、親スレッドで

@ Parameters



@ BeforeClass

、および

@ AfterClass

というアノテーションが付けられた静的メソッドを呼び出します。したがって、テストを並行して実行する前に、潜在的なメモリの矛盾や競合状態を必ず確認してください。

また、共有状態を変化させるテストは、並行して実行するのに適していません。

4.マルチモジュールMavenプロジェクトでのテスト実行

今までは、Mavenモジュール内で並行してテストを実行することに焦点を当ててきました。

しかし、Mavenプロジェクトに複数のモジュールがあるとしましょう。これらのモジュールは順次構築されるため、各モジュールのテストも順次実行されます。

  • モジュールを並行して構築するMavenの-Tパラメータを使用して、このデフォルトの動作を変更できます。これには2つの方法があります。

プロジェクトの構築中に使用するスレッドの正確な数を指定することができます。

mvn -T 4 surefire:test

または、ポータブル版を使用して、CPUコアごとに作成するスレッド数を指定します。

mvn -T 1C surefire:test

どちらの方法でも、テスト時間を短縮し、実行時間を短縮することができます。

5.まとめ

まとめると、マルチスレッド動作を有効にし、

parallel

パラメーターを使用して並列度を定義することから始めました。

その後、Surefireが作成するスレッド数に制限を加えました。後で、テスト実行時間を制御するためにタイムアウトパラメータを設定します。

最後に、マルチモジュールのMavenプロジェクトで、ビルドの実行時間を短縮し、それによってテストの実行時間をテストする方法を調べました。

いつものように、ここに提示されたコードはhttps://github.com/eugenp/tutorials/tree/master/testing-modules/parallel-tests-junit[GitHubで利用可能]です。