JUnit4 と Robotium を共存させる方法


JUnit4 と Robotium を共存させる方法です。
@RunWith(Enclosed.class) でテストクラスを階層化・グルーピングして、テストの条件ごとにテストメソッドを分類して整理できるようになるので便利です。

Gradle まわり

テスト対象のアプリの build.gradle に設定を書いていきます。
行うことは2つです。

テストコードの依存関係の解決

  • JUnit4(など)
  • Robotium

の依存関係を解決します。

dependencies {
    androidTestCompile 'com.android.support.test:testing-support-lib:0.1'
    androidTestCompile 'com.jayway.android.robotium:robotium-solo:5.2.1'

    // もしくは、 jar ファイルを ディレクトリに置いておくなら
    // androidTestCompile fileTree(dir: 'testlibs', include: '*.jar')
}

テストランナー (android.support.test.runner.AndroidJUnitRunner) の設定

android {
    defaultConfig {
        testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner'
    }
}

テストクラス

main と同じ階層に androidTest ディレクトリを作ります。そのなかに java ディレクトリを作成します。
図にすると下のとおりです。

src
┣ main
┃ ┗ java
┃    ┗ com.example // アプリのコード
┗ androidTest
   ┗ java
      ┗ com.example.debug.test // テストクラスはこの中!

テストクラスは次のようになります。

  • 各テストクラスの親クラスになる BaseTest クラス
  • サブクラスの SampleTest@RunWith(Enclosed.class) で階層化してみました)

の2つにわけてみました。

BaseTest.class
@RunWith(AndroidJUnit4.class)
abstract public class BaseTest extends ActivityInstrumentationTestCase2<AppBaseActivity> {

    protected Solo solo;

    public BaseTest() {
        super(AppBaseActivity.class);
    }

    @Before
    @Override
    public void setUp() throws Exception {
        super.setUp();
        injectInstrumentation(InstrumentationRegistry.getInstrumentation());
        solo = new Solo(getInstrumentation());
        getActivity();
    }

    @After
    @Override
    public void tearDown() throws Exception {
        solo.finishOpenedActivities();
        super.tearDown();
    }
}
SampleTest.class
@RunWith(Enclosed.class)
public class SampleTest {

    @RunWith(AndroidJUnit4.class)
    public static class FooTest extends BaseTest {

        public FooTest() {
            super();
        }

        @Test
        public void runFoo() {
            // テストコード
        }

        @Test
        public void runFooWithExpiredToken() {
            // テストコード
        }
    }

    @RunWith(AndroidJUnit4.class)
    public static class BarTest extends BaseTest {

        public BarTest() {
            super();
        }

        @Test
        public void runBar() {
            // テストコード
        }
    }
}

テスト実行

GUI

Android Studio。塗りつぶしている箇所はモジュールを選択。

CUI

./gradlew clean assembleDebug assembleAndroidTest

# テスト対象のアプリ 
adb install -r sample/build/outputs/apk/app-debug.apk

# テスト
adb install -r sample/build/outputs/apk/app-debug-androidTest-unaligned.apk

adb shell am instrument -w com.example.debug.test/android.support.test.runner.AndroidJUnitRunner

感想

JUnit4 は JUnit3 に比べて色々と便利なアノテーションが追加されていますね。あまり知らないので学んでいきたいと思いました。