今更ながら、この記事の通りに、Robolectric に対応したプロジェクトを作る手順をまとめておきます。
Robolectric の役割
Android は、標準のフレームワークにテストフレームワークも含んでいます。
JUnit3 をベースとして、モジュールのテストや画面のテストの為のフレームワークが提供されています。
一方、実行環境の制約から、Android エミュレータや端末上での実行が要求されます。テストの実行のためにエミュレータを立ち上げたり、テストの apk をインストールしたりする必要が有るため、テストそのものの実行に手間と時間がかかってしまいます。
Robolectric では、Android のフレームワークにある各種の API を JVM 上でエミュレートすることにより、テストの実行時間を短くスピーディにすることができます。
手順の概要
- build.gradle の設定でテストの準備をする
TestRunner を拡張して、AndroidManifest を見えるようにする- テストを書く
build.gradle の準備
ビルドスクリプトに記述する内容は以下の通りです。
android-test プラグインの導入- robolectric プラグインの導入
- JUnit4, Robolectric, Android-FEST への依存の宣言
テスト用のディレクトリの変更
現在、Robolectric は KitKat に対応していないため、TargetSDK と CompileWith の API Level を 18 にしておきます。
この設定は@Config
アノテーションを用いてテストコード中で設定できます。
2015/03/10 追記:以下のスクリプトはすでに古く、動作する保証がありません。現時点で最新の記述はこの下にあります。
buildscript {
// ビルドスクリプトの依存
repositories {
mavenCentral()
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
}
dependencies {
classpath 'com.android.tools.build:gradle:0.8.+'
classpath 'com.squareup.gradle:gradle-android-test-plugin:0.9.1-SNAPSHOT'
}
}
repositories {
mavenCentral()
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
}
apply plugin: 'android'
apply plugin: 'android-test'
android {
compileSdkVersion 18
buildToolsVersion "19.0.1"
defaultConfig {
minSdkVersion 7
targetSdkVersion 18
versionCode 1
versionName "1.0"
}
sourceSets {
instrumentTest.setRoot('src/test') // テストディレクトリを test に変更する
}
}
dependencies {
compile 'com.android.support:gridlayout-v7:19.0.1'
compile 'com.android.support:support-v4:19.0.1'
compile 'com.android.support:appcompat-v7:19.0.1'
testCompile 'junit:junit:4.11' // JUnit 4
testCompile 'org.robolectric:robolectric:2.3-SNAPSHOT' // Robolectric 本体
testCompile 'com.squareup:fest-android:1.0.+' // FEST(Fixtures for Easy Software Testing) を Android で利用するためのライブラリ
instrumentTestCompile 'junit:junit:4.11'
instrumentTestCompile 'org.robolectric:robolectric:2.3-SNAPSHOT'
instrumentTestCompile 'com.squareup:fest-android:1.0.+'
}
2015/03/10 追記:こちらが最新
buildscript {
// ビルドスクリプトの依存
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.1.0'
classpath 'org.robolectric:robolectric-gradle-plugin:1.0.1'
}
}
repositories {
jcenter()
}
apply plugin: 'com.android.application'
apply plugin: 'org.robolectric' // 少し前まで robolectric でしたが、正式リリース以後 org.robolectric となります
android {
compileSdkVersion 21
buildToolsVersion "21.1.2"
defaultConfig {
minSdkVersion 7
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
// robolectric のテストは androidTest ディレクトリに放り込むので sourceSet について特に記述なし
}
dependencies {
compile 'com.android.support:gridlayout-v7:19.0.1'
compile 'com.android.support:support-v4:19.0.1'
compile 'com.android.support:appcompat-v7:19.0.1'
// 以下、様々な transitive dependencies を exclude します
androidTestCompile('junit:junit:4.11') { // JUnit4
exclude module: 'hamcrest-core'
}
androidTestCompile('org.robolectric:robolectric:2.4') { // Robolectric 本体
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-plugin-registry'
exclude module: 'maven-profile'
exclude module: 'maven-project'
exclude module: 'maven-settings'
exclude module: 'nekohtml'
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-http-shared'
exclude module: 'wagon-provider-api'
exclude group: 'com.android.support', module: 'support-v4'
}
androidTestCompile 'org.mockito:mockito-all:1.9.5'
androidTestCompile 'com.squareup:fest-android:1.0.+' // FEST(Fixtures for Easy Software Testing) を Android で利用するためのライブラリ
}
TestRunner の準備
src/test/java
にテストを配置する関係で、Robolectric が AndroidManifest を見つけられなくなるため、TestRunner を拡張して場所を指定します。
2015/03/10 追記:以下の TestRunner は必要無くなりました。org.robolectric.RobolectricTestRunner を使用します。AndroidManifest については、@Config
アノテーションを用います。
import org.junit.runners.model.InitializationError;
import org.robolectric.AndroidManifest;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.res.Fs;
public class RobolectricGradleTestRunner extends RobolectricTestRunner {
public RobolectricGradleTestRunner(Class<?> testClass) throws InitializationError {
super(testClass);
}
@Override
protected AndroidManifest getAppManifest(Config config) {
String manifestProperty = System.getProperty("android.manifest");
if (config.manifest().equals(Config.DEFAULT) && manifestProperty != null) {
String resProperty = System.getProperty("android.resources");
String assetsProperty = System.getProperty("android.assets");
return new AndroidManifest(Fs.fileFromPath(manifestProperty), Fs.fileFromPath(resProperty),
Fs.fileFromPath(assetsProperty));
}
AndroidManifest appManifest = super.getAppManifest(config);
return appManifest;
}
}
以上で、プロジェクトの準備は完了です。
テストの記述
Android フレームワークが提供するテストスートと違い、JUnit4 が使えるので、以下のようにテストが記述できます。
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import static org.junit.Assert.assertTrue;
@RunWith(RobolectricTestRunner.class) // TestRunner の指定
@Config(manifest = "src/main/AndroidManifest.xml", emulateSdk = 18) // sdk の api level を指定する
public class MyModuleTest {
@Test // テストケースの表明
public void shouldPass() throws Exception {
assertTrue(true);
}
}
テストの実行は以下のようにします。
$ ./gradlew test
これで、エミュレータ無しにテストが実行できるようになりました。