学生エンジニア団体VolareさんとDeNAの合同イベント「ソフトウェアテスト手法を学ぼう」の発表資料です。 https://volare.connpass.com/event/236403/
モバイルアプリテスト入門Nozomi Takuma2022-03-02ソフトウェアテストについて学ぼう
View Slide
自己紹介● Nozomi Takuma● DeNA SWETグループ○ 兼務: Pococha事業部システム部● Androidとテストが好き
今日の発表のゴール
今日の発表のゴール● モバイルアプリのテスト経験が少ない方に、テストを設計する上で考えるべきポイントを知ってもらう● モバイルアプリのテストにおける難しさと工夫について知ってもらう● モバイルアプリのテストをやるべきタイミングが来たときに参考になれば嬉しい
アジェンダ● モバイルアプリのテストの基本方針○ テストのスコープ○ テスト戦略● モバイルアプリのテストのハードルを下げるため工夫
説明に使うサンプルアプリ
ライブ配信アプリを例に考えてみる● アプリ起動時に表示されるホーム画面● 現在ライブ配信中のユーザーがリストで表示されている○ 下にスクロールしてページング○ リスト内のアイテムを押すとそのユーザーの配信に移動できる○ プリセットのフィルターが用意されており、▼から切り替えができる● 画面下部のタブから主要機能の画面に移動● タブの右上のボタンから自身の配信を開始
アプリの内部構成
例:ホーム画面を起動する
モバイルアプリのテストの基本方針
モバイルアプリのテストって何をするの?端末にアプリを入れて、それぞれの機能が問題ないか操作して確認すればいいかな?
スコープの種類● Unit● Integration● End-to-end
スコープの種類Unit test Unit test Unit testIntegration testEnd-to-end test(E2E test)● Unit● Integration● End-to-endUnit test
スコープの種類Unit test Unit test Unit testクラス・メソッド・UIパーツ単位等小さいスコープで正しく動作するかを検証するUnit test
スコープの種類Integration test複数のユニットを結合した状態で正しく動作するかを検証をする
スコープの種類End-to-end test(E2E test)アプリ全体を統合した状態で検証するアプリのフローやAPI含むアプリ外との連携が正しく動作するか等、広いスコープで検証する
スコープの種類Unit test Unit test Unit testIntegration testEnd-to-end test(E2E test)Unit test厳密に線を引く必要はなく、スコープに種類があることがわかれば👌
テストしてみよう● アプリ起動時に表示されるホーム画面● 現在ライブ配信中のユーザーがリストで表示されている○ 下にスクロールしてページング○ リスト内のアイテムを押すとそのユーザーの配信に移動できる○ プリセットのフィルターが用意されており、▼から切り替えができる● 画面下部のタブから主要機能の画面に移動● タブの右上のボタンから自身の配信を開始
テストしてみよう● アプリ起動時に表示されるホーム画面● 現在ライブ配信中のユーザーがリストで表示されている○ 下にスクロールしてページング○ リスト内のアイテムを押すとそのユーザーの配信に移動できる○ プリセットのフィルターが用意されており、▼から切り替えができる● 画面下部のタブから主要機能の画面に移動● タブの右上のボタンから自身の配信を開始初期表示が6件スクロールすると追加で表示される
● ユーザーを8件以上作成する○ 初期表示6ユーザー○ ページングで追加される1ユーザー○ ホーム画面を表示するユーザー● 7ユーザー以上で配信を開始する○ ※全員がフィルターに含まれるようにする必要あり● 配信を行っていないユーザーでホーム画面を起動する● 6ユーザー表示されることを確認して、下にスクロール検証手順
● ユーザーを8件以上作成する○ 初期表示6ユーザー○ ページングで追加される1ユーザー○ ホーム画面を表示するユーザー● 7ユーザー以上で配信を開始する○ ※全員がフィルターに含まれるようにする必要あり● 配信を行っていないユーザーでホーム画面を起動する● 6ユーザー表示されることを確認して、下にスクロール検証手順ちょっと大変そう....
モバイルアプリのテスト戦略● テストのスコープによって次のパラメーターが変化する○ 実行時間○ 忠実度(実環境・実アプリにどこまで近いか)○ 信頼性・安定性● 基本的にはトレードオフになっているので、バランスを取りながら手段を選択する
Unit testだったらどんなテストができそう?● ページングのロジックの確認○ 現在保持しているリストの次のページを取得する○ 新たに取得したアイテムを保持しているリストに追加する○ ページング終了の判定● ページングを開始してから読み込み中→読み込み完了までの状態の変化の確認
Unit testだったらどんなテストができそう?● ページングのロジックの確認○ 現在保持しているリストの次のページを取得する○ 新たに取得したアイテムを保持しているリストに追加する○ ページング終了の判定● ページングを開始してから読み込み中→読み込み完了までの状態の変化の確認API通信している箇所をテストダブルに置き換えて、テストデータを返すようにする実際にユーザーを作成したり、別端末で配信を開始しなくてもよくなる
テストダブル● テストしたい対象が依存しているコンポーネントを本物そっくりに振る舞う代役(ダブル)と差し替えることで、自分の期待する挙動や値の返却をできるようにする● SWET blog:「テスタビリティの高いGoのAPIサーバを開発しよう」というハンズオンを公開しました○ https://swet.dena.com/entry/2021/12/07/123000
Unit testの場合のトレードオフ実行時間● 速い○ UIの操作やAPI通信が含まれないため高速に実行できる忠実度● 低い○ 画面やAPIとの連携は含まれない信頼性● 高い○ 独立性が高く実行ごとに変化する要素が少ないため壊れにくい
Integration testだったらどんなテストができそう?● Unit testで確認した範囲にプラスしてリストの操作の確認● 7件と言わず大量にデータを用意してスクロールしつづけるといったことも簡単にできそうテストデータを返すようにAPI通信部分を置き換える
Integration testの場合のトレードオフ実行時間● やや遅い○ アプリと画面の起動、UIの操作が含まれるためやや遅い忠実度● そこそこ高い○ UI操作とページング処理が確認できる信頼性● 中くらい○ API通信がない分独立性が高いが、端末の状態や同じ画面内の別の処理の影響を受ける可能性はある
End-to-end testだったらどんなテストができそう?● Integration testで確認した範囲にプラスして、APIとの疎通確認○ API通信の仕組みの実装○ リクエスト・レスポンスの誤り○ API自体が動いているか● ライブ配信しているユーザーがホームに表示されているか確認
End-to-end testの場合のトレードオフ実行時間● 遅い○ アプリと画面の起動 + UIの操作 + API通信○ 検証したい項目に辿りつくまでの準備の時間忠実度● 高い○ ユーザーがアプリを触るのとほぼ同じ状態で検証できる信頼性● 低い○ 端末の状態と同じ画面内の別の処理以外にも、通信状態やAPIサーバーの状態の影響をうける
表にするとこうなった実行速度 忠実度 信頼性Unit 速い 低い 高いIntegration やや遅い そこそこ高い 中くらいEnd-to-end 遅い 高い 低い
トレードオフ以外に考慮するべきこと● 確認したいことがテストできているか?● テストの難易度○ テストを実装する難しさ○ 検証したいパスに到達するための難しさ● テスト実行以外の時間
確認したいことがテストできているか?● 何を検証したいかによって、結合する範囲や手段は変わってくる○ 例えば、実ユーザーが触るときの使用感はEnd-to-endと手動の組み合わせでないと確認ができない○ 最小単位でテストすることにこだわりすぎた結果、スタブが正しい値を返すことのテストになってしまっている、みたいな場合もある● テストの目的を忘れないことはとても大事で、それにあわせてスコープを決定する
テストを実装する難しさ● テスト実装の難易度が選択する手段に影響する場合がある○ テストしたい内容によっては自動テストだと難しく、手動での検証を選択したほうがよい場合がある○ Unit testは実装が簡単と考えられるが、テスタビリティが低い設計の場合は、大きいスコープのテストよりも難易度が上がる○ テストに必要なデータの準備コストは、スコープの大きさと比例して難しくなるとは限らない
テスタビリティ● テスタビリティが高い設計は、戦略通りのテストスコープの実現やスコープの変更に対応できるようになっている● SWET blog:「テスタビリティの高いGoのAPIサーバを開発しよう」というハンズオンを公開しました(2回目の宣伝)○ https://swet.dena.com/entry/2021/12/07/123000
検証したいパスに到達するための難しさ● 単体でみると数ケース見ればよくても、結合する範囲が広がると通り得るパスの数が膨れ上がっていき、網羅するのが難しくなる● 結合範囲が広がると、特定のケースに到達するにはどうしたらいいかを把握することが難しくなる● テストのスコープによっては、検証したいパスに到達するのが難しい場合がある○ 例えばAPIから返却されうるエラーパターンの確認
検証したいパスに到達するための難しさ関数A関数B関数C関数D処理の分岐関数E関数F関数G関数H関数H
検証したいパスに到達するための難しさ関数A関数B関数C関数D処理の分岐関数E関数F関数G関数H関数Hユニットテストの場合関数のパターンをみればいいパターンを網羅してテストケースが増えても実行時間が短いためスケールしやすい
検証したいパスに到達するための難しさ関数A関数B関数C関数D処理の分岐関数E関数F関数G関数H関数Hスコープを広げると通りえるパターンが膨れ上がる実行時間も長いため、確認できるケースが限られてくる
検証したいパスに到達するための難しさ関数A関数B関数C関数D処理の分岐関数E関数F関数G関数H関数Hここを検証したい
検証したいパスに到達するための難しさ関数A関数B関数C関数D処理の分岐関数E関数F関数G関数H関数Hユニットテストの場合関数Eに着目すればよい
検証したいパスに到達するための難しさ関数A関数B関数C関数D処理の分岐関数E関数F関数G関数H関数Hスコープを広げるとここの分岐も考慮する必要がある
テスト実行以外の時間● スコープの小さいテストは時間の面で優位○ 完全に実装が終わっていなくても一部を切り出してテストでき、動作確認がはじめられるまでの時間が短い○ プロジェクトを分割することでテストしたい対象のみビルドをするといったことが可能になり、ビルド時間の短縮も見込める● 時間が短いことは、テスト活動を継続していく上でとても大事○ Developer Experience(開発体験)に直結する
モバイルアプリのテスト戦略● スコープの異なるテストをバランスよく選択する○ スコープが大きいテストだけだと実行速度や信頼性が課題になり、スケールしない・メンテナンスが難しいといった問題に直面する○ スコープが小さいテストだけだとUI/操作性/結合時といった問題を取りこぼしてしまう● スコープ以外にも、確認したいことがテストできているか・テストの難易度・実行までの時間といったポイントを考慮する
モバイルアプリのテストのハードルを下げるための様々な工夫
モバイルアプリのテストをやっていて難しいと感じること● UIが絡むことで発生する問題が多い○ 特定のUIパターンの表示・特定のUI操作をトリガーに発生するもの○ テストのスコープを広げないと見つかりづらい● アプリをビルドするのに時間がかかる○ UIの動作確認したいのに、それをするにはアプリをビルドしないといけなくて時間がかかるというジレンマ
● UIが絡むことで発生する問題が多い○ 特定のUIパターンの表示・特定のUI操作をトリガーに発生するもの○ テストのスコープを広げないと見つかりづらい● アプリをビルドするのに時間がかかる○ UIの動作確認したいのに、それをするにはアプリをビルドしないといけなくて時間がかかるというジレンマモバイルアプリのテストをやっていて難しいと感じることこのハードルを乗り越えるために様々なチームで様々な工夫が行われているどんな工夫している事例があるのかを紹介していきます(Android多め)
ミニアプリ化● アプリを機能ごとに分割して起動できるようにする● アプリ全体をビルドするよりもビルド時間が短縮され、動作確認にかかるコストと機能に行き着くまでのコストを下げる● クックパッド開発者ブログ: 大規模なiOSアプリの画面開発を効率化するために動作確認用ミニアプリを構築する○ https://techlife.cookpad.com/entry/2020/08/05/090000
Jetpack composeやSwift UIのプレビュー機能● モバイルアプリにおいて新たに登場した宣言的UIフレームワークは、既存のViewシステムにはない高度なプレビュー機能が実装されている● UIのバリエーションを目視で確認する時間の削減が見込める● DroidKaigi 2021: Let's Preview! Jetpack Compose○ https://speakerdeck.com/mochico/title-lets-preview-jetpack-compose
UIカタログ● UIコンポーネントを一覧化し、各コンポーネントの表示パターンを確認できるようにする● UIのバリエーションを目視で確認する時間の削減が見込める● CyberAgent Developers Blog: Android向けUI Catalog Library –Katalogを公開しました○ https://developers.cyberagent.co.jp/blog/archives/33059/
Visual regression test● コードの変更前と変更後のアプリUIをキャプチャした画像を比較して差分を検知する● reg-suitといったツールを使うことで、目視では気が付きづらいような差分も検知できる● プレビュー機能やUIカタログとの親和性が高い● CATS PRODUCTIVITY BLOG: Android のアプリ開発でも VisualRegression Testing を始めましょう○ https://cats-234205.web.app/2020/visual-regression-testing-with-android/
UI操作の自動化● The Airbnb Tech Blog: Better Android Testing at Airbnb— Part 3: Interaction Testing○ 画面上のパーツを走査的にクリックしていき、その際の内部の振る舞い(API通信・画面遷移等)をjsonに記録し、差分を比較する○ UI操作時に意図せぬ変更がされていないかを確認する■ https://medium.com/airbnb-engineering/better-android-testing-at-airbnb-1d1e91e489b4
End-to-end test自動化のハードルを下げる● ノーコードでのテスト実装をサポートする機能を提供することで、より多くの人がEnd-to-end test実装に関われるようになる○ Magic pod○ Autify for Mobile■ Mot Lab: デリバリーアプリ「GO Dine」でのテスト自動化の取り組み● https://lab.mo-t.com/blog/godine-qa
モバイルアプリのテストの今後● モバイルアプリのテストはまだまだ伸びしろがある○ もっと使いやすくできる○ もっと多くの人に使ってもらえる○ もっと多くのことができるようになる● DeNAのSWETチームでは、そういったことを模索している
まとめ
まとめ● モバイルアプリのテストはトレードオフになっているパラメータのバランスを取りながら戦略を立てる必要がある● UIが絡む動作確認は難易度が高く、ハードルを下げるために様々な工夫がされている● モバイルアプリのテストはまだまだ伸びしろがあるので、発展に貢献していきたい
ご清聴ありがとうございました!