Android StudioでRobolectricを使いJUnit4によるユニットテストを行う

Android StudioでJunit4を使ったテストを実行する方法は、今のところ2通りあるみたいです。

  • TestRunnerを指定して行う(android-junit4を使う)
  • Robolectricを使う

TestRunnerを指定した方法だと、IDEでテストの実行結果が確認できるので便利です。ただし、設定がややこしいのが不便なところです。簡単に取り込める方法があれば教えて欲しいです。

対してRobolectricを使う場合は、テストの実行結果をブラウザで確認しなければならないというデメリットはありますが、導入方法が比較的簡単です。今回はRobolectricを使ってJunit4によるユニットテストを実施する手順を紹介します。

Qiitaのこちらの記事があってようやくまともに入れることができました。感謝感謝。

1. プロジェクトを作成する

Android StudioのメニューからFile > New Projectを選択し、新規プロジェクトを作成します。単にプロジェクトを作成するだけです。別に既存のプロジェクトを使うなら飛ばして問題無いです。

2. build.gradleの編集

プロジェクトルートのbuild.gradleにclasspath 'org.robolectric:robolectric-gradle-plugin:0.13.+'を追記します。(app/build.gradleではないです)

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.13.2'
        classpath 'org.robolectric:robolectric-gradle-plugin:0.13.+'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

新規プロジェクトの場合、build.gradleがこうなればOKです。(この例ではAndroid Studio 0.8.14を使っています)

3. app/build.gradleの編集

やることは3つです。

  • apply plugin: ‘robolectric’の追加
  • dependenciesの追加
  • robolectricディレクティブの追加

apply pluginの追加

app/build.gradleの2行目(apply plugin: 'com.android.application'のすぐ下)にapply plugin: 'robolectric'を追加します。

dependenciesの追加

RobolectricとJunit4を追加をします。

    androidTestCompile 'org.robolectric:robolectric:2.3'
    androidTestCompile 'junit:junit:4.11'

robolectricディレクティブの追加

robolectric-gradle-pluginのサンプルを利用してコピペします。

そのままだとGradle Syncがうまくいかないので、一部削除しています。

robolectric {
    // configure the set of classes for JUnit tests
    include '**/*Test.class'
    exclude '**/espresso/**/*.class'

    // configure max heap size of the test JVM
    maxHeapSize = '2048m'

    // configure whether failing tests should fail the build
    ignoreFailures true

    // use afterTest to listen to the test execution results
    afterTest { descriptor, result ->
        println "Executing test for {$descriptor.name} with result: ${result.resultType}"
    }
}

最終的にapp/build.gradleはこんな感じになります。

apply plugin: 'com.android.application'
apply plugin: 'robolectric'

android {
    compileSdkVersion 21
    buildToolsVersion "21.0.2"

    defaultConfig {
        applicationId "jp.gcreate.sample.samplerobolectric"
        minSdkVersion 10
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.0'
    androidTestCompile 'org.robolectric:robolectric:2.3'
    androidTestCompile 'junit:junit:4.11'
}

robolectric {
    // configure the set of classes for JUnit tests
    include '**/*Test.class'
    exclude '**/espresso/**/*.class'

    // configure max heap size of the test JVM
    maxHeapSize = '2048m'

    // configure whether failing tests should fail the build
    ignoreFailures true

    // use afterTest to listen to the test execution results
    afterTest { descriptor, result ->
        println "Executing test for {$descriptor.name} with result: ${result.resultType}"
    }
}

JUnit4によるテストをしてみる

とりあえずJUnit4を使ったテストができるか試してみます。ここではTrueを返すだけのtest()メソッドを持ったクラスを作ります。

テスト対象クラス

public class Sample {
    public boolean test(){
        return true;
    }
}

テストコードを作成する

androidTest/java/(パッケージ)/SampleTest.javaを作成します。勝手が分かっている方なら直接作った方が早いと思います。が、今回はIDEにある程度作って貰う方法を紹介します。

作成したテスト対象クラス(今回はSample.java)をエディタで開いた状態で、右クリックしGo To > Testを選びます。

右クリックGoTo Test

その後小さいダイアログが出てくるので、Create New Testをクリックします。

Create New Test

そうするとテストコードを自動生成してくれるウィザードが立ち上がるので、JUnit4を選んでやります。(他にもJUnit3やら作成してくれます)

Create TestでJUnit4を選ぶ

画像はSampleTestTestになっていますが、今回の例で言うとSampleTestになっているはずです。(SSとったときは対象クラスの名前がSampleTestだったんです・・・)

JUnit4にチェックを付ける以外は特に何もしなくてOKです。Memberのところにチェックをつけると、自動的にテストメソッドまで作ってくれます。

その後、テストコードをどこに配置するか聞いてくるので、androidTestとなっているディレクトリを選んでやればOKです。(デフォルトで選ばれているディレクトリを指定してやれば大丈夫だと思います)

androidTestとなっているディレクトリを選ぶ

後は作成されたテストコードのクラス名の前に、@RunWith(RobolectricTestRunner.class)を追記します。

テストコードはこんな感じになりました。

import org.junit.Test;

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.*;

@Config(emulateSdk = 18)
@RunWith(RobolectricTestRunner.class)
public class SampleTest {

    @Test
    public void とりあえず失敗するテスト(){
        Sample sut = new Sample();
        assertThat(sut.test(),is(false));
    }

    @Test
    public void とりあえず成功するテスト(){
        Sample sut = new Sample();
        assertThat(sut.test(),is(true));
    }

isが赤字になってしまいますが、org.hamcrest.core.Is.isをstatic importすればOKです。

実行はターミナルで./gradlew clean testと入力してエンターです。(gradlewが置いてあるディレクトリで実行すること)

毎回コマンドを打つのが面倒くさい場合、Android StudioのメニューからRun > Edit configrations ...で+ボタンを押しGradleを追加、Gradle Projectにプロジェクトルートを追加、Tasksにclean testと入力したものを作ります。後はGUIからこれを選んで実行してやれば、毎回コマンド入力しなくても同じことができます。

Edit configrationsでGradleを追加

Gradle projectにプロジェクトルートを選択、Tasksにclean testを入力

作成したGradle実行環境を選んで再生ボタン押す

テストの結果はプロジェクトルート/app/build/test-report/debug/index.htmlに出力されます。いちいちブラウザで確認しないといけないのは若干面倒くさくはあります。

ちなみに初期状態で作られているApplicationTest.javaのせいで余計なエラーが出ます。

JUnit4実行結果

ApplicationTest.javaを削除すれば出てこなくなります。

@Config(emulateSdk = 18)について

targetSdkVersionを19以上にしていると、Robolectric does not support API level 19, sorry!というエラーが表示されます。この場合は、テストコードに@Config(emulateSdk = 18)@RunWithの前に追記することで回避できます。

API19以上に依存するクラスをテストしたい場合は、Robolectricが対応するのを待つか、それまではRobolectricを使わずにテストするしかないみたいです。

参考:Stack over flow

Amazonのほしいものリストを公開しています。仕事で欲しいもの、単なる趣味としてほしいもの、リフレッシュのために欲しいものなどを登録しています。 寄贈いただけると泣いて喜びます。大したお礼はできませんが、よりよい情報発信へのモチベーションに繋がりますので、ご検討いただければ幸いです。