見出し画像

iOSの自動テストをBitriseで並列実行する - Bitriseでのワークフロー複数実行 -

はじめに

自動テストの実行時間がある程度かかっているケースはしばしばあるかと思います。

その場合、よくやる対応方法の1つが並列実行です。

iOSにおける並列実行においては、次のような観点があります。
- 実行環境を分けて実行したい(例えば、iOS14とiOS13で実行とか英語と日本語環境で実行など)
- テストケースを分割して並列実行したい

前述の実行環境においては、英語と日本語環境を分けたい場合は「Test Plans」を利用する方法などがあります。
また、OSを変えたいといった実行環境においては、実行時に利用するシミュレーターを変えるなどもあります。

後者のテストケースを分割して実行する場合、CircleCIでは次のような方法をサポートしています。

iOSでよく利用されているBitriseにおいては自ら設定をして、ワークフローを並列で実行するという方法になります。

ワークフローの並列実行自体はある程度前から提供されていますが、今年7月から各ワークフローの成果物を収集できるようになりました。
(これが入るまでは同様のことをする場合、APIを駆使する必要がありました。

本記事では、その方法についてかんたんに説明をしていきます。

あくまで並列実行の方法についてであり、テストケースをどのように分割するかについては細かく言及しません(別記事で言及できればと思いますし、そのうちBitriseがいい感じの解決策を提供してくれることを期待しています)。

なお、執筆時点(2020/12/15)の場合の対応方法です。
今後のBitriseの機能提供により違ったやり方ができるようになるかもしれません。


Bitriseでの自動テストの並列実行

ここではBitriseでどのように並列実行するかについて説明をしていきます。

1)実行するテストを分割したワークフローを用意する

テストを並列実行するために、1つのワークフロー内ですべてのテストを実行するのではなくて、テストを分割してそれぞれを実行するワークフローを用意します。

テストケースの分割の仕方の例

テストケースを分割して並列実行する場合、どのように分割するかというのがあります。
本記事では並列実行の仕方がメインなので、分割の方法については軽く説明します。

xcodebuildのonly-testingオプションを利用することで指定したテストを実行することができます。

たとえば、テストを実行するfastlaneのscanではonly_testingパラメータを利用することで、実行を制御することはできます。

また、Test Plansで実行するテストを決めることもできるので、そちらを利用する方法もあります。

他に、Visual Regression Testとユニットテストを別々のTargetにしている場合で、それらをそれぞれのワークフローで用意して並列実行するという方法もあります。

---

2)複数ワークフローを実行するワークフローを用意する

用意したワークフローを実行するワークフローを用意します。
これにはBitriseにある次の「Bitrise Start Build」stepを利用します。

スクリーンショット 2020-12-15 13.30.47

このstepの「Workflows」の設定で実行したいワークフローを入力します。

スクリーンショット 2020-12-15 13.33.46

たとえば、上記のように設定した場合は「test_1」「test_2」「test_3」の3つのワークフローが実行します。

Bitriseの並列実行数に余裕があれば、設定したワークフローは並列で実行されます(当然ですが並列実行数に余裕がなければ、実行されず待機状態になるのでその点は注意です)。

このstepによりワークフローを並列実行することができます。

この設定で全ては終了でしょうか。
これによりワークフローは並列で動きますが、場合によっては課題があります。

それは並列実行したテスト結果です。

---

テスト結果をまとめる

上述したようにワークフローを並列実行した場合、テストの結果のまとめをどうするかというのがあります。

分割したそれぞれのワークフローが実行されたとして、なにかしらのテストが失敗した場合にどのように知るかということがあります。
また、テストケース数としてどの程度実行されたかをmergeして知りたいというのもあるかと思います。

そこで、それぞれのワークフローの結果を集約してテスト結果をまとめる方法について説明をしていきます。

本機能は今年7月に追加され、今回紹介している「Bitrise Start Build」では0.13.0から利用できるようになっています(なお、同様のことをできるstepとして「Bitrise Wait for Build」というstepもあります)。

本機能を利用するには、さきほどの「Bitrise Start Build」のstepで設定をおこないます。

1)ワークフローの終了を待機する

stepの設定の「Wait for builds」をtrueにすると指定したワークフローの実行がおわるまで待機します。

これによりまず、他のワークフローが終わるのを待ちます。
これで他のワークフローの実行結果を利用することが出来ます。

2)成果物を利用する

次に「Path to save the Artifacts in」の箇所で成果物の場所を設定します。

スクリーンショット 2020-12-15 13.32.44

この成果物に各ワークフローのテストの結果(たとえばResult Bundleなど)を保存しておくことで、大元のワークフローで成果物を利用することができます。

また成果物は上書きされるため、それぞれのワークフローでユニークな名前で保存しておく必要があります。

テストの成果物としては、テストの実行に「Xcode Test for iOS」stepを利用している場合であれば、次の設定をそれぞれのワークフローでユニークになるように指定してテスト結果として保存しておくのも1つの手です。

スクリーンショット 2020-12-15 17.26.54

また、テストの結果がはいっているResultBundleのパスは次のような環境変数($BITRISE_XCRESULT_PATH)に値が入っているので、ResultBundleをrenameして保存しておくのも1つの手です。

スクリーンショット 2020-12-15 17.28.31

そして、これらの各ワークフローのテスト結果を大元のワークフローで取得し、テスト結果をマージします。

その結果をどのように活用するかは用途次第ですが、私はテストケース数(成功数、失敗数)をマージしてSlack通知させたりしています。

次の記事に書いたようにSlack通知させたり、GitHub Commit Statusに保存したりしています。

---

注意点

この設定をおこなう注意点としては、この大元のワークフローもある程度の実行時間動き続けることになります。

結果として、並列数を1つ使うことになります。

したがって、それぞれのワークフローのテスト結果を利用する必要がない場合は、「Wait for builds」をfalseにしたほうがいいです。

---

必ずテストの実行時間は早くなるのか?

これでテストの実行時間は必ず早くなるのでしょうか?
そうとも限りません。

テストを実行するためにビルドが必要になります。
下図の(1)をビルド時間とし、(2)をテストの実行時間とします。
3並列化した場合の結果はAfterにあるとおりです。

スクリーンショット 2020-12-15 16.33.59

この図では(2)のテストの実行時間がある程度長かったため、トータルとして多少早くなっています。

しかし、もし(1)のビルド時間が支配的なのであれば、並列化してもあまり合計の実行時間の短縮は見込めません。

おわりと蛇足

Bitriseでのテストの並列実行について軽く書きました。

蛇足ですが、テストの実行環境をBitrise以外にすることで並列実行するという方法もあります。

たとえば、Device Farmを利用することでそういったことが可能となります。

上記のような外部の実行環境を利用するといったアプローチもありますし、また実行するテストを常に絞るという方法もあります。

色々な手段を使って自動テストを有効活用していきたいですね。


この記事が気に入ったらサポートをしてみませんか?