AndroidでJUnit4とJUnit3.8やEspressoを併用する方法


執筆時点(2014/04/07)の環境、バージョン等

  • AndroidStudio 0.5.4
  • JUnit 4.11
  • Android-JUnit4 0.3
  • Espresso 1.1 (mockitoと併用するときはdependencies版を使いましょう)

1.はじめに

Android開発でAndroidでJUnit4を使う方法の設定を行うとJUnit4を使ったテストを実装できます。
が、上記リンク先の設定を行うと今度はJUnit3.8系(Android SDKに含まれている)で記述したテストやGoogle製UIテストフレームワーク"Espresso"が動かなくなります。(TestRnnerが異なるため)

Espressoを使用したかったので、併用する方法を調べました。
gradleをよく知らなかったのでめちゃくちゃ時間がかかった...。

2.結論

  1. JUnit4用、Espresso用のflavorを用意して、 build.gradle または AndroidManifest.xml でそれぞれのTestRunnerを指定する。
  2. テスト実行設定(Run/Debug Configuration)もJUnit4用、Espresso用を用意して、それぞれのTestRunnerを指定する。

なお、一回のテスト実行で両方を実行することはできません(たぶん)。

※flavorをこの用途に使うことがいいことなのかはよく分かりません。というかちょっと違う気がします。


注意
Espressoを使わず、SDK標準のJUnit3.8のみ使う場合は、
以下の手順で
"com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner"
を指定しているところを、
"android.test.InstrumentationTestRunner"に読み替えてください。また、flavor名やdependenciesは適宜読み替え・変更してください。

3.Product Flavorとは

この辺を参考に。

フレーバーは、アプリケーションの一部の機能や振舞いをカスタマイズするために使います。たとえば「広告あり」フレーバーと「広告なし」フレーバーを定義する、といった具合です。
フレーバーは、build.gradleに定義することではじめて作られますが、1つもフレーバーが定義されていない場合は、暗黙的に名前のない1つのフレーバーが定義されているとみなされます。

ビルドタイプと同様に、フレーバーについても、それぞれソースコードを差し替えたり、リソースを差し替えたりすることができます。

こちらは、ビルドタイプとは異なり、全てのフレーバーが試験対象となります。そのため、テストコードもフレーバーごとに差し替えることが可能になっています。

いま気づいたけど、この引用の最後に「テストコードもフレーバーごとに差し替えることが可能になっています。」って書いてある...もっと早く気付けば...(´・ω・`)

似た機能でBuild Typeというのもあるので、そちらも読んでおきましょう。
Build Typeで実現しようとして2日くらい無駄にしました。

4.JUnit4用、Espresso用Product Flavorの作り方

build.gradle を編集する。

build.gradle
android {
    defaultConfig {
        // testInstrumentationRunnerの指定を削除する。
        // 各flavor内で指定するため。
    }

    productFlavors {
        // JUnit4用のflavor
        junit4Test {
            // AndroidManifest.xmlで指定する場合は、下記設定は省略可。(junit4Test{} のみ記述)
            testInstrumentationRunner "com.uphyca.testing.JUnit4InstrumentationTestRunner"
        }
        // Espresso用のflavor
        espressoTest {
            // AndroidManifest.xmlで指定する場合は、下記設定は省略可。(espressoTest{} のみ記述)
            testInstrumentationRunner "com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner"
        }
    }

    dependencies {
        // Espresso関連jar
        //  参考: "https://code.google.com/p/android-test-kit/wiki/Espresso#To_use_Espresso_without_dependencies"
        // mockitoを使う場合は、hamcrest-core、hamcrest-integrationは入れないらしい。
        //  参考: "http://y-anz-m.blogspot.jp/2013/11/android-ui-testing-framework-espresso.html"
        // mockitoを使わないなら、standalone版のespresso-1.1-bundled.jarだけ下記libsに入れればOK。
        espressoTestCompile fileTree(dir: 'src/espressoTest/libs', include: '*.jar');
        espressoTestCompile 'com.google.guava:guava:14.0.1',
                'com.squareup.dagger:dagger:1.1.0',
                'org.hamcrest:hamcrest-core:1.1',
                'org.hamcrest:hamcrest-integration:1.1',
                'org.hamcrest:hamcrest-library:1.1'

        // JUnit4, mockito 関連jar
        junit4TestCompile ("org.mockito:mockito-core:1.9.5")
        junit4TestCompile ("com.google.dexmaker:dexmaker-mockito:1.+")
        junit4TestCompile ("junit:junit:4.+")
        junit4TestCompile ("com.uphyca:android-junit4:+")
    }
}

productFlavors {} 内に、jnit4TestespressoTestというflavorが定義されました。flavor名は任意の名前でOKです。

dependencies {} 内のjunit4TestCompileespressoTestCompile は各flavorのビルド時に適用されます。(flavor名 + Compileで、そのflavor用の定義として解釈される。ちなみにBuild Typeも同様)

5.各flavor用ディレクトリの作成

srcディレクトリ配下(mainと同じ階層)に jnit4TestespressoTest というディレクトリを作成し、テストコードを格納するjavaディレクトリや、jarを置くlibs、AndroidManifest.xmlを作成します。

作成後、Tools > Android > Sync Project with Gradle Files (またはツールバーのSync Project with Gradle Filesアイコン)を実行してbuild.gradleの変更を反映させておきます。

6.AndroidManifest.xmlの編集

build.gradle でtestInstrumentationRunnerを指定した場合

AndroidManifest.xml
<manifest>
    <!-- 下記以外は省略しています -->
    <instrumentation
        android:targetPackage="your.app.package" />
</manifest>

src/junit4Test/AndroidManifest.xml、src/espressoTest/AndroidManifest.xmlが同じ内容となります。
instrumentation タグの android:name 属性の値は build.gradle で指定したtestInstrumentationRunner の値が挿入されます。

build.gradle でtestInstrumentationRunnerを省略した場合

JUnit4用

AndroidManifest.xml
<manifest>
    <!-- 下記以外は省略しています -->
    <instrumentation
        android:name="com.uphyca.testing.JUnit4InstrumentationTestRunner"
        android:targetPackage="your.app.package" />
</manifest>

Espresso用

AndroidManifest.xml
<manifest>
    <!-- 下記以外は省略しています -->
    <instrumentation
        android:name="com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner"
        android:targetPackage="your.app.package" />
</manifest>

7.AndroidStudioで実行する設定

JUnit4のテストを実行する設定と、Espressoのテストを実行する設定のふたつを作成します。

Run > Edit Configurations... (またはツールバー)から、Run/Debug Configurations画面を開き、左上の+ボタンから以下のように設定を作成する。

JUnit4のテスト実行設定


※Nameは任意のわかりやすい名前に。

Espressoのテスト実行設定


※Nameは任意のわかりやすい名前に。

8.テスト実行

Build Variantsの選択

AndroidStudioの左端、下の方のドロイド君アイコン Build Variants をクリックするとBuild Variantsウインドウが開きます。

テストしたいModule(上図の場合「app」)のBuild Variantsを選択します。

Build Variantsとは

Product FlavorとBuild Typeの組み合わせのこと。
この辺を参考に。

AndroidStudio(というかGradleのAndroidプラグインかな?)では、デフォルトで(暗黙的に)debugrelease というBuild Typeがあり、ここまでの手順で作ったflavorと組み合わせると

  • espressoTest - debug
  • espressoTest - release
  • junit4Test - debug
  • junit4Test - release

となります。(上図のコンボボックスはこれが表示されている)

デフォルト設定では、テストは debug に対してしか実行されません。
なのでJUnit4のテストを実行したいときは junit4TestDebug、Espressoでは espressoTestDebug を選択します。

実行設定の選択

Build Variantsと対応するテスト実行設定(手順7.で作成)を選択します。

Runアイコンでテストを実行します。