noriharu3 です。
E2Eテストの実行時間短縮を目指して、複数サーバーでテストを並列実行してみましたのでご紹介します。
複数のサーバーでE2Eテストを実行する方法
元々E2Eテストは以下の構成で実装されていました。
Gradleを使用していたので並列実行するだけなら、パラメーターを設定するのみ。
なのですが、今回はE2Eテストを1つのサーバーで並列実行するのではなく、複数サーバーでE2Eテストを並列実行できないか
模索しました。
理由としては、E2Eのテストケース毎にDBのロールバックが必要となっていたため、 1つのサーバーで並列実行することがそもそもできなかったからです。
E2Eテストを並列実行させる
Gradleを使っている場合は、パラメーターを設定するだけです。 終わりですw。
// build.gradle test { useJUnitPlatform() ++ maxParallelForks = 2 }
E2Eテストを複数のサーバーで並列実行させる
テスト実行前の事前処理で実行するサーバーを決定し、テスト毎に実行するサーバーを切り替えます。
具体的には、テスト未実施のサーバーリスト一覧をテキストファイルに保持しておき、そこからテストを実行するサーバーを決定します。
- 処理の流れ
// e2e_server_list e2e_server_1 e2e_server_2
// E2EテストプログラムのAbstract Class ... (途中省略) @BeforeAll protected void リモートホスト割り振り() { Map<String, String> result; try { result = execCommand("sh", "server_pop_push.sh", "pop"); } catch (IOException e) { throw new RuntimeException(e); } catch (InterruptedException e) { throw new RuntimeException(e); } setServerName(result.get("stdout")); } ... (途中省略) @AfterAll public void リモートホスト返却() { try { execCommand("sh", "server_pop_push.sh", "push", getServerName()); } catch (IOException e) { throw new RuntimeException(e); } catch (InterruptedException e) { throw new RuntimeException(e); } } } ... (途中省略)
// server_pop_push.sh SERVER_LIST_FILE="e2e_server_list" LOCK_FILE="/tmp/e2e.lock" # 0/1/2以外の任意のファイルディスクリプタ(番号)を指定 exec 200>"${LOCK_FILE}" flock 200 ### メイン処理開始 if [ $1 = "pop" ]; then cat $SERVER_LIST_FILE | tail -n 1 sed -ie '$d' $SERVER_LIST_FILE elif [ $2 != '' ]; then echo $2 >> $SERVER_LIST_FILE else echo '引数が不正です。' fi
結果
結果として、2台のサーバーで並列実行したところ、テスト時間は約半分(40%)となりました。
Before
1台のサーバーで順番にテストを実行していました。
After
指定したサーバ台数で分散して、E2Eテストを実行できるようになりました。。
各サーバに均等に処理が振り分けるわけではなく、テスト未実施のサーバーに振り分けられます。
2台のサーバーで並列実行したところ、テスト時間は約半分(40%)となりました。
最後に
E2Eテストを
- 分散
- 並列実行
したブログは多くあるかと思いますが、これらは1つのサーバーに対して複数のブラウザを立てて処理を実行するもの
がほとんどでした。
DBのロールバックが必要など、何らかの理由で単純にE2Eテストを並列処理できず困っている方に、何らかのヒントを提供することができたら幸いです。