CirlcleCI で実行している Protractor テストを並列実行してみた

CirlcleCI で実行している Protractor テストを並列実行してみた

最近 Protractor のテストが CircleCI 側のテスト環境の負荷が高くなっているせいか、たびたびコケるようになってきた。
ローカルの開発環境では通るのに。
テストがコケる場所も実行するときによって違ったり、再度実行すると問題なく通ったり、という状況だ。
また、テストの実行時間も25分前後かかるようになってきた。

そこで、Protractor のテストを3つのコンテナに分割して並列実行するように修正してみた。

CircleCI の料金プラン

CircleCI で複数のコンテナを動かすには、有料プランの契約が必要となる。
CircleCI は、無料プランだと1コンテナのみ、追加の1コンテナごとに$50という料金体系。

CircleCI 側の設定

複数のコンテナでテストを実行するには、CircleCI 側で設定が必要となる。
下記ドキュメントが参考になる。
https://circleci.com/docs/setting-up-parallelism
https://circleci.com/docs/parallel-manual-setup

CircleCI の Project Settings から、変更するコンテナ数をクリックする。
コンテナ数変更画面
上記は、3つコンテナを選択した場合。

circle.yml 修正

そのままテストを実行すると、1つ目のコンテナでしか Protractor のテストが通らないはず。
バックグラウンドで起動する必要があるサーバーが1つ目でしか実行されないためである。
3つのコンテナで実行させるように、circle.yml の修正も必要となってくる。

【修正前】

1
test:
  pre:
    - grunt serve:
      background: true
    - sleep 5

【修正後】

1
test:
  pre:
    - grunt serve:
        background: true
        parallel: true
    - sleep 5:
        parallel: true
  override:
    - bash test.sh:
        parallel: true

parallel: true を各コンテナで実行する必要がある処理に追加する。
また、テストについて並列実行するシェルスクリプトを実行するように、override に記述する。

テスト実行用シェルスクリプト

サンプルスクリプト

こちらに例示していあるサンプルスクリプトをベースに修正する。

【サンプルスクリプト】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash

i=0
files=()
for file in $(find ./test -name "*.py" | sort)
do
if [ $(($i % $CIRCLE_NODE_TOTAL)) -eq $CIRCLE_NODE_INDEX ]
then
files+=" $file"
fi
((i++))
done

test-runner ${files[@]}

環境変数

スクリプト内に入っている環境変数について。

CIRCLE_NODE_TOTAL

ビルドに使用されるコンテナの合計数。

CIRCLE_NODE_INDEX

ビルドが実行されているコンテナの番号。0から始まる。

スクリプト修正

サンプルスクリプトを基に、Protractor 用にスクリプトを修正する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash

i=0
for file in $(find ./test -name "*E2Etest.coffee" | sort)
do
if [ $(($i % $CIRCLE_NODE_TOTAL)) -eq $CIRCLE_NODE_INDEX ]; then
grunt test --specs $file
RETURN_CD=$?
if [ $RETURN_CD -ne 0 ]; then
exit $RETURN_CD
fi
fi
((i++))
done

test ディレクトリ配下の、*E2Etest.coffee をソートして、1つ目のコンテナ、2つ目のコンテナというように、機械的に各コンテナに振り分けて、1つずつ実行していく形にした。
途中、テストが通らなかったら exit で処理を抜けるように修正。
(これを入れないと、テストが通る、通らないにかかわらずすべて正常終了してしまうため)

テスト実行

上記を実装後に、テストを実行すると下記のように複数のコンテナでテストが並列実行される。
複数コンテナで並列実行

今後の対応として

今回はスクリプト内のテスト振り分けの部分を、何も考えずに機械的に振り分けてしまったので、テストの実行処理時間にそれほど大きな差はなかった。
(1つのコンテナに重いテストが集中してしまったため)
テストの振り分けを各コンテナでうまく振り分けることができればテストの実行時間をかなり削減できそうではある。
今後はこのあたりの改善をして行きたい。

CircleCIを活用した継続的インテグレーションによるシステム開発・モバイルアプリケーション開発をご検討の企業様は、是非MMMにご相談下さいませ!

このエントリーをはてなブックマークに追加