アプリのテスト

Android Studio は、簡単にテストを実施できるように設計されています。ローカル JVM で実行する JUnit テストや、デバイスで実行するインストゥルメント化テストを、わずか数回のクリックで設定できます。ローカル単体テストで Android API の呼び出しをテストする Mockito、インストゥルメント化テストでユーザー インタラクションを実際に試す EspressoUI Automator などのテスト フレームワークを統合することにより、テスト機能を拡張することもできます。Espresso テスト レコーダーを使用すると、Espresso テストを自動的に生成できます。

このページでは、アプリに新しいテストを追加して Android Studio から実行する方法に関する基本的な情報を紹介します。

テストの作成方法の詳細については、Android でアプリをテストするをご覧ください。

テストのタイプと場所

テストコードの場所は、作成するテストのタイプによって異なります。Android Studio では、次の 2 つのタイプのテスト用に、ソースコード ディレクトリ(ソースセット)が用意されています。

ローカル単体テスト

module-name/src/test/java/ にあります。

このテストは、マシンのローカル Java 仮想マシン(JVM)で実行されます。Android フレームワークの依存関係がテスト対象に含まれていない場合、または Android フレームワークの依存関係をモックで代用できる場合は、このテストを使用して、テストに要する時間を最小限に抑えることができます。

このテストは、実行時に、final 修飾子をすべて削除した修正版の android.jar に対して実行されます。そのため、Mockito などの一般的なモック ライブラリを使用できます。

インストゥルメント化テスト

module-name/src/androidTest/java/ にあります。

このテストは、ハードウェア デバイスまたはエミュレータで実行されます。Instrumentation API にアクセスしてテストするアプリの Context などの情報を参照し、テストコードでテスト対象のアプリを制御します。ユーザー インタラクションを自動化する統合テストおよび機能 UI テストを作成する場合、またはモック オブジェクトで代用できない Android 依存関係がテスト対象に含まれている場合は、このテストを使用します。

インストゥルメント化テストは、(アプリの APK とは別の)APK に組み込まれるので、固有の AndroidManifest.xml ファイルが存在する必要があります。ただし、このファイルは、Gradle によってビルド時に自動的に生成されるので、プロジェクトのソースセットでは参照できません。「minSdkVersion」の別の値を指定する場合や、テスト専用の実行リスナーを登録する場合などは、必要に応じて独自のマニフェスト ファイルを追加できます。アプリをビルドする際、Gradle は複数のマニフェスト ファイルを 1 つのマニフェストにマージします。

Gradle のビルドは、プロジェクトのアプリ ソースセットの場合と同じように、これらのテスト ソースセットを解釈します。そのため、ビルド バリアントに基づいてテストを作成することができます。

新しいプロジェクトを作成するか、またはアプリ モジュールを追加すると、Android Studio は上記のテスト ソースセットを作成し、各ソースセットにサンプル テストファイルを挿入します。図 1 のように、これらのテスト ソースセットは [Project] ウィンドウに表示されます。

図 1. [Project] ビュー(左)と [Android] ビュー(右)に表示されたプロジェクトの(1)インストゥルメント化テストと(2)ローカル JVM テスト

新しいテストを追加する

ローカル単体テストまたはインストゥルメント化テストを作成する場合、次の手順を行って、特定のクラスまたはメソッド用の新しいテストを作成できます。

  1. テストしたいコードが含まれている Java ファイルを開きます。
  2. テストしたいクラスまたはメソッドをクリックして、Ctrl+Shift+T キー(⇧⌘T)を押します。
  3. 表示されたメニューで、[Create New Test] をクリックします。
  4. [Create Test] ダイアログでフィールドを編集し、生成するメソッドを選択して [OK] をクリックします。
  5. [Choose Destination Directory] ダイアログで、作成するテストのタイプに応じたソースセットをクリックします。インストゥルメント化テストの場合は androidTest、ローカル単体テストの場合は test です。次に、[OK] をクリックします。

または、次の手順を行って、適切なテスト ソースセット内に汎用 Java ファイルを作成します。

  1. 左側の [Project] ウィンドウでプルダウン メニューをクリックし、[Project] ビューを選択します。
  2. 適切なモジュール フォルダとネストされた src フォルダを展開します。ローカル単体テストを追加するには、test フォルダとネストされた java フォルダを展開します。インストゥルメント化テストを追加するには、androidTest フォルダとネストされた java フォルダを展開します。
  3. Java パッケージ ディレクトリを右クリックして、[New] > [Java Class] を選択します。
  4. ファイルに名前を付けて、[OK] をクリックします。

さらに、アプリ モジュールの build.gradle ファイルに、テスト ライブラリ依存関係を指定します。

dependencies {
        // Required for local unit tests (JUnit 4 framework)
        testImplementation 'junit:junit:4.12'

        // Required for instrumented tests
        androidTestImplementation 'com.android.support:support-annotations:24.0.0'
        androidTestImplementation 'com.android.support.test:runner:0.5'
    }
    

その他のライブラリ依存関係(任意)と、テストの作成方法の詳細については、ローカル単体テストの作成インストゥルメント化テストの作成をご覧ください。

アプリ APK とテスト APK の競合を解決する

アプリ APK とテスト APK は同じクラスパスを共有します。したがって、それらの APK が同じライブラリの異なるバージョンに依存している場合、ビルドエラーが発生します。Gradle がこのバージョン競合を検出できないと、アプリは予期しない動作をするか、実行時にクラッシュすることがあります。

詳細については、依存関係解決のエラーを修正するをご覧ください。

ビルド バリアントに応じたインストゥルメント化テストを作成する

一意のソースセットを持つビルド バリアントがプロジェクトに含まれている場合、対応するインストゥルメント化テストのソースセットがあると便利です。ビルド バリアントに応じたインストゥルメント化テストのソースセットを作成すると、テストコードを適切に分類して、特定のビルド バリアントに適用されるテストのみを実行できます。

ビルド バリアントに応じたテスト ソースセットを追加するには、次の手順を行います。

  1. 左側の [Project] ウィンドウでプルダウン メニューをクリックし、[Project] ビューを選択します。
  2. 適切なモジュール フォルダ内で src フォルダを右クリックし、[New] > [Directory] をクリックします。
  3. ディレクトリ名として「androidTestVariantName」と入力します。たとえば、ビルド バリアントが「MyFlavor」の場合、ディレクトリ名を「androidTestMyFlavor」にします。[OK] をクリックします。
  4. 新しいディレクトリを右クリックして、[New] > [Directory] をクリックします。
  5. ディレクトリ名として「java」と入力し、[OK] をクリックします。

これで、この新しいソースセットにテストを追加できました。[Choose Destination Directory] ダイアログが表示されたら、新しいバリアント用テスト ソースセットを選択します。

src/androidTest/ ソースセット内のインストゥルメント化テストは、すべてのビルド バリアントによって共有されます。アプリの「MyFlavor」バリアント用のテスト APK をビルドすると、Gradle は src/androidTest/ ソースセットと src/androidTestMyFlavor/ ソースセットを結合します。

次の表は、アプリのコード ソースセットに対応するソースセット内にインストゥルメント化テストのファイルがどのように配置されるかを示しています。

アプリクラスのパス 対応するインストゥルメント化テストクラスのパス
src/main/java/Foo.java src/androidTest/java/AndroidFooTest.java
src/myFlavor/java/Foo.java src/androidTestMyFlavor/java/AndroidFooTest.java

アプリ ソースセットの場合と同様に、Gradle のビルドは、異なるテスト ソースセットのファイルをマージおよびオーバーライドします。この場合、「androidTestMyFlavor」ソースセット内の AndroidFooTest.java ファイルは、「androidTest」ソースセット内のバージョンをオーバーライドします。ソースセットがどのようにマージされるかについては、ビルドの設定をご覧ください。

アプリとテストのソースセットに対してビルド バリアントを使用すべきもう 1 つの理由は、モック依存関係を利用して閉じられた環境でのテストを作成するためです。つまり、依存関係のフェイク実装(通常は不安定なネットワーク リクエストやデバイス センサーのデータなど)が含まれるアプリのプロダクト フレーバーを作成してから、対応するモックテスト ソースセットを追加することが可能です。詳細については、閉じられた環境でのテストに役立つプロダクト フレーバーに関するブログ記事をご覧ください。

インストゥルメント化テスト用のマニフェスト設定

Gradle がテスト APK をビルドすると、自動的に AndroidManifest.xml ファイルが生成され、マニフェストに <instrumentation> ノードが設定されます。Gradle がこのノードを設定する理由の 1 つは、targetPackage プロパティでテスト対象のアプリの正しいパッケージ名が指定されていることです。次のサンプルコードのように、テスト ソースセットに別のマニフェスト ファイルを作成するか、モジュール レベルの build.gradle ファイルを設定することにより、このノードのその他の設定を変更できます。

    android {
      ...
      // Each product flavor you configure can override properties in the
      // defaultConfig {} block. To learn more, go to Configure product flavors.
      defaultConfig {
        ...
        // Specifies the application ID for the test APK.
        testApplicationId "com.test.foo"
        // Specifies the fully-qualified class name of the test instrumentation runner.
        testInstrumentationRunner "android.test.InstrumentationTestRunner"
        // If set to 'true', enables the instrumentation class to start and stop profiling.
        // If set to false (default), profiling occurs the entire time the instrumentation
        // class is running.
        testHandleProfiling true
        // If set to 'true', indicates that the Android system should run the instrumentation
        // class as a functional test. The default value is 'false'
        testFunctionalTest true
      }
    }
    ...
    

テストのビルドタイプを変更する

デフォルトでは、すべてのテストは、「debug」ビルドタイプに対して実行されます。テスト対象を別のビルドタイプに変更するには、モジュール レベルの build.gradle ファイルの testBuildType プロパティを使用します。たとえば、「staging」ビルドタイプに対してテストを実行するには、次のスニペットのようにファイルを編集します。

android {
        ...
        testBuildType "staging"
    }
    

Gradle のテスト オプションを設定する

Android plugin for Gradle を使用すると、単体テストのすべてまたは一部のオプションを指定できます。モジュール レベルの build.gradle ファイルで、testOptions {} ブロックを使用して、Gradle がすべてのテストを実行する際の方法を変更するオプションを指定します。

    android {
      ...
      // Encapsulates options for running tests.
      testOptions {
        // Changes the directory where Gradle saves test reports. By default, Gradle saves test reports
        // in the path_to_your_project/module_name/build/outputs/reports/ directory.
        // '$rootDir' sets the path relative to the root directory of the current project.
        reportDir "$rootDir/test-reports"
        // Changes the directory where Gradle saves test results. By default, Gradle saves test results
        // in the path_to_your_project/module_name/build/outputs/test-results/ directory.
        // '$rootDir' sets the path relative to the root directory of the current project.
        resultsDir "$rootDir/test-results"
      }
    }
    

ローカル単体テストのみのオプションを指定するには、testOptions {} 内に unitTests {} ブロックを設定します。

    android {
      ...
      testOptions {
        ...
        // Encapsulates options for local unit tests.
        unitTests {
          // By default, local unit tests throw an exception any time the code you are testing tries to access
          // Android platform APIs (unless you mock Android dependencies yourself or with a testing
          // framework like Mockito). However, you can enable the following property so that the test
          // returns either null or zero when accessing platform APIs, rather than throwing an exception.
          returnDefaultValues true

          // Encapsulates options for controlling how Gradle executes local unit tests. For a list
          // of all the options you can specify, read Gradle's reference documentation.
          all {
            // Sets JVM argument(s) for the test JVM(s).
            jvmArgs '-XX:MaxPermSize=256m'

            // You can also check the task name to apply options to only the tests you specify.
            if (it.name == 'testDebugUnitTest') {
              systemProperty 'debug', 'true'
            }
            ...
          }
        }
      }
    }
    

インストゥルメント化テスト専用のテスト モジュールを使用する

インストゥルメント化テスト専用のモジュールを作成して残りのコードをテスト対象から分離する場合は、別々のテスト モジュールを作成し、ライブラリ モジュールのビルドと同様に、テスト モジュールのビルドを設定します。テスト モジュールを作成する手順は次のとおりです。

  1. ライブラリ モジュールを作成します。
  2. モジュール レベルのビルドファイルで、com.android.test の代わりに com.android.library プラグインを適用します。
  3. プロジェクトを同期します。

テスト モジュールを作成したら、テストコードをメインまたはバリアントのソースセット(src/main/javasrc/variant/java など)に追加します。アプリ モジュールで複数のプロダクト フレーバーを定義している場合は、テスト モジュールでそうしたフレーバーを再作成できます。テスト モジュールは、バリアント対応の依存関係管理を使用して、ターゲット モジュール内の一致するフレーバーのテストを試みます。

デフォルトでは、テスト モジュールには debug バリアントのみが含まれます。ただし、テスト済みのアプリ プロジェクトに合わせて、新しいビルドタイプを作成できます。テスト モジュールで debug 以外の異なるビルドタイプをテストするには、次に示すように、VariantFilter を使用してテスト プロジェクト内の debug バリアントを無効にします。

android {
        variantFilter { variant ->
            if (variant.buildType.name.equals('debug')) {
                variant.setIgnore(true);
            }
        }
    }
    

テスト モジュールでアプリの特定のフレーバーまたはビルドタイプのみをターゲットにしたい場合は、matchingFallbacks プロパティを使用して、テストしたいバリアントのみをターゲットにできます。そうすれば、テスト モジュールは自分自身のためにそれらのバリアントを設定せずにすみます。

テストを実行する

テストを実行するには、次の手順を行います。

  1. ツールバーの [Sync Project] をクリックして、プロジェクトを Gradle と同期します(必須)。
  2. 次のいずれかの方法でテストを実行します。
    • [Project ] ウィンドウでテストを右クリックして、[Run] をクリックします。
    • コードエディタで、テストファイル内のクラスまたはメソッドを右クリックして [Run] をクリックし、クラス内のすべてのメソッドをテストします。
    • すべてのテストを実行するには、テスト ディレクトリを右クリックして、[Run tests] をクリックします。

デフォルトでは、テストは、Android Studio のデフォルトの実行構成を使用して実行されます。実行構成の一部(インストゥルメンテーション ランナーやデプロイのオプションなど)を変更する場合は、[Run/Debug Configurations] ダイアログ([Run] > [Edit Configurations] をクリック)で実行構成を編集できます。

テスト カバレッジを表示する

テスト カバレッジ ツールは、ローカル単体テストで、単体テストによりカバーされたアプリコードの割合と領域をトラッキングするために使用します。テスト カバレッジ ツールを使用すると、アプリを構成する要素、クラス、メソッド、コード行が十分にテストされたかどうかを確認できます。

単体テストを実行する方法はいくつかあり、IntelliJ の Running With Coverage ページに説明があります。次に示すのは、エディタからインラインで単体テストを実行する場合の手順です。

  1. 実行する単体テストをダブルクリックします。
  2. エディタで、カバレッジ付きで実行する行にカーソルを置きます。
    • クラス宣言にカーソルを置くと、そのクラスのすべてのテストメソッドが実行されます。
    • メソッド宣言にカーソルを置くと、そのメソッドのすべてのコードが実行されます。
    • メソッド内の特定の行にカーソルを置くと、その行だけが実行されます。
  3. カーソルを置いた行を右クリックします。
  4. コンテキスト メニューで、[Run test-name with coverage] を選択します。

    カバレッジ ツール ウィンドウが表示されます。

図 2 は、加算、減算、乗算、除算をテストするカルキュレータ単体テストのカバレッジ ツール ウィンドウを示しています。

図 2. アプリのコード カバレッジの割合を確認する

ローカル単体テストの詳細については、ローカル単体テストの作成をご覧ください。

テスト結果を表示する

JUnit テストまたはインストゥルメント化テストを実行すると、[Run] ウィンドウに結果が表示されます。緑のバーはすべてのテストが成功したことを示し、赤いバーは 1 つ以上のテストが失敗したことを示します。図 3 は、成功したテスト実行を示しています。

図 3. [Run] ウィンドウに表示されたテスト結果

[Run] ウィンドウの左側にはツリービューでテストが表示され、右側の出力ペインには現在のテストスイートの結果とメッセージが表示されます。次に示すように、ツールバー、コンテキスト メニュー、ステータス アイコンを使用して、テスト結果を管理できます。

  1. 実行ツールバーを使用して、現在のテストの再実行、現在のテストの停止、失敗したテストの再実行(単体テストでのみ使用可能なため、上の図には表示されていません)、出力の一時停止、スレッドのダンプを行います。
  2. テスト ツールバーを使用して、テスト結果のフィルタリングと並べ替えを行います。また、ノードの展開と折りたたみ、テスト カバレッジの表示、テスト結果のインポートとエクスポートができます。
  3. コンテキスト メニュー をクリックして、テスト実行のトラッキング、インライン統計の表示、スタックトレースのスクロールを行います。また、例外の発生箇所でソースコードを開き、ソースに自動スクロールし、テスト実行の完了時に失敗した最初のテストを選択します。
  4. テスト ステータス アイコンは、テストにエラーがあったか、テストが無視されたか、失敗したか、進行中か、成功したか、一時停止しているか、終了したか、実行されなかったかを示します。
  5. ツリービューの行を右クリックするとコンテキスト メニューが表示され、デバッグモードでテストを実行したり、テストのソースコード ファイルを開いたり、テスト中のソースコードの行にジャンプしたりできます。

[Run] ウィンドウ、ツールバー、コンテキスト メニューの詳細については、IntelliJ の Test Runner Tab ページをご覧ください。

インライン統計を表示する

テストの実行にかかる時間を確認する方法は次のとおりです。

  1. 歯車アイコン をクリックします。
  2. プルダウン リストで、[Show Inline Statistics] を選択します。

    テストの右側に、ミリ秒単位の経過時間が表示されます。

文字列を比較する

単体テストで、2 つの文字列オブジェクトを比較したことによる assertEquals() エラーが発生した場合は、次の手順により、2 つの文字列オブジェクトの違いを確認して、失敗の原因を特定できます。

  1. 出力ペインで、[Click to see difference] リンクをクリックします。
  2. 差分ビューアで違いを調べます。詳しくは、IntelliJ の Differences viewer for files のページをご覧ください。

テスト結果をエクスポートする

テスト結果を XML 形式または HTML 形式でエクスポートするには、次の手順を行います。

  1. [Export Test Results] をクリックします。
  2. [Export Test Results] ダイアログで、出力形式と出力情報を指定して、[OK] をクリックします。

    エクスポートされたテスト結果が、指定したフォルダに保存されます。

テスト結果をインポートする

エクスポート済みのテスト結果をインポートするには、次の手順を行います。

  1. [Import Test Results] をクリックします。
  2. プルダウン メニューで、インポートするファイルを選択します。

    インポートされたテスト結果が、[Run] ウィンドウに表示されます。