続・AndroidでJUnit4を使う方法(Android SDKで正式サポートされました!)


はじめに

Androidアプリケーション開発者にでっかいクリスマスプレゼント?が投げ込まれましたー。

Espressoが2.0にバージョンアップすると共に、Android Support Library の一部として取り込まれ、JUnit4がサポートされました!!

Espresso 2.0 is here!: Google+
Espresso 2.0 が Android support library の一部としてリリースされた

SDK ManagerでAndroid Support RepositoryをインストールすればEspressoのjarをlib等に置くことなく使えるということかな?(まだ試してません・・・)

(参考)こちらも併せてどうぞ

Setup

変更点

build.gradle
# Esporesso1.1までの書き方
androidTestCompile files('libs/espresso-1.1-bundled.jar')  
androidTestCompile files('libs/testrunner-1.1*.jar')

" 2.0~の書き方
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.0'
androidTestCompile 'com.android.support.test:testing-support-lib:0.1'
HogeTest.java
// ~1.1
com.google.android.apps.common.testing.ui.espresso
// 2.0~
android.support.test.espresso

サンプル

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

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"

    defaultConfig {
        applicationId "com.my.awesome.app"
        minSdkVersion 10
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

    }
    ...
}

dependencies {
    // App's dependencies, including test
    compile 'com.android.support:support-annotations:21.0.3'

    // Testing-only dependencies
    androidTestCompile 'com.android.support.test:testing-support-lib:0.1'
    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.0'
}

Getting Started

AndroidJUnitRunnerについて

ざっくりですが、Espresso 2.0 で導入された AndroidJUnitRunner のオフィシャルWikiのJUnit4関連部分を抜粋・意訳しました。

誤訳等あったらごめんなさい。

以下翻訳

JUnit4

(訳注: このセクションはほとんどJUnit4自体の説明なので知っている人は読み飛ばしてください。特に後半のアノテーションの説明。)

 AndroidJUnitRunner は、JUnit3と完全な上位互換性を保ちながらJUnit4に完全対応しています。AndroidRunnerBuilder はJUnitの AllDefaultPossibilitiesBuilder を継承しておりJUnit3とJUnit4の両方のテストを収集するため、既存のJUnit3のテストを書き換えることなく、Junit4の新たなテストを書くことができます。

注意:一つのクラス内に、JUnit3方式とJUnit4方式のテストを混ぜないでください。

 JUnit4のテストには @RunWith(AndroidJUnit4.class) アノテーションをつけてください。AndroidJUnitRunner は全てのJUnit4アノテーションをサポートしており、テストの実行やコーディングがより簡単で理解しやすくなります。

 よく使うアノテーションを挙げましょう。

  • @Test アノテーションは、JUnit3のtestXXXプレフィックスの代替機能です。JUnit4のテストクラスは TestCase クラスを継承する必要はありませんし、継承するとJUnit3のテストとして扱われます。

  • @Test(expected=IllegalArgumentException.class) 。JUnit4では@Test アノテーションの後ろに期待するパラメータを書くことで、コード量を減らせます(訳注: 原文の toredudes は to reduces のタイポ??自信なし)。JUnit3では以下のようなコードでした。

try{ 
    foo.bar();
    fail("IllegalArgumentException expected");
} catch (IllegalArgumentException expected) {}
  • @Before はJUnit3の setUp() メソッドに相当し、各テストメソッドの実行前に呼び出されます。テストフィクスチャのセットアップ等に使います。複数の @Before メソッドがあってもよいですが、呼び出し順は一定ではありません。

  • @AftertearDown() に相当し、各テストメソッド終了時に実行されます。リソース解放に使いましょう。

  • @BeforeClass はテストクラス毎に一度だけ呼び出されます。DB接続などコストのかかる処理に使うとよいでしょう。

  • @AfterClass はクラス内の全テストメソッド実行後に呼ばれます。 BeforeClassで作成したリソースの解放に使います。

AndroidテストAPIへの適用

ActivityInstrumentationTestCase2

 ActivityInstrumentationTestCase2 のような既存のAndroidテストAPIでJUnit4構文を使うには、次の5ステップを行います。

  • ActivityInstrumentationTestCase2 に @RunWith(AndroidJUnit4.class) アノテーションを付けます。(訳注: 原文の ! はタイポ??)
  • setUp() メソッドをオーバーライドし、@Before アノテーションを付け、super.setUp() を呼び出します。
  • InstrumentationRegistry を使用して Instrumentation をインジェクトします。以前はInstrumentationTestRunner によりインジェクトされていましたが、手動で行う必要があります。
injectInstrumentation(InstrumentationRegistry.getInstrumentation());
  • AndroidJUnitRunner に認識させるため、全てのテストに @Test を付けます。
  • tearDown をオーバライドし @After を付け、 super.tearDown() を呼び出します。これはオブジェクトのリークを防ぐために重要です。

ActivityInstrumentationTestCase2 でJUnit4を使った例です。

@RunWith(AndroidJUnit4.class)
@LargeTest
public class MyJunit4ActivityInstrumentationTest
            extends ActivityInstrumentationTestCase2<MyActivity> {

    private MyActivity mActivity;

    public MyJunit4ActivityInstrumentationTest() {
        super(MyActivity.class);
    }

    @Before
    public void setUp() throws Exception {
        super.setUp();
        injectInstrumentation(InstrumentationRegistry.getInstrumentation());
        mActivity = getActivity();
    }

    @Test
    public void checkPreconditions() {
        assertThat(mActivity, notNullValue());
        // Check that Instrumentation was correctly injected in setUp()
        assertThat(getInstrumentation(), notNullValue());
    }

    @After
    public void tearDown() throws Exception {
        super.tearDown();
    }

}

Instrumentation Thread Handlers

(訳注: よくわかっていないので省略します)

参考

JUnit4についてはこの本が勉強になりました。初心者にもわかりやすかったです。
Androidのテストに関する記述もあって(eclipseベースだったりして)若干古いですが、考え方はいまでも充分役に立ちます。

JUnit実践入門 ~体系的に学ぶユニットテストの技法 (WEB+DB PRESS plus)
JUnit実践入門 ~体系的に学ぶユニットテストの技法 (WEB+DB PRESS plus)