アプリをテストする

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 によりこのノードが設定されるのは、targetPackage プロパティがテスト対象アプリの正しいパッケージ名を指すようにするためでもあります。このノードの他の設定を変更するには、テスト ソースセット内に別のマニフェスト ファイルを作成するか、下記のコードサンプルに示すように、モジュール レベルの build.gradle ファイルを設定します。

Groovy

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
    }
}
...

Kotlin

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 が実行するすべてのテストに適用されるオプションを指定します。

Groovy

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"
    }
}

Kotlin

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 {} ブロックを設定します。

Groovy

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'
                }
                ...
            }
        }
    }
}

Kotlin

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 = listOf("-XX:MaxPermSize=256m")

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

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

インストルメンテーション テスト専用のモジュールを作成して残りのコードをテストから分離する場合は、別個のテスト モジュールを作成し、ライブラリ モジュールの場合と同じようにビルドを構成します。テスト モジュールを作成する手順は次のとおりです。

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

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

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

Groovy

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

Kotlin

android {
    variantFilter {
        if (buildType.name == "debug") {
            ignore = 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] ウィンドウに表示されます。

複数のデバイスで並行して実行する

Android Studio Arctic Fox 以降では、複数のデバイスで並行してインストルメンテーション テストを実行し、Test Matrix ツールビューを使用して分析できます。このツールビューを使用すると、さまざまなデバイス設定でどのテストが失敗しているかを、より簡単に特定できます。

複数のデバイスでインストルメンテーション テストを実行する手順は次のとおりです。

  1. インストルメンテーション テストを開きます。
  2. 対象デバイスのプルダウン メニューから [Select Multiple Devices...] を選択します。
  3. インストルメンテーション テストを実行するデバイスを確認し、[OK] をクリックします。
  4. 対象のプルダウン メニューのテキストが [Multiple Devices (x)] に変わったことを確認して、実行ボタンをクリックします。
  5. Test Matrix ツール ウィンドウには、選択した各デバイス設定のテスト結果が表示されます。オプションで、マトリックス内のアイテムをクリックして、選択したテストケースの結果を確認できます。列見出しをクリックして行を並べ替えることもできます。