高度なテストのセットアップ

基本的なテスト構成をセットアップして実行する方法は、Android Studio でテストするコマンドラインからテストするに記載されています。ただし、アプリとそのテスト要件が高度になるほど、テスト構成の調整が必要になります。たとえば次のようなことを行う場合、高度なテストのセットアップが必要になります。

  • 特定のビルド バリアントに対してのみインストルメンテーション テストを実行するか、そのマニフェスト設定をオーバーライドする。
  • テストを実行するビルドタイプを変更するか、その Gradle オプションを構成する。
  • インストルメンテーション テストを独自のテスト モジュールに抽出する。
  • 継続的インテグレーション セットアップの一環として、さらに高度なテストを行う。

このページでは、デフォルト設定がニーズに合わない場合にテストを構成するさまざまな方法について説明します。

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

一意のソースセットを持つビルド バリアントがプロジェクトに含まれている場合は、そのソースセットに対応するインストルメンテーション テストを用意することをおすすめします。そうすると、テストコードを整理でき、特定のビルド バリアントに適用されるテストのみを実行できます。

インストルメンテーション テストをビルド バリアントにリンクするには、src/androidTestVariantName にある独自のソースセットに配置します。

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

Android Studio でビルド バリアントに応じたテスト ソースセットを追加する手順は次のとおりです。

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

これで、新しいテストの追加手順に沿って、この新しいソースセットにテストを追加できるようになりました。[Choose Destination Directory] ダイアログが表示されたら、新たに作成したバリアント用テスト ソースセットを選択します。

アプリのコード ソースセットに対応するソースセットに、インストルメンテーション テストのファイルがどのように配置されるかの例を下表に示します。

表 1. アプリのソースコードと、対応するインストルメンテーション テストのファイル

アプリクラスのパス 対応するインストルメンテーション テストクラスのパス
src/main/java/Example.java src/androidTest/java/AndroidExampleTest.java
src/myFlavor/java/Example.java src/androidTestMyFlavor/java/AndroidExampleTest.java

アプリ ソースセットの場合と同様に、Gradle のビルドでは、異なるテスト ソースセットのファイルを統合し、オーバーライドします。この場合、androidTestMyFlavor ソースセット内の AndroidExampleTest.java ファイルは、androidTest ソースセット内のバージョンをオーバーライドします。これは、プロダクト フレーバーのソースセットがメインのソースセットよりも優先されるためです。

ビルド バリアント セレクタで異なるフレーバーを選択すると、該当する androidTest フォルダが Android ビューに表示され、使用するフォルダが表示されます。

MyFlavor バリアントが選択され、androidTestMyFlavor フォルダが Android ビューに表示されています
図 1. MyFlavor バリアントが選択され、androidTestMyFlavor フォルダが Android ビューに表示されています。

別のバリアントが選択されている場合、androidTestMyFlavor フォルダは表示されません。

OtherFlavor バリアントが選択され、androidTestMyFlavor フォルダが Android ビューに表示されていません
図 2. OtherFlavor バリアントが選択され、androidTestMyFlavor フォルダが Android ビューに表示されていません。

[Project] ビューを使用している場合は多少異なりますが、同じ原則が適用されます。

MyFlavor バリアントが選択され、androidTestMyFlavor フォルダが Project ビューでアクティブになっています
図 3. MyFlavor バリアントが選択され、androidTestMyFlavor フォルダが Project ビューでアクティブになっています。

別のバリアントが選択されている場合、androidTestMyFlavor フォルダは引き続き表示されますが、アクティブとしては表示されません。

OtherFlavor バリアントが選択され、androidTestMyFlavor フォルダが Project ビューでアクティブになっていません
図 4. OtherFlavor バリアントが選択され、androidTestMyFlavor フォルダが Project ビューでアクティブになっていません。

ソースセットがどのように統合されるかについては、ソースセットをご覧ください。

インストルメンテーション マニフェスト設定を構成する

インストルメンテーション テストは、独自の AndroidManifest.xml ファイルとともに個別の APK に組み込まれます。Gradle がテスト APK をビルドすると、自動的に AndroidManifest.xml ファイルが生成され、<instrumentation> ノードで構成されます。Gradle によってこのノードが構成されるのは、targetPackage プロパティがテスト対象アプリの正しいパッケージ名を指すようにするためでもあります。

このノードの他の設定を変更するには、次のコードサンプルに示すように、テスト ソースセットに別のマニフェスト ファイルを作成するか、モジュール レベルの build.gradle ファイルを構成します。オプションの一覧については、BaseFlavor API リファレンスをご覧ください。

Groovy

android {
    ...
    defaultConfig {
        ...
        testApplicationId "com.example.test"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        testHandleProfiling true
        testFunctionalTest true
    }
}

Kotlin

android {
    ...
    defaultConfig {
        ...
        testApplicationId = "com.example.test"
        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        testHandleProfiling = true
        testFunctionalTest = true
    }
}

構成する各プロダクト フレーバーで、defaultConfig {} ブロックのプロパティをオーバーライドできます。詳しくは、プロダクト フレーバーの設定をご覧ください。

スニペットのプロパティは次のとおりです。

設定 説明
testApplicationId テスト APK のアプリ ID を指定します。
testInstrumentationRunner テスト インストルメンテーション ランナーの完全修飾クラス名を指定します。
testHandleProfiling true に設定すると、インストルメンテーション クラスでプロファイリングの開始と停止が可能になります。
false に設定すると、インストルメンテーション クラスが実行されている全期間にわたってプロファイリングが行われます。
testFunctionalTest true に設定すると、Android システムがインストルメンテーション クラスを機能テストとして実行する必要があることが示されます。
デフォルト値は false です。

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

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

Groovy

android {
    ...
    testBuildType "staging"
}

Kotlin

android {
    ...
    testBuildType = "staging"
}

Gradle テスト オプションを構成する

Android Gradle プラグインを使用すると、テストの全部または一部に対して特定のオプションを指定できます。モジュール レベルの build.gradle ファイルで、testOptions ブロックを使用して、Gradle が実行するすべてのテストに適用されるオプションを指定します。

Groovy

android {
    ...
    // Encapsulates options for running tests.
    testOptions {
        reportDir "$rootDir/test-reports"
        resultsDir "$rootDir/test-results"
    }
}

Kotlin

android {
    ...
    // Encapsulates options for running tests.
    testOptions {
        reportDir "$rootDir/test-reports"
        resultsDir = "$rootDir/test-results"
    }
}

reportDir プロパティは、Gradle がテストレポートを保存するディレクトリを変更します。デフォルトでは、Gradle はテストレポートを path_to_your_project/module_name /build/outputs/reports/ ディレクトリに保存します。$rootDir は、現在のプロジェクトのルート ディレクトリへの相対パスを設定します。

resultsDir プロパティは、Gradle がテスト結果を保存するディレクトリを変更します。デフォルトでは、Gradle はテスト結果を path_to_your_project/module_name /build/outputs/test-results/ ディレクトリに保存します。$rootDir は、現在のプロジェクトのルート ディレクトリへの相対パスを設定します。

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

Groovy

android {
    ...
    testOptions {
        ...
        // Encapsulates options for local unit tests.
        unitTests {
            returnDefaultValues true

            all {
                jvmArgs '-XX:MaxPermSize=256m'

                if (it.name == 'testDebugUnitTest') {
                    systemProperty 'debug', 'true'
                }
                ...
            }
        }
    }
}

Kotlin

android {
    ...
    testOptions {
        ...
        // Encapsulates options for local unit tests.
        unitTests {
            returnDefaultValues = true

            all {
                jvmArgs = listOf("-XX:MaxPermSize=256m")

                 if (it.name == "testDebugUnitTest") {
                    systemProperty = mapOf("debug" to "true")
                }
                ...
            }
        }
    }
}

デフォルトでは、テストするコードが Android プラットフォーム API にアクセスしようとすると、ローカル単体テストで例外がスローされます(Android の依存関係をモックする場合、または Mockito のようなテスト フレームワークを使用する場合を除きます)。ただし returnDefaultValues プロパティを有効にすると、プラットフォーム API にアクセスしたとき、テストで例外をスローされるのではなく null またはゼロが返されるようになります。

all ブロックは、Gradle がローカル単体テストを実行する方法を制御するためのオプションをカプセル化します。指定できるすべてのオプションの一覧については、Gradle のリファレンス ドキュメントをご覧ください。

jvmArgs プロパティは、テスト JVM の JVM 引数を設定します。

タスク名を確認して、指定したテストにのみオプションを適用することもできます。このスニペットの例では、testDebugUnitTest タスクに対してのみ、debug プロパティが true に設定されています。

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

インストルメンテーション テスト専用のモジュールが必要な場合、残りのコードをテストから分離するには、別のテスト モジュールを作成し、ライブラリ モジュールの場合と同様にビルドを構成します。

テスト モジュールを作成する手順は次のとおりです。

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

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

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

Groovy

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

Kotlin

android {
    variantFilter {
        if (buildType.name == "debug") {
            ignore = true
        }
    }
}

テスト モジュールのターゲットをアプリの特定のフレーバーまたはビルドタイプのみにする場合は、matchingFallbacks プロパティを使用して、テストするバリアントのみをターゲットにできます。これにより、テスト モジュール自体でそれらのバリアントを構成する必要もなくなります。