running-instrumented-tests-with-androidjunit4 について
AndroidJUnit4 によるインストルメンテーションテストの依存関係、Runner、アノテーション、ルールを扱うスキルガイドです。Android 開発者向けに、Test Orchestrator、実行引数、権限付与、アニメーション制御を含む起動・設定問題の解決方法をまとめています。
主な機能
- 01AndroidX Test の依存関係設定
- 02インストルメンテーション Runner の設定
- 03非推奨ではない AndroidJUnit4 の使用
- 04インストルメンテーション引数の取得
- 05Test Orchestrator の設定
- 06権限付与とアニメーション無効化
活用シーン
- 01インストルメンテーション Runner の検出失敗を修正
- 02Test Orchestrator でテストプロセスを分離
- 03アノテーションや引数でテストを絞り込む
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ skydoves/ android-testing-skills --skill running-instrumented-tests-with-androidjunit4インストール後、Claude Code で/running-instrumented-tests-with-androidjunit4を入力して読み込まれたか確認します。
詳細
AndroidJUnit4 でインストルメンテーションテストを実行する — ランナーのスタックを正しく設定する
ランナーのスタックが正しく設定されていないと、アサーションが実行される前にインストルメンテーションテストが失敗します。非推奨の AndroidJUnit4 インポート、androidTestUtil ではなく androidTestImplementation に設定されたオーケストレーター、androidx.test.platform.app.InstrumentationRegistry ではなく非推奨の androidx.test.InstrumentationRegistry などが原因です。このスキルでは、正確な依存関係マトリクス、ランナーの Gradle 設定、関連するアノテーションとルールを解説します。
このスキルを使用する場面
- IDE が
androidx.test.runner.AndroidJUnit4に@Deprecatedの警告を表示する、またはテストはコンパイルされるものの、非推奨の警告が出る場合。 am instrumentがINSTRUMENTATION_FAILED: <pkg>/androidx.test.runner.AndroidJUnitRunnerまたはTest runner not foundを返す場合。- Gradle で Test Orchestrator を設定しているのに、テストが単一のインストルメンテーションプロセスを共有している場合(オーケストレーターが警告なしに無効化されています)。
- ユーザーが
am instrument経由で-e size small/-e package com.fooを渡しても、テストがそれを無視する場合 —RunnerArgsが接続されていません。 - テストで
ACCESS_FINE_LOCATION/RECORD_AUDIOなどが必要で、ユーザーがadbから手動で権限を付与している場合。 - API 26 未満でテストをスキップしたくて、アノテーションを探している場合。
このスキルを使用しない場面
- ユーザーが
Activityを起動したり、ライフサイクルを操作したりする場合 —../../scenarios/launching-activities-with-activityscenario/SKILL.mdを参照してください。 - ユーザーが View を操作する場合 —
../../espresso/writing-espresso-tests/SKILL.mdを参照してください。 - ユーザーがシステム UI や別のアプリを操作する場合 —
../../uiautomator/cross-app-tests-with-uiautomator/SKILL.mdを参照してください。 - ユーザーが JVM(Robolectric / 純粋な JUnit)テストを実行する場合 —
../../../jvm-tests/runner/configuring-junit4-on-android/SKILL.mdを参照してください。 - ユーザーが何をテストするかを検討している段階の場合 —
../../../fundamentals/strategies/applying-testing-strategies/SKILL.mdを参照してください。
前提条件
- Android Gradle Plugin モジュール(
com.android.applicationまたはcom.android.library)。 - ディスク上に
src/androidTest/ソースセットがあること(./gradlew :module:connectedDebugAndroidTestが解決される必要があります)。 - エミュレーターまたは実機(あるいは Firebase Test Lab / マネージドデバイス)— ランナーは JVM 上では実行できません。
- テストのクラスパスに JUnit 4 が含まれていること(
junit:junit:4.13.2)。JUnit 5 には Vintage エンジンブリッジが必要ですが、ここでは対象外です。
ワークフロー
- 1. AndroidX Test のアーティファクトを
androidTestImplementationに固定します。 これらはdocs/CORPUS.mdH.1 に記載された、2026 年時点の標準的な GA バージョンです。
dependencies {
androidTestImplementation("androidx.test:core:1.7.0")
androidTestImplementation("androidx.test:runner:1.7.0")
androidTestImplementation("androidx.test:rules:1.7.0")
androidTestImplementation("androidx.test.ext:junit:1.3.0")
androidTestImplementation("androidx.test.ext:junit-ktx:1.3.0")
androidTestImplementation("androidx.test.ext:truth:1.7.0")
}
androidx.test.ext:junit は、非推奨ではない AndroidJUnit4 ランナーと 非推奨ではない ActivityScenarioRule を提供するアーティファクトです。androidx.test:runner にも従来の AndroidJUnit4(非推奨)が含まれています — こちらからはインポートしないでください。tasks/research/R1-androidx-test-core.md の 481-490 行を参照してください。
- 2. モジュールの
android.defaultConfigでtestInstrumentationRunnerを設定します。 ランナーの FQCN はandroidx.test.runner.AndroidJUnitRunnerです — これはランナーの クラス であり、非推奨のAndroidJUnit4テストランナーアノテーション とは異なることに注意してください。tasks/research/R1-androidx-test-core.mdの 270-289 行より。
android {
defaultConfig {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
// Optional: pass `-e key value` args to every run via Gradle
testInstrumentationRunnerArguments["clearPackageData"] = "true"
}
testOptions {
animationsDisabled = true // hermetic — see Pattern below
}
}
- 3.
androidx.test.ext.junit.runnersの@RunWith(AndroidJUnit4::class)でテストクラスにアノテーションを付けます。 正しいインポートはこれだけです。
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class LoginActivityTest {
@Test fun loginSucceeds() { /* ... */ }
}
非推奨の androidx.test.runner.AndroidJUnit4 は、runner-1.7.0/androidx/test/runner/AndroidJUnit4.java:43-44 で @Deprecated として宣言されています。実行時には引き続き動作しますが、IDE が警告を表示し、コードモッドによる置き換えの対象になります。
- 4.
androidx.test.platform.app.InstrumentationRegistryを使ってインストルメンテーション引数を読み取ります。 従来のandroidx.test.InstrumentationRegistry(platform.appを含まないもの)は@Deprecatedおよび@InlineMeとして宣言され、標準クラスへの移行が促されています —tasks/research/R1-androidx-test-core.mdの 142-153 行を参照してください。
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.core.app.ApplicationProvider
val instrumentation = InstrumentationRegistry.getInstrumentation()
val args: Bundle = InstrumentationRegistry.getArguments() // -e key value extras
val targetContext: Context = ApplicationProvider.getApplicationContext()
val testContext: Context = instrumentation.context // package context of the test APK
InstrumentationRegistry.getArguments() は、am instrument -e key value で渡された -e のキーと値のペアを公開します。例:-e size small -e numShards 4。サポート対象キーの正式な一覧は、runner-1.7.0/androidx/test/internal/runner/RunnerArgs.java の54~99行目にあります(tasks/research/R1-androidx-test-core.md の295~336行目を参照)。
- 5.
androidx.test.filtersの@SmallTest/@MediumTest/@LargeTestを使ってテストにアノテーションを付けます。am instrument -e size smallと組み合わせることで、実行時間の範囲でフィルタリングできます。パッケージのKDocによると、SmallTestは200ms以下、MediumTestは1000ms以下、LargeTestは1000ms超です。同じパッケージにあるアノテーション:@FlakyTest、@RequiresDevice、@Suppress。
import androidx.test.filters.SmallTest
import androidx.test.filters.SdkSuppress
@RunWith(AndroidJUnit4::class)
@SmallTest
class LoginViewModelTest { /* ... */ }
@Test
@SdkSuppress(minSdkVersion = 26)
fun usesApi26OnlyApi() { /* ... */ }
@SdkSuppress(minSdkVersion, maxSdkVersion, excludedSdks, codeName) は runner-1.7.0/androidx/test/filters/SdkSuppress.java:39-58 にあります。API範囲外のテストは失敗ではなく、スキップ(仮定の失敗、終了コード -4)になります。
- 6. Test Orchestrator は
androidTestImplementationではなく、androidTestUtilに追加します。 これはランナーの設定で最もよくある単独の設定ミスです。Test Orchestrator は各@Testを専用のインストルメンテーションプロセスで実行するため、クラッシュの影響がそのテストだけに限定されます。テスト間でclearPackageDataを実行することもできます。
dependencies {
androidTestUtil("androidx.test:orchestrator:1.6.1") // installs orchestrator APK on device
androidTestUtil("androidx.test:services:1.6.0") // required for clearPackageData
}
android {
testOptions {
execution = "ANDROIDX_TEST_ORCHESTRATOR"
}
defaultConfig {
testInstrumentationRunnerArguments["clearPackageData"] = "true"
}
}
androidTestUtil は、テスト実行前にデバイスへヘルパーAPKをインストールする、AGPの特別な構成です。Orchestratorを androidTestImplementation に指定してもコンパイルは通りますが、何も起きず、テストは引き続き単一の共有プロセスで実行されます。tasks/research/R1-androidx-test-core.md の683~687行目を参照してください。
- 7.
adb shell pm grantの代わりにGrantPermissionRule.grant(...)を使って実行時権限を付与します。 このルールはandroidx.test:rulesに含まれており、テストクラスの実行中に権限を付与します。
import androidx.test.rule.GrantPermissionRule
import org.junit.Rule
@get:Rule
val permissionRule: GrantPermissionRule = GrantPermissionRule.grant(
android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.RECORD_AUDIO,
)
このルールは rules-1.7.0/androidx/test/rule/GrantPermissionRule.java に実装されています。API 23以降では UiAutomation.grantRuntimePermission を使用します。古いデバイスでは、権限をマニフェストですでに付与しておく必要があります(このルールは何もしません)。
-
8. 再現性の高いテスト実行ではアニメーションを無効にします。
testOptions { animationsDisabled = true }を指定すると、テスト実行中はwindow_animation_scale、transition_animation_scale、animator_duration_scaleが0に設定され、終了処理時に以前の値へ戻されます。これを設定しないと、タップによるフォーカス、リップル、Activityの遷移とアサーションが競合します。 -
9. 複数の
@Ruleの順序を@Rule(order = N)で指定します(任意)。 順序の値が小さいほど、外側で評価されます。Hiltでは@HiltAndroidRuleをorder = 0にする必要があります。
@get:Rule(order = 0) val hiltRule = HiltAndroidRule(this)
@get:Rule(order = 1) val activityRule = ActivityScenarioRule(LoginActivity::class.java)
- 10. 実行します。 ホストから次のコマンドを実行します。
./gradlew :app:connectedDebugAndroidTest
# or via adb directly:
adb shell am instrument -w -r \
-e size small \
-e clearPackageData true \
com.example.app.test/androidx.test.runner.AndroidJUnitRunner
終了コードを正しく取得するには、-w(待機)が必須です。これがないと、テストが失敗しても $? は 0 になります。docs/CORPUS.md のI.5を参照してください。
パターン
パターン:誤りと正しい例 — AndroidJUnit4 のインポート
// WRONG
import androidx.test.runner.AndroidJUnit4 // @Deprecated since androidx.test:runner 1.x
@RunWith(AndroidJUnit4::class)
class FooTest
// WRONG because: this class is @Deprecated at runner-1.7.0/.../AndroidJUnit4.java:43-44.
// The IDE flags it; codemods replace it; the doc explicitly redirects to ext.junit.
// RIGHT
import androidx.test.ext.junit.runners.AndroidJUnit4
@RunWith(AndroidJUnit4::class)
class FooTest
パターン:誤りと正しい例 — InstrumentationRegistry のインポート
// WRONG
import androidx.test.InstrumentationRegistry // @Deprecated, every member @InlineMe'd
val ctx = InstrumentationRegistry.getTargetContext() // returns target package context, NOT the application
// WRONG because: monitor-1.8.0/androidx/test/InstrumentationRegistry.java:34 is @Deprecated.
// Use androidx.test.platform.app.InstrumentationRegistry + ApplicationProvider.
// RIGHT
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.core.app.ApplicationProvider
val instrumentation = InstrumentationRegistry.getInstrumentation()
val ctx: Context = ApplicationProvider.getApplicationContext()
パターン:誤りと正しい例 — Test Orchestrator の設定(最もよくある設定ミス)
// WRONG
dependencies {
androidTestImplementation("androidx.test:orchestrator:1.6.1")
}
android.testOptions.execution = "ANDROIDX_TEST_ORCHESTRATOR"
// WRONG because: orchestrator must be installed as a separate APK on the device.
// `androidTestImplementation` puts it on the test APK classpath instead, where it does
// nothing. Tests still run in one shared process. No error, just silent inactivation.
// RIGHT
dependencies {
androidTestUtil("androidx.test:orchestrator:1.6.1")
androidTestUtil("androidx.test:services:1.6.0") // required for clearPackageData
}
android.testOptions.execution = "ANDROIDX_TEST_ORCHESTRATOR"
パターン:RunnerArgs を使った実行時のテストフィルタリング
# Run a single method
adb shell am instrument -w -r \
-e class com.example.LoginActivityTest#loginSucceeds \
com.example.app.test/androidx.test.runner.AndroidJUnitRunner
# Filter by size annotation
adb shell am instrument -w -r -e size small com.example.app.test/androidx.test.runner.AndroidJUnitRunner
# Shard across N runners (CI fan-out)
adb shell am instrument -w -r -e numShards 4 -e shardIndex 0 \
com.example.app.test/androidx.test.runner.AndroidJUnitRunner
サポート対象の -e キーの一覧は、runner-1.7.0/androidx/test/internal/runner/RunnerArgs.java:54-99 にあります(class、package、notClass、size、annotation、notAnnotation、numShards、shardIndex、clearPackageData、coverage、debug、listener など)。テスト内でこれらを取得するには、InstrumentationRegistry.getArguments() を読み取ります。
必須ルール
- 必須:
@RunWith(...)にはandroidx.test.ext.junit.runners.AndroidJUnit4を使用してください。androidx.test.runner.AndroidJUnit4形式は@Deprecatedです。 - 必須:
androidx.test.platform.app.InstrumentationRegistryを使用してください。androidx.test.InstrumentationRegistryは@Deprecatedです。 - 必須:
androidx.test:orchestratorはandroidTestUtilに指定し、androidTestImplementationには指定しないでください。誤った構成に指定しても、エラーが出ずに失敗します。 - 必須:
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"を設定してください(ランナーの クラス は非推奨ではありません。非推奨なのはテストランナーの アノテーション のみです)。 - 必須:
am instrumentに-wを渡し、終了コードにテスト結果が反映されるようにしてください。これを付けない場合、$?は意味を持ちません。 - 禁止: インストルメンテーションのライフサイクル(
onCreate、onStart)を待つためにThread.sleepを呼び出さないでください。ActivityScenario.moveToState(../../scenarios/launching-activities-with-activityscenario/SKILL.mdを参照)またはIdlingResourceを使用してください。 - 禁止: テスト内から
adb shell pm grantを使って権限を付与しないでください。テストクラスの範囲内で権限を付与し、適切に元に戻すために、GrantPermissionRule.grant(...)を使用してください。 - 禁止:
@Rule public ActivityTestRuleを使用しないでください。これは@Deprecatedです。@get:Rule val rule = ActivityScenarioRule(...)を使用してください。 - 推奨: CI のシャードでサイズによるフィルタリングができるよう、すべてのインストルメンテーションテストクラスに
@SmallTest、@MediumTest、または@LargeTestを付けてください。 - 推奨: 個々のテストでは不要に見える場合でも、
testOptions.animationsDisabled = trueを設定してください。リップルやトランジションの不安定さは、気付かないうちに無関係なテストを破損させます。
検証
-
./gradlew :<module>:connectedDebugAndroidTestの実行時に、Test runner not foundやINSTRUMENTATION_FAILEDが発生しない。 - ソースファイルに
androidx.test.runner.AndroidJUnit4またはandroidx.test.InstrumentationRegistry(旧パス)のインポートがない。 -
grep -r "androidTestImplementation.*orchestrator" build.gradle*の結果が空である。orchestrator はandroidTestUtilに指定します。 -
adb shell am instrument -w -r -e size small <pkg>.test/androidx.test.runner.AndroidJUnitRunnerは、テスト失敗時にゼロ以外の終了コードを返す。 - orchestrator が有効な場合、
adb logcat | grep AndroidTestOrchestratorにテストごとのプロセス起動が表示される。 - モジュールの
androidブロックでtestOptions.animationsDisabled = trueが設定されている。 - テストに必要なランタイム権限には、手動の
adb shell pm grantではなく、@get:Rule val rule = GrantPermissionRule.grant(...)が設定されている。
参考資料
- Android Developers — AndroidJUnitRunner の概要:https://developer.android.com/training/testing/instrumented-tests/androidx-test-libraries/runner
- Android Developers — Test Orchestrator:https://developer.android.com/training/testing/instrumented-tests/androidx-test-libraries/runner#use-android
- AndroidX Test のリリースノート:https://developer.android.com/jetpack/androidx/releases/test
runner-1.7.0/androidx/test/runner/AndroidJUnit4.javaの41~44行目 —@Deprecated public final class AndroidJUnit4 extends Runner。junit-1.3.0/androidx/test/ext/junit/runners/AndroidJUnit4.javaの49行目 — 現在の非推奨ではないランナー。JVM 上では Robolectric に、デバイス上ではAndroidJUnit4ClassRunnerに処理を委譲します。runner-1.7.0/androidx/test/runner/AndroidJUnitRunner.javaの270~372行目 —am instrumentが呼び出すランナークラス。ライフサイクルと Orchestrator の待機ロジックが記載されています。runner-1.7.0/androidx/test/internal/runner/RunnerArgs.javaの54~99行目 — ランナーが受け付けるすべての-eキーの正式な一覧です。monitor-1.8.0/androidx/test/InstrumentationRegistry.javaの34行目 —@Deprecatedの旧レジストリ。すべてのメンバーに、platform.app 形式への@InlineMeが付与されています。monitor-1.8.0/androidx/test/platform/app/InstrumentationRegistry.java— 現在の正式なレジストリです。rules-1.7.0/androidx/test/rule/GrantPermissionRule.javaの1~100行目 —static GrantPermissionRule grant(String...)。runner-1.7.0/androidx/test/filters/SdkSuppress.javaの39~58行目 —minSdkVersion/maxSdkVersion/excludedSdks/codeName。tasks/research/R1-androidx-test-core.md— ランナーとテストコアの詳細な解説(ランナーについては269~740行目、2種類のAndroidJUnit4の混同については481~490行目)。docs/CORPUS.mdの Section H — インストルメンテーションライブラリの座標と非推奨化の表。- 関連スキル:
../../managed-devices/running-tests-on-gradle-managed-devices/SKILL.md— Gradle が用意して起動・終了するエミュレーターでこれらのテストを実行します(CI で再現可能です)。 - 関連セット:
../../../adb/tests/running-instrumented-tests-via-adb/SKILL.md—adb shell am instrument -w -rでランナーを直接呼び出します。 - 関連セット:
../../../platform/legacy/migrating-from-android-test-classes/SKILL.md— モジュールが引き続き旧android.test.*クラスまたはInstrumentationTestRunnerを使用している場合は、まずこのランナースタックに移行してください。