DroidKaigi 2023 セッションレポート (自動テスト編)
株式会社TOKIUMの渡邊(@error96num)です!先日、9/14(木)~16(土)の3日間に渡り開催されたDroidKaigi 2023に参加いたしました。今年は「Androidの自動テストに関する知見を蓄えること」を目的として参加し、結果、多くの学びを得ることができました。
本記事では、テストに関する3つのセッションについて、現地で聴講した内容をご紹介します。
- Androidアプリの良いユニットテストを考える
- Maintaining E2E Test Automation as We Transition from View to Compose
- Building a screenshot testing pipeline that scales
はじめに:自動テストの全体像
セッションの内容を解説するための前提知識として、自動テストの全体像について簡単におさらいします。ここでは「テストピラミッド」の概念に基づいて、テストの粒度による違いについて述べておきます。(以下の用語は、セッションのタイトルや内容にも登場します。)
- ユニットテスト:単一のクラスやメソッドに焦点をあてたテストです。一般的に、連携する他の要素はテストダブル[1]によって置き換えます。
- インテグレーションテスト: 2つ以上のクラスの相互作用を検証することに焦点をあてたテストです。
- E2Eテスト:機能単位やコンポーネント単位で、実際にユーザがソフトウェアを使用する環境を想定して一連の動作をテストします。
本記事で紹介するセッションのタイトルと、対象としているテストの関係を図中に示しました。各テストはそれぞれにカバーできる範囲が異なり、並行して運用する必要があるため、今回のような技術カンファレンスでは特定の粒度のテストに特化したセッションが行われることが多いです。それでは、各セッションの内容の紹介に入ります!
Androidアプリの良いユニットテストを考える
要約
株式会社ディー・エヌ・エーのSWETグループから、Nozomi Takumaさんによる発表です。登壇者は、「良いユニットテストとは何か?」を考えることで、自動テストの方針決定を行うためのポイントを解説しました。
- 前提として、ユニットテストが目指すものを定義しました。
- 結合範囲が広いテストが持つ課題(不安定さ、テスト設計/実装/運用のコスト)をクリアする
- リグレッションを発生させることなくソフトウェアの変更が容易な状態を保つ
- Android特有の自動テスト実行環境について整理し、実行速度を最大化するための環境選定の指針を示しました。
- Androidフレームワークに依存しないロジックをその他のコードから切り離して、非UIのローカルテストで実行
- Androidフレームワークに依存したコードは、Robolectricのローカルテストで実行
- Robolectricでは忠実度が不足している箇所は、実機/エミュレータ上のテストで実行
- ユニットテストにおけるテストダブルの使用については、安定性・コストの面でメリットをもたらす一方で、同時にリグレッションの検知漏れや誤検知につながるリスクを孕むことを述べました。そこで、テストダブルに置き換える箇所の判断基準と、各種テストダブルの適切な使い分けについて解説を行いました。
- その他テストの失敗例と、良いユニットテストの特徴を実現するためのTipsについて、コード例を交えながら紹介しました。
感想
本セッションでとくに印象に残ったポイントは、単にテスト設計/実装/運用に関するテクニックの紹介に終始せず、背景にある原則を丁寧に解説いただいことです。粒度が小さく独立性が高い「ユニットテスト」の目的がどこにあり、その独立性を確保するために何が犠牲となっているのかについて冒頭で示すことで、本セッションの向かう方向である「良いユニットテスト」が明確になりました。その前提を持つことによって、セッションの後半で紹介された個別のケースについて理解がしやすくなる構成となっていました。結果、セッションを通じて、ユニットテストのみならず自動テスト全体に対する解像度が一段上がったと感じています。
Maintaining E2E Test Automation as We Transition from View to Compose
要約
株式会社メルカリから、Software Engineerのshinmiyさんとkenkenさんによる発表です。登壇者らは、日本最大のC2Cマーケットプレイスアプリであるメルカリのコードベースを刷新する「GroundUP App プロジェクト」を通じて得た、E2Eテストに関する知見を共有しました。
- GroundUp App プロジェクトではUI実装部分をAndroid ViewからJetpack Composeに置き換えており、その際はEspressoによるE2EテストもJetpack Composeに対応させる必要がありました。そこで、Page Object Model (POM)[2] と呼ばれるデザインパターンを採用し、Espresso APIによるUI操作やアサーションの実装をUIフレームワークに依存しない形にすることで、シームレスなテストコードの移行を実現しました。セッションでは、POMによるAndroid ViewからJetpack Composeへの移行手順を実装例を交えて丁寧に解説しました。
- 加えて、リリース前チェックの位置付けとしてE2Eテストを運用する方法についても言及しました。Firebase Test LabやTestRailといったツールを用いたCIパイプラインの概要を示し、TestRailを介してQAチームと開発チームが協業する流れについても説明しました。
- 最後に、E2EテストにおけるTipsを紹介しました。
- テストコードで時間のかかる処理を待つ場合には、一定時間スレッドをタイムアウトさせることを避ける。代わりに、Compose 1.4 から追加された
waitUntilNodeCount
,waitUntilAtLeastOneExist
などのメソッドを活用する[3] -
onNodeWithTag
とonNodeWithText
を混同しない。コードの自動補完を利用するときはとくに気をつける -
and
,or
のinfix関数を用いて2つ以上のマッチャーを並列する[4] - SubcomposeLayoutsでは、必要に応じてテストタグを活用する。ただし、テストタグはプロダクションコードの可読性が下がるため、むやみに多用しないこと
- テストコードの自動補完に、GitHub Copilotを活用する
- テストコードで時間のかかる処理を待つ場合には、一定時間スレッドをタイムアウトさせることを避ける。代わりに、Compose 1.4 から追加された
感想
2年半に渡って取り組んだプロジェクトから得られた知見ということもあり、40分間の発表に実践的な内容がかなり凝縮されていたと感じます。特に、Jetpack Composeの移行に際してのテスト更新のアプローチは、Jetpack Composeを本格的に取り入れつつある弊社にとっても、ドンピシャで刺さる内容でした。E2Eテストに関するTipsも、今後のテスト実装や最適化に役立つ情報が多く含まれていました。
Building a screenshot testing pipeline that scale
要約
株式会社メルカリから、Android EngineerのLukas Appelhansさんによる発表です。本セッションのテーマであるスクリーンショットテストとは、UIコードの変更による影響をスクリーンショットによって自動的に検出するテストです。登壇者は、Paparazziとreg-suitを組み合わせて差分レポートを自動生成する、スケーラブルなスクリーンショットテストパイプラインを提案しました。
- 始めに、スクリーンショットテストパイプラインの構築手順について、設定ファイルの記述例やCI環境への組み込み方を取り上げて説明しました。
- GradleタスクからPaparazziを起動し、スクリーンショットを撮影
- reg-suitで差分レポートを生成し、クラウド上に保存
- 次に、構築したパイプラインの利用手順について解説しました。
- Paparazziによるテストケースの書き方
- reg-suitによる差分レポートの見方
- 提案した構成によるテストの、メルカリにおける運用実績を踏まえて、運用上の課題 (主に現在のPaparazziによる制約) について共有しました。
- Jetpack Composeで複数のCompositionを必要とするケースで、意図通りに描画されないことがある (例:テキストが視覚的にオーバーフローした場合に、動的にテキストサイズを小さくして再描画したいケース)
- 単一のテストケースに対して、複数のピクセル密度で実行することができない (例:複数のデバイスを想定して、それぞれのスクリーンショットを撮りたいケース)
感想
直観的に、スクリーンショットテストの運用イメージを得られたのが大きな収穫です。弊社のAndroidアプリではまだスクリーンショットテストを導入していませんが、よりプロダクトが成熟したり開発チームの規模が大きくなった際には、本テストの導入によって開発効率の改善が図れると思います。
本セッションの前半では、技術選定フェーズにおいてPaparazziとreg-suitの組み合わせに至った経緯も丁寧に解説され、後半ではその運用上の課題を共有されました。このように実際のアプリ開発における意思決定に関して生の声を聴くことができ、大変勉強になりました。
全体を通して
今回ご紹介したセッションを含め、実際の現場でのノウハウが詰まった内容を発表された登壇者の皆様に深く感謝しています。他の開発者が直面した課題と、それをどのように乗り越えたのか、エッセンスを凝縮して知ることができるのは、カンファレンス参加の醍醐味であると感じます。
「この度得た学びを基に、業務で実践を重ね、そこで得た知見をAndroid開発コミュニティに還元できるようになりたい」そう思わされた3日間でした!
Discussion