Instrumented Unit Test内部でのActivityの起動（UnitTest探求記4）

Unit Test 探求記は、unit test に関してまったりと実験しつつその過程を綴ってみるというものです。

# 今回のお題
Instrumented Unit Test 内部にて Activity を起動してみます。

# 依存関係の追加

## ◆ build.gradle.kts

`androidx.test.core.app.launchActivity` を利用するために `androidx.test:core-ktx` への依存を追加しています。

[source](https://github.com/beyondseeker/of-commons/blob/8ced68c123625f48e4e59d801f642d130c80ed93/android/build.gradle.kts)

```kotlin:追加差分
dependencies {
    // for androidx.test.core.app.launchActivity
    androidTestImplementation("androidx.test:core-ktx:1.3.0")
}
```

# UnitTest と Activity の追加

## ◆ GetAttrInstrumentedTest.kt

UnitTest とテスト用の Activity を同一ファイルに既述しています。

```kotlin
package com.objectfanatics.commons.android.view

import android.app.Activity
import android.util.Log
import androidx.test.core.app.launchActivity
import androidx.test.ext.junit.rules.ActivityScenarioRule
import org.junit.Rule
import org.junit.Test

class GetAttrInstrumentedTest {
    @get:Rule
    var activityRule: ActivityScenarioRule<GetAttrInstrumentedTestActivity> =
        ActivityScenarioRule(GetAttrInstrumentedTestActivity::class.java)

    @Test
    fun getXxxAttrTest() {
        // Activity を起動
        val scenario = launchActivity<GetAttrInstrumentedTestActivity>()

        // 起動した Activity の simpleName をログ出力してみる
        scenario.onActivity { activity ->
            Log.e(
                "GetAttrInstrumentedTestActivity",
                "activity.javaClass.simpleName = ${activity.javaClass.simpleName}"
            )
        }
    }
}

class GetAttrInstrumentedTestActivity : Activity()
```

## ◆ AndroidManifest.xml

Activity を AndroidManifest.xml に登録します。

```xml
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.objectfanatics.commons.android">
    <application>
        <activity android:name=".view.GetAttrInstrumentedTestActivity"/>
   </application>
</manifest>
```

この登録を行わないと、以下のように怒られます。

```
java.lang.RuntimeException: Unable to resolve activity for: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.objectfanatics.commons.android.test/com.objectfanatics.commons.android.view.GetAttrInstrumentedTestActivity }
at androidx.test.core.app.InstrumentationActivityInvoker.startActivity(InstrumentationActivityInvoker.java:387)
at androidx.test.core.app.InstrumentationActivityInvoker.startActivity(InstrumentationActivityInvoker.java:416)
at androidx.test.core.app.ActivityScenario.launchInternal(ActivityScenario.java:265)
at androidx.test.core.app.ActivityScenario.launch(ActivityScenario.java:195)
at androidx.test.ext.junit.rules.ActivityScenarioRule.lambda$new$0$ActivityScenarioRule(ActivityScenarioRule.java:68)
at androidx.test.ext.junit.rules.ActivityScenarioRule$$Lambda$0.get(Unknown Source:2)
at androidx.test.ext.junit.rules.ActivityScenarioRule.before(ActivityScenarioRule.java:82)
at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:46)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:392)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2081)
```

# テスト結果
以下のようにテストが実行され、起動された Activity の instance から取得した情報がログ出力されました。

```
Testing started at 6:48 ...

08/27 06:48:36: Launching 'GetAttrInstrumentedT...' on asus ASUS_X00PD.
Running tests

$ adb shell am instrument -w -r    -e debug false -e class 'com.objectfanatics.commons.android.view.GetAttrInstrumentedTest' com.objectfanatics.commons.android.test/androidx.test.runner.AndroidJUnitRunner

Started running tests

Connected to process 26907 on device 'asus-asus_x00pd-JBAXZN003806L6E'.
Tests ran to completion.
```

```:logcat
E/GetAttrInstrumentedTestActivity: activity.javaClass.simpleName = GetAttrInstrumentedTestActivity
```

# まとめ
今回は、instrumented unit test 内で Activity の起動と、Activity の instance へのアクセスを行いました。