はじめに
push時にCircleCIでテストを行っていますが、テストが終わるのは1秒でも速いほうがよいので以降の処理に依存関係がないテストをbackgroundモードで実行し、非同期っぽいテストにしました。
利用環境
CircleCI Enterprise version 2.0
並列で実行できるテスト
CircleCIでテストをするとき、このような流れでテストを行うことが多いのではないでしょうか。実際にはこれ以外にテスト用コンテナやDBコンテナなどを起動する処理が必要ですが、ここでは省略しています。
よく考えてみるとLintとユニットテストは独立した関係なので、Lintをしながら平行にDBマイグレーションをしたっていいはずです。
Backgroundオプションによる並列化
CircleCIの場合Lintのジョブとユニットテストのジョブを分離させて並列テストを行うことができますが、無料プランだと並列実行はできませんし、mediumインスタンス(標準のサイズ)は2vCPU割り当てられているので、1ジョブの中で並列化させてみたいところ。
もしかしたらversion 2.1ではうまいことできるのかもしれませんが、残念なことに利用しているCircleCIは未だに2.0です。
あいにくCircleCIにはジョブの中で処理を並列化させる機能はありません(たぶん)。しかしbackgroundオプションを利用すると、コマンドの終了を待たずに次のステップに進みます。本当は名前の通り常駐プロセスを起動させる用途に使うオプションですが、処理の並列化にも使うことができます。
Background commands
Lintを実行するためにはcomposer install, bundle installなどパッケージのインストールは完了している必要があります。しかしDBマイグレーションは不要です。一方ユニットテストは、Lintが終わっている必要はありませんが、パッケージインストールに加え、DBマイグレーションも完了している必要があります。つまりこのような順番で実行すれば良いことになります。
config.ymlの修正
では実際にconfig.ymlを修正してみましょう。config.ymlからテストの部分を抜粋しました。
- run:
name: Waiting for DB connection
command: dockerize -wait tcp://cidb:3306 -timeout 120s
- run: mkdir -p ~/reports/coverage
- run: composer cs-check-report > ~/reports/cs-check-results.xml # ←ここをbackground処理にしたい
- run: php artisan migrate --database=cidb --path=database/migrations/foobar --seed
- run: ./vendor/bin/phpunit -c ./phpunit.ci.xml --coverage-html ~/reports/coverage tests/
backgroud処理に変更するにはrunコマンドのアトリビュートにbackgroudをつけてあげます。この例ではこんな感じになります。
- run:
name: Waiting for DB connection
command: dockerize -wait tcp://cidb:3306 -timeout 120s
- run: mkdir -p ~/reports/coverage
- run:
command: composer cs-check-report > ~/reports/cs-check-results.xml
background: true # ←バックグラウンド処理にした
- run: php artisan migrate --database=cidb --path=database/migrations/foobar --seed
- run: ./vendor/bin/phpunit -c ./phpunit.ci.xml --coverage-html ~/reports/coverage tests/
この設定を行うと、composer cs-check-report
が実行されると同時に次のphp artisan migrate
が開始されます。
非常に分かりづらい画像で恐縮ですが、composer cs-check-report
が実行中(水色)のまま、php artisan migrate
が完了(緑色)になっているのがおわかりいただけるかと思います。出力表示部の右上にExit code出力がないことでもわかるかと思います。
注意点
backgroudの本来の使い方とは異なるので注意が必要です。コマンドの完了を待たずに次に進むため、テスト結果に依存する処理がある場合は利用できません。たとえばテスト結果をartifactとしてアップロードする処理などです。また成否に関わらず次のテストに進んでしまうため、どこかのテストで失敗したら、その場で打ち切りたいケースなどには向いていないでしょう。