LoginSignup
144
142

More than 5 years have passed since last update.

Espresso 2.0とRobolectricを併用したテスト環境の作り方

Last updated at Posted at 2015-02-03

2015.6.9追記:Android Studio 1.2 + Robolectric 3の組み合わせが良さそうなので、この記事をあまり鵜呑みにしないでください(参考

Androiderの皆さん、テストしてますか?

今回は、UIテストが幸せになるEspresso 2.0と、ユニットテストが幸せになるRobolectricをAndroid Studio的に自然な形で併存させるための設定をご紹介します。

ゴールとしては、下記のような表示になります。

スクリーンショット 2015-02-03 17.27.05.png

Android Studioではあまり見かけないテストフォルダの配置に「おっ」と思った方は、次項を読み飛ばしてその先へどうぞ。

前提知識:これまでのテスト

Espresso

UIテストをモリモリ書いてきた諸兄は、Espressoと仲良くしていらっしゃることと思います。Support Libraryの一部としてEspresso 2.0が配布されるようになり、JUnit4が使えるようになったことを喜んだのは、記憶に新しいところです。

Robolectric

また、ユニットテストをモリモリ書いてきた諸兄は、Robolectricと仲良くしていらっしゃることと思います。JVM上で高速にテストを回すことができるRobolectricは、手元でのTDDにおいても、サーバー上のCIにおいても、欠かすことのできない存在になってきていますね。

問題点と解決策(旧)

どちらもDB層からUI層まで幅広い領域のテストに対応していますが、動作環境や実行速度の一長一短があるため、上手く使い分けができると幸せを享受しやすそうです。

しかし、両方を扱うには、少し問題がありました。Android Plugin for GradleやAndroid Studioは、テスト用ソースディレクトリを1つしか認識することができなかったのです。JUnit3しか書けなかった昔のandroidTestと、JUnit4でテストを書くRobolectricをプロジェクト内に併存させるのは、難しいものに思われました。

この問題への一案を提示したのが、robolectric/deckard-gradleというサンプルプロジェクトでした。

  • src/test/
    • com.example/
      • espresso/
        • FirstUITest
        • SecondUITest
      • FirstRobolectricTest
      • SecondRobolectricTest

deckard-gradleでは、上記のようなパッケージ構造にした後、次のような設定を記述することで、実行されるテストの振り分けを行っていました。

build.gradle
robolectric {
    include '**/*Test.class'
    exclude '**/espresso/**/*.class'
}

これらの設定により、下記のテストが可能になっていました。

  • ./gradlew connectedAndroidTest
  • ./gradlew test
  • Android Studio上でのandroidTestの実行

これはこれで良いものでしたが、少し不自然な対応だったために、1つの問題が残りました。

Espresso用のパッケージを別に用意したために、パッケージプライベートなフィールドに直接アクセスすることによる、テスト上の利便性を享受できなくなってしまったのです。

パッケージプライベートをテストで利用している例
@Test
public void 各Viewがインジェクトされている() {
    assertThat(activity.toolbar, is(not(nullValue())));
    assertThat(activity.tvDisplay, is(not(nullValue())));
    assertThat(activity.ivPicasso, is(not(nullValue())));
}

余談:その他の問題

他にも、旧来のdeckard-gradle方式による環境構築には、いくつかの問題がありました。

  • RobolectricテストをAndroid Studio上から実行することができない(通常のRobolectricの問題)
  • Espresso 2.0とRobolectricが混在した環境でAndroidJUnitRunnerを走らせると、Robolectricテストも実行しようとしてエラーになる

android-unit-test + Android Studio Unit Test

Espresso 2.0の時代に追従すべく、日本時間で2月3日の早朝に大きなリニューアルコミットがdeckard-gradleにマージされました

できるようになったこと

今回のリニューアルで、できるようになったことを列挙します。

  • src/androidTestに置いたEspresso 2.0方式のテストを./gradlew connectedAndroidTestで実行できるようになった
  • src/testに置いたRobolectricテストを./gradlew testで実行できるようになった
  • Android Studio上でのandroidTestの実行
  • 以下はAndroid Studio Unit Testプラグイン導入後に実行可能になる
    • Android Studio上でのRobolectricテストの実行ができるようになった
    • Android Studio上でsrc/androidTestsrc/testが両方ともテストソースディレクトリとして認識される(緑色のアイコンになる)

大きな変更点としては下記2点が挙げられます。

  • テストの種類ごとにディレクトリを分けても、それぞれにパスが通ったままテストコードを書けるようになった
  • Android Studio上でRobolectricテストを実行できるようになった

実装の要点

android-unit-testによるテスト環境構築について、要点だけ解説します。

Espresso 2.0特有の設定内容(AndroidJUnitRunnerとか)については特に説明しません。他の記事をご覧ください。

1. robolectric-gradle-pluginを置き換える

もうrobolectric-gradle-pluginは使いません。ありがとう。さようなら。

代わりに、android-unit-testプラグインを使います。

build.gradle
classpath 'com.github.jcandksolutions.gradle:android-unit-test:2.1.1'

これに伴い、apply plugin: 'robolectric'robolectric { ... }などのコードも削除します。これまでrobolectricブロックに書いていた設定を今後も扱いたい場合は、android-unit-testのREADMEに類似の情報がありますので、適宜設定してください。

2. プラグインの適用とテスト用のdependencyを記述する

まずはandroid-unit-testプラグインを有効にします。必ずandroid{ ... }ブロックの 下に 記述しましょう。

build.gradle
apply plugin: 'com.android.application'

android {
  ...
}

apply plugin: 'android-unit-test'

さらにその下には、テスト用のdependencyを記述できます。Espressoテスト向けはandroidTestCompileとして、Robolectricテスト向けはtestCompileとして記述します。

下記は、deckard-gradleのbuild.gradleにおける一例です。

build.gradle
apply plugin: 'android-unit-test'

dependencies {
    repositories {
        mavenCentral()
    }

    // Espresso
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.0')
    androidTestCompile('com.android.support.test:testing-support-lib:0.1')

    // Robolectric
    testCompile 'junit:junit:4.12'
    testCompile 'org.hamcrest:hamcrest-core:1.1'
    testCompile 'org.hamcrest:hamcrest-library:1.1'
    testCompile 'org.hamcrest:hamcrest-integration:1.1'

    testCompile('org.robolectric:robolectric:2.4') {
        exclude module: 'classworlds'
        exclude module: 'commons-logging'
        exclude module: 'httpclient'
        exclude module: 'maven-artifact'
        exclude module: 'maven-artifact-manager'
        exclude module: 'maven-error-diagnostics'
        exclude module: 'maven-model'
        exclude module: 'maven-project'
        exclude module: 'maven-settings'
        exclude module: 'plexus-container-default'
        exclude module: 'plexus-interpolation'
        exclude module: 'plexus-utils'
        exclude module: 'wagon-file'
        exclude module: 'wagon-http-lightweight'
        exclude module: 'wagon-provider-api'
    }
}

テスト内でmockitoなどを使いたい場合には、このタイミングで記述しておきましょう。

ひとまずこの段階で、./gradlew connectedAndroidTest./gradlew testは実行できるようになっているはずです。お手軽ですね。

3. Android Studioにプラグインを入れる

Preferences > Plugins > Browse RepositoriesAndroid Studio Unit Test を探してインストールします。

スクリーンショット 2015-02-04 2.00.17.png

これで準備は完了です。

Robolectricで使用していた android.sourceSets.androidTest.setRoot("src/test") が残っていると、上手くいかないので事前にbuild.gradleから削除しておきましょう。

src/androidTestsrc/testが両方ともテストソースディレクトリとして扱われていることを確認できるはずです。

スクリーンショット 2015-02-03 17.27.05.png

Robolectricテストを動かしてみる

それでは、RobolectricのテストをAndroid Studioから実行してみましょう。どれかのテストクラスを右クリックして、JUnitテストとして実行します。(ドロイド君ではない方です)

スクリーンショット 2015-02-04 2.10.55.png

すると、Android Studioのテスト結果画面が現れます。やはり、テストの成功が緑色のバーで見れると、達成感がありますね。

スクリーンショット 2015-02-04 2.15.08.png

まとめ

android-unit-testプラグインを使うことで、Android標準のテスティングフレームワークとRobolectricを、Android Studio内で編集・実行しやすい形で共存させることができるようになりました。

UIテストに強いEspressoと、ユニットテストに強いRobolectricを上手く使い分けながら、堅牢なアプリを開発するべく、ゴリゴリとテストを書いていけたら素晴らしいですね。

それでは皆様、良いテストライフを。

宣伝

ウォーターセル株式会社では、農業界に新しい情報プラットフォームを構築し、生産者に嬉しい情報の扱い方を模索しようとしています。この難題を一緒に考えてくれるAndroidアプリエンジニア、iOSアプリエンジニア、インフラエンジニア、Webフロントエンドエンジニア、Railsエンジニアを探しています。

興味のある方はTwitterで@Nkznへ空リプか何かください。

144
142
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
144
142