UI テストを自動化する

ユーザー操作をテストすると、ユーザーが予期しない結果に遭遇することやアプリの操作性が低下することを回避できます。アプリの UI が正しく機能していることを確認する必要がある場合は、ユーザー インターフェース(UI)テストを作成する習慣を身につけるようにしてください。

UI テストのアプローチの一つとして、ターゲット アプリに対して一連のユーザー オペレーションを人間のテスターに実行させ、正しく動作するか検証する方法があります。しかし、この手動のアプローチは時間がかかり、エラーも発生しがちです。より効率的なアプローチは、ユーザーの操作が自動で行われるように UI テストを作成することです。自動化されたアプローチにより、再現可能な方法で迅速かつ確実にテストを実行できます。

UI テストでは、アプリ(またはその一部)を起動し、ユーザー操作をシミュレートして、最後にアプリが適切に反応することを確認します。テストは統合テストであり、小さなコンポーネントの動作を検証するものから、ユーザーフロー全体を横断する大規模なナビゲーション テストまで、多岐にわたります。回帰をチェックしたり、さまざまな API レベルや物理デバイスとの互換性を確認したりする際に便利です。

Android Studio でのインストルメンテーション UI テスト

Android Studio を使用してインストルメンテーション UI テストを実行するには、別の Android テストフォルダ(src/androidTest/java)にテストコードを実装します。Android Plug-in for Gradle は、テストコードに基づいてテストアプリをビルドし、ターゲット アプリと同じデバイスにテストアプリを読み込みます。テストコードでは、UI テスト フレームワークを使用して、ターゲット アプリでのユーザー操作をシミュレートして、特定の使用シナリオに対応するテストタスクを実行できます。

Jetpack フレームワーク

Jetpack には、UI テストを作成するための API を提供するさまざまなフレームワークが含まれています。

  • Espresso テスト フレームワーク(Android 4.0.1、API レベル 14 以降)には、1 つのターゲット アプリ内のビューに対するユーザー操作をシミュレートする UI テストを作成するための API が用意されています。Espresso を使用する大きなメリットは、テスト対象アプリの UI とテスト アクションを自動的に同期できることです。Espresso はメインスレッドがアイドル状態になったことを検出するため、適切なタイミングでテストコマンドを実行できるため、テストの信頼性が向上します。
  • Jetpack Compose(Android 5.0、API レベル 21 以降)には、Compose の画面とコンポーネントを起動して操作するためのテスト API が用意されています。Compose 要素とのやり取りはテストと同期され、時間、アニメーション、再コンポーズを完全に制御できます。
  • UI Automator(Android 4.3、API レベル 18 以降)は、システムとインストール済みのアプリにまたがるアプリ間の UI 機能テストに適した UI テスト フレームワークです。UI Automator API を使用すると、テストデバイスで設定メニューやアプリ ランチャーを開くなどの操作を行うことができます。
  • Robolectric(Android 4.1、API レベル 16 以降)を使用すると、エミュレータやデバイスではなく、通常の JVM のワークステーションまたは継続的インテグレーション環境で実行するローカル テストを作成できます。Espresso または Compose のテスト API を使用して、UI コンポーネントとやり取りできます。

不安定性と同期

モバイルアプリとフレームワークは非同期という性質を備えているため、信頼性が高く再現性のあるテストを作成するのが困難なことがよくあります。ユーザー イベントが注入されると、テスト フレームワークは、アプリがそのイベントへの反応を完了するまで待機しなければなりません。これには、画面上のテキストの変更からアクティビティの完全な再作成まで、多岐にわたります。決定論的な動作がないテストは、「不安定」です。

Compose や Espresso などの最新のフレームワークはテストを念頭に置いて設計されているため、次のテスト アクションやアサーションの前に UI がアイドル状態であることが保証されます。これが同期です。

同期のテスト

データベースからのデータの読み込みや、無限アニメーションの表示など、テストでは不明な処理を非同期やバックグラウンドで行うと、問題が発生することがあります。

テストに合格する前にアプリがアイドル状態かどうかを確認するループを示すフロー図
図 1: 同期のテスト

テストスイートの信頼性を高めるために、Espresso アイドリング リソースなど、バックグラウンド オペレーションを追跡する方法をインストールできます。また、コルーチンの TestDispatcher や RxJava の RxIdler など、アイドル状態をクエリできる、または同期を改善するバージョンのテスト用モジュールを置き換えることもできます。

同期が固定時間の待機に基づいている場合のテスト失敗を示す図
図 2: テストでスリープを使用すると、テストの速度が低下したり不安定になったりします。

アーキテクチャとテスト設定

アプリのアーキテクチャでは、テストで一部を置き換えて double をテストできるようにする必要があります。テストに役立つユーティリティを提供するライブラリを使用する必要があります。たとえば、データ リポジトリ モジュールをインメモリ バージョンに置き換えることで、テストに架空の確定的なデータを提供できます。

本番環境とテストのアーキテクチャ図。本番環境の図は、ローカルとリモートのデータソースからリポジトリにデータを提供し、リポジトリが UI と非同期にデータを供給する様子を示しています。テストの図は、データを UI に同期して提供する架空のリポジトリを示しています。
図 3: 依存関係をフェイクに置き換えて UI をテストする。

この機能を有効にするには、依存関係インジェクションを使用することをおすすめします。独自のシステムを手動で作成することもできますが、Hilt などの DI フレームワークを使用することをおすすめします。

自動テストのメリット

Android アプリは、さまざまな API レベルとフォーム ファクタを持つ何千台ものデバイスをターゲットにできますが、OS がユーザーに提供する高度なカスタマイズは、アプリが正しくレンダリングされない可能性や、デバイスによってはクラッシュする可能性があることを意味します。

UI テストでは互換性テストを行い、さまざまなコンテキストでのアプリの動作を検証できます。以下のような異なるデバイスで UI テストを行うことをおすすめします。

  • API レベル: 21、25、30
  • 言語 / 地域: 英語、アラビア語、中国語。
  • 向き: 縦向き、横向き。

さらに、アプリはスマートフォン以外の動作もチェックする必要があります。タブレット、折りたたみ式デバイス、その他のデバイスでテストする必要があります。

参考情報

UI テストの作成について詳しくは、次のリソースをご覧ください。

ドキュメント

Codelabs