こんにちは、Android エンジニアの @myamamic です。スタディサプリ小中講座の Android アプリ開発を担当しています。
この記事では私たちが実施している E2E テストについて、実施の目的や自動化によって受けている恩恵、E2E テストをどのように運用しているかを紹介します。
- はじめに: E2E テストの目的
- E2E テストケースの観点
- E2E テストの自動化
- MagicPod について
- E2E テストの運用: ケースの作成や修正
- E2E テストの運用: MagicPod 一括実行のスケジューリング
- まとめ: E2E テスト自動化によって得られた恩恵
- 終わりに
はじめに: E2E テストの目的
私たちのチームでは、以下の目的で E2E テストを実施しています。
- エンドユーザーの行動に基づくテストケースを実行して、「アプリ上で学習できる」というコア機能の提供を担保する
最悪の状態(クラッシュやフリーズでユーザーが何もできない状態など)を回避する、セーフティネットの役割を果たすことを目的としています。
なお、詳細なロジックやデータ整合性の確認は backend 側のユニットテストで担保しているため、Android アプリの E2E テストでは確認対象外としています。
E2E テストケースの観点
次に、E2E テストケースをどのような観点で作成しているかを紹介します。 すべての機能や挙動を網羅することは現実的ではないため、以下の観点で優先度をつけてテストケースを作成しています。
- スモークテスト
- 必須。シナリオテストのメインパスを主に対象とする。
- フルシナリオテスト
- 優先度は高め。シナリオテスト全般を網羅的に対象とする。
- フル機能テスト
- 余裕があれば作成。スモークテストとフルシナリオテストでテストしていない機能のうち、優先度の高いところから対象とする。
なお、スモークテスト / フルシナリオテスト / フル機能テストの観点分けは厳密な定義を決めているわけではなく、新しい機能を実装したときに Android エンジニア + QA エンジニアで議論して決めています。
下記はスタディサプリ小中講座 Android アプリで作成しているテストケースの例です。
観点 | 例 |
---|---|
スモークテスト | 新規会員登録できる,ログインできる,レッスンを開始/完了できる,学習履歴を表示できる, etc |
フルシナリオテスト | 連続学習できる, etc |
フル機能テスト | 学校を変更できる,テキストをダウンロードできる,deeplink 経由で画面遷移できる, etc |
例にあげたように、スモークテストには「この機能が動いていないと価値をまったく提供できていない」ようなケースを入れています。
E2E テストの自動化
品質担保のためにかかせない E2E テストですが、以下のように実施に時間とコストがかかることが課題でした。
- ユーザーが操作する一連の流れを通して実行するためテストケースごとに時間がかかる
- 処理が OS バージョンによって分岐している場合、それぞれ確認したい
- 例: 通知やストレージの Runtime permission 周りなど
- スマホ/タブレットなど端末ごとに確認したい
これらのテストを QA エンジニアや開発者が手動で実施するとそこそこの時間がかかってしまいます。
この課題を改善するため、MagicPod による E2E テストの自動化と並列化を行っています(ただし、Google Play Billing に関するテストなど一部のケースは自動化が難しいため引き続き手動で実施)。
MagicPod について
QA エンジニアの @testtatto がいくつかのサービスを比較し、スタディサプリ小中講座ではノーコード E2E テスト自動化サービスの MagicPod を採用することになりました。
このあたりの経緯についてはこちらの記事に詳しく書かれています。
メンバー全員が MagicPod を使ったことがないという状態から導入していきました。最初から全員で同時に使い始めるよりも、先に誰かがある程度使い方を把握したのちに周囲に広めていく方法がスムーズかもしれません。
実際スタディサプリ小中講座では、使い方をマスターした QA エンジニアが各プラットフォーム(iOS, Android, web)の開発者にレクチャーしながらモブプロでテストケースを作成していくという方法で進めていきました。このやり方はノウハウを共有しやすく良かったです。
なお、MagicPod にはユーザー同士で知見を共有することができる Slack コミュニティが用意されていたり、現在開発中や今後開発予定の機能を可視化したポータルサイトが提供されていたりと、情報の入手しやすさは抜群です。
E2E テストの運用: ケースの作成や修正
つづいて、MagicPod による E2E テストの運用について紹介します。スタディサプリ小中講座のチームでは基本的に開発者が MagicPod のテストケースを作成し、QA エンジニアがレビューする体制としています。詳細はこちら
開発者がテストケースのオーナーシップを持つことのメリットはいくつか挙げられますが、テストの追加や修正といった対応を素早く回せることにとくにメリットを感じています。
テストケースの作成では QA エンジニアのフォローをもらいつつ、観点に沿ってケースを考えていきます。QA エンジニアとの議論を通して、チームのテストスキル向上にもつながっています。
また、MagicPod ではコードの変更とテストケースの修正を完全に同期させることが難しく、テストケースが新しいコードに対応していないことによる失敗がときどき起こります。このような失敗によって本当の不具合を見逃すことを防ぐために、失敗しているケースはなるべく早く修正しテストケースを最新に保つようにしています。毎晩の MagicPod E2E テストで失敗したケースについては、翌日の daily meeting で失敗した原因を確認し、さらなる調査や修正が必要な場合はその場でアサインを決めて対応しています。
これらの運用は多くの場合、開発者で完結することができています。*1
E2E テストの運用: MagicPod 一括実行のスケジューリング
MagicPod 自体にも一括実行のスケジュール機能があり曜日ごとに開始時刻を設定できますが、テスト対象にできるアプリはその時点でアップロード済みのバイナリになります。
master ブランチに PR をマージするたびに MagicPod にバイナリをアップロードし、MagicPod 側のスケジュール機能を利用することもできますが以下の課題がありました。
- MagicPod の一括実行開始直前にマージした変更はアップロードが間に合わないので含まれない
- できる限り最新の状態でテストしたい
- マージのたびにアップロードしても、実際に一括実行に使われるバイナリは最後の 1 つだけ
- テストに使われないバイナリのアップロード時間、コストがムダになってしまう
上記を解消するため、MagicPod Web API のクライアントツール magicpod-api-client を利用して、GitHub Actions のワークフローを構築しました。アプリをビルド → MagicPod へバイナリアップロード → MagicPod 一括実行というフローにすることで、最新のバイナリに対してテストを実行することができるようになりました。
また、ワークフローはどのブランチでも実行できるため、マージ前のブランチに対して手動で実行して動作を確認するといった使い方も可能になりました。
まとめ: E2E テスト自動化によって得られた恩恵
不具合の早期発見
E2E テストの運用: ケースの作成や修正 で紹介したように「毎晩テスト -> 翌日確認」の運用をしている中で、PR レビューや動作確認で見逃してしまった不具合を検知できたことが数回ありました。
不具合の検知タイミングは早ければ早いほど対応がしやすいため助かっています。
アプリリリース前のリグレッションテストの時間短縮
スタディサプリ小中講座 Android アプリでは、ストアでのリリース前にリグレッションテストを実施しています(リグレッションテストの内容は E2E テスト + 新規実装部分の探索的テスト)。以前は QA エンジニア 1 名が 約 1 時間かけて E2E テストをすべて手動で行っていましたが、大部分のケースを自動化したことによって手動で確認する作業は 5 分〜10 分で済むようになりました!
自動化したケースの実行は 1 時間以上かかりますがリリースフローの CI で自動的に実行されるため、待ち時間をあまり意識しなくて済んでいます。
終わりに
今回はスタディサプリ小中講座の Android アプリでどのように E2E テストの自動化をしているかを紹介しました。約 2 年ほど MagicPod による E2E テストを行ってきて、知見も貯まってきています。今後 MagicPod でのテストケース作成 tips も紹介できればと考えています!
*1:困った段階で QA エンジニアにヘルプを求めています