JUnit 5並列実行

テストの並列実行設定、クラス単位の既定モード、排他制御、アクセスモード

テストの並列実行

デフォルトでは、すべてのテストメソッドは単一スレッドで順次実行される。JUnit 5では設定によりテストを並列実行できる。

並列実行の有効化

クラスパスのルートにjunit-platform.propertiesを作成し、並列実行を有効にする。

/test/resource/junit-platform.properties

junit.jupiter.execution.parallel.enabled=true

この設定だけではテストメソッドは並列にならない。メソッドを並列実行するには、テストクラスに@Execution(ExecutionMode.CONCURRENT)を設定する。SAME_THREADは親と同じスレッドで実行し、デフォルト値である。

デフォルト実行モードの変更

次のプロパティを設定すると、メソッドのデフォルト実行モードが並列実行になる。

junit.jupiter.execution.parallel.enabled=true
junit.jupiter.execution.parallel.mode.default=concurrent

ただし、Lifecycle.PER_CLASSを指定したテストクラスや、MethodOrderer.Random以外の順序指定テストは、このデフォルト並列モードの例外になる。スレッドセーフで並列実行したい場合は、明示的に@Execution(ExecutionMode.CONCURRENT)を付ける。

最上位クラスのデフォルト変更

junit.jupiter.execution.parallel.mode.classes.default=concurrentは、最上位クラスのデフォルト実行モードだけを変更する。この設定では、異なるテストクラスは別スレッドで実行され、各クラス内のメソッドは順次実行される。

設定別の実行

junit.jupiter.execution.parallel.mode.defaultjunit.jupiter.execution.parallel.mode.classes.defaultの組み合わせにより、4つの動作になる。

  • 両方same_thread: クラスとメソッドを順次実行する。
  • メソッドsame_thread、クラスconcurrent: クラスごとに並列実行し、クラス内メソッドは順次実行する。
  • メソッドconcurrent、クラスsame_thread: クラス内メソッドは並列実行し、クラスは順次実行する。
  • 両方concurrent: クラスとメソッドをすべて並列実行する。

並列実行 並列実行 並列実行 並列実行

並列数の変更

dynamic戦略では、junit.jupiter.execution.parallel.config.dynamic.factorに利用可能プロセッサ数を掛けて、並列実行スレッド数を決定する。

junit.jupiter.execution.parallel.enabled=true
junit.jupiter.execution.parallel.config.strategy=dynamic
junit.jupiter.execution.parallel.mode.default=concurrent
junit.jupiter.execution.parallel.config.dynamic.factor=2

factorには小数も指定できる。JUnitは内部でBigDecimalを使い、計算結果をintへ変換する。

固定値を使う場合はfixedを指定し、junit.jupiter.execution.parallel.config.fixed.parallelismで並列数を指定する。

junit.jupiter.execution.parallel.enabled=true
junit.jupiter.execution.parallel.config.strategy=fixed
junit.jupiter.execution.parallel.mode.default=concurrent
junit.jupiter.execution.parallel.config.fixed.parallelism=6

任意にカスタマイズする場合はParallelExecutionConfigurationStrategyを実装し、junit.jupiter.execution.parallel.config.custom.classで指定する。

排他制御

排他制御は、共有リソースへ複数テストが同時アクセスしても問題が起きないようにする制御である。クラスまたはメソッドに@ResourceLockを付ける。同じロックキーを持つテストは同期される。

アクセスモード

@ResourceLockResourceAccessModeによるアクセスモードをサポートする。

先行している処理 後から発生した処理 後から発生した処理
READ READ 実行可能
READ READ_WRITE 待機
READ_WRITE READ 待機
READ_WRITE READ_WRITE 待機

READだけなら並列実行可能だが、READ_WRITEがある場合は排他制御される。データを読むだけのテストにはREAD、更新するテストにはREAD_WRITEを指定する。