Help us understand the problem. What is going on with this article?

Robolectric (v4.3)の導入で迷える子羊を俺が救う[ Android / testing ]

Robolectric

記事の初版からだいたい一年が経ちました

(特にセットアップ関係は)ここを見たほうがよいと思います。
Android Developers > ドキュメント > ガイド > 「ローカル単体テストを作成する」
https://developer.android.com/training/testing/unit-testing/local-unit-tests?hl=ja
依存関係系はページの先頭に書いてあって、実際のコードはフレームワークの依存関係を含めるあたりです。

java.lang.IllegalStateException: No instrumentation registered!で怒られたらAndroid Gradle Pluginを見直してみてくださいね。
https://stackoverflow.com/questions/53595837/androidx-no-instrumentation-registered-must-run-under-a-registering-instrumen

よいテストライフを👋

これ is 何

Androidのテスト環境のRobolectric v4.3 の導入を紹介する記事です。

Robolectric v4.0以降大幅に書き方が変化したもののそれに対応していない記事が多く、
今新規に導入をしようとした場合には半端なレベルの日本語作業者は全員地獄を見ると思ったので、
次なる犠牲者を出さないためにも記事にすることにしました。ちなみに僕は地獄を見ました。

手順

ビルド設定関連

書いてあるところ : Robolectric GETTING-STARTED

module-name/build.gradle
android {
  // ほかにも書いてある
    sourceSets {
      // ↓無ければ追記
        test.java.srcDirs += 'src/test/java'
        androidTest.java.srcDirs += 'src/androidTest/java'
    }

    testOptions {
        unitTests {
            includeAndroidResources = true
            returnDefaultValues = true
        }
    }
}

dependencies{
    // ほかにも書いてある
    testImplementation 'androidx.test:core:1.2.0'
    testImplementation 'androidx.test:runner:1.2.0'
    testImplementation 'androidx.test:rules:1.2.0'
    testImplementation 'androidx.test.ext:junit:1.1.1'
    testImplementation 'androidx.test.ext:truth:1.2.0'
    testImplementation 'com.google.truth:truth:0.42'

    testImplementation 'junit:junit:4.12'
    testImplementation 'org.robolectric:robolectric:4.3'
}
gradle.properties
  # androidStudio 3.3以上では不要
  android.enableUnitTestBinaryResources=true

ここまでで環境の整備は完了です。かんたん!

テストの記述

手作業でも AndroidStudio のCreate Testでもよいので、テストのファイルを用意します。(test.java.srcDirsのほうのディレクトリです!)
ここで色々書いていくわけですが、公式を参考にするだけでは書ききれなかったりと、ハマりポイントでした。

テストランナー

@RunWith(AndroidJUnit4::class)

v4.0以降を使うのであれば、たぶんandroidxを使わない手はないと思うのでAndroidJUnit4です。
Robolectricのものと自動で切り替わります。

Contextの取得

ApplicationProvider.getApplicationContext()

InstrumentationRegistryは使用しません。

ActivityScenarioの取得

val scenario = launch<CountActivity>(startActivityIntent)

実際の実装からいくらか切り抜いて例としているので半端になってしまうのですが、
こんな感じ↓のダイアログのイメージです。まさかの文字列表現。

タイトル文字列   
[-][+][ 5]

各ViewのIDはtitleText,buttonMinus,buttonPlus,count

機能は

  • 数値をカウントアップ・ダウンする
  • Intent経由で以下の値を渡せる
    • タイトル文字列 IntentKey.TITLE_TEXT (String)
    • 現在値 IntentKey.COUNT (Int)
    • 最小値 IntentKey.LOWEST_COUNT (Int)
@RunWith(AndroidJUnit4::class)
@Config(sdk = [Build.VERSION_CODES.O]) // 動作対象バージョンの指定ができます
class CountActivityTest {
    @Test fun onClickCount() {
        val startActivityIntent = Intent(ApplicationProvider.getApplicationContext(), CountActivity::class.java).also{
            it.putExtra(CountActivity.IntentKey.TITLE_TEXT.name,"TEST_TITLE")
            it.putExtra(CountActivity.IntentKey.COUNT.name, 3)
            it.putExtra(CountActivity.IntentKey.LOWEST_COUNT.name, 0)
        }

        val scenario = launch<CountActivity>(startActivityIntent)
        scenario.moveToState(Lifecycle.State.CREATED) // Activityの状態をCreatedにする=onCreate()後の状態
        scenario.onActivity {
            assertNotEquals(it.titleText.text, "ERROR_TITLE")
            assertEquals(it.titleText.text, "TEST_TITLE")

            assertEquals(it.count.text, "3")
            assertNotEquals(it.count.text, "2")
            it.buttonMinus.performClick()
            assertEquals(it.count.text, "2")
            it.buttonMinus.performClick()
            it.buttonMinus.performClick()
            assertEquals(it.count.text, "0")
            it.buttonMinus.performClick()
            assertEquals(it.count.text, "0")

            it.buttonPlus.performClick()
            assertEquals(it.count.text, "1")
        }
    }
}

JVM上でActivity関連のテストができました。

既知の不具合(踏んだもの)

おわりに

なかなかv4.4のリリースありませんね・・・(2020.04.23)

happy testing !

nanoyatsu
だから見てて下さい・・・俺の・・・変身
https://nanoyatsu.hatenadiary.jp/
andfactory
Smartphone Idea Companyとして、人々の生活に「&(アンド)」を届ける。
https://andfactory.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away