configuring-test-dependencies について
Android Compose プロジェクトの保守担当者向けに、デバイステストと Robolectric のホストテストで必要な Gradle 依存関係と設定先を説明するスキルです。テスト用マニフェスト、Lint 警告、アクセシビリティチェックの依存関係も扱います。
主な機能
- 01デバイスとホストのテスト依存関係を区別
- 02ui-test-manifest の設定先を指定
- 03ComponentActivity の起動要件を解説
- 04TestManifestGradleConfiguration 警告を説明
- 05アクセシビリティチェックの依存関係を提示
活用シーン
- 01Compose テストの Activity 起動失敗を修正
- 02createComposeRule が解決されない問題への対応
- 03Robolectric テストの依存関係を補完
- 04TestManifestGradleConfiguration 警告の調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ skydoves/ android-testing-skills --skill configuring-test-dependenciesインストール後、Claude Code で/configuring-test-dependenciesを入力して読み込まれたか確認します。
詳細
テスト依存関係の設定 — Gradle のマトリックスを正しく構成する
Compose UI テストは、依存関係レイヤーで予測可能な 3 つの原因により失敗します。JUnit4 の構成が誤ったソースセットにある、ui-test-manifest アーティファクトが不足しているか誤った構成にある、またはホストテスト用の 3 つの依存関係が揃っていない、のいずれかです。このスキルでは、正確なマトリックスと、それをチェックする lint 警告を定義します。後続のスキル(choosing-test-rule-vs-runtest/SKILL.md、setting-up-host-vs-device-tests/SKILL.md)では、依存関係が正しく設定されていることを前提とします。
このスキルを使う場面
- ユーザーから
java.lang.RuntimeException: Could not launch activity within 45 seconds. Examined activities: ... androidx.activity.ComponentActivityまたはActivityNotFoundExceptionが報告された場合。 - IDE で
createComposeRuleが未解決として示されるか、import androidx.compose.ui.test.junit4.createComposeRuleが赤く表示される場合。 - lint が
build.gradle.ktsの行にTestManifestGradleConfiguration(重大度 WARNING)を表示する場合。 - ユーザーが Compose の Robolectric/ホスト(JVM)テストを追加しようとしており、依存させるアーティファクトを尋ねている場合。
- ユーザーが
enableAccessibilityChecks(...)を使いたいものの、どのアーティファクトに含まれているか分からない場合。
このスキルを使わない場面
- 依存関係はすでに正しく、ユーザーが
createComposeRule()とrunComposeUiTest { }のどちらを使うか選んでいる場合は、./choosing-test-rule-vs-runtest/SKILL.mdを使います。 - 依存関係はコンパイルできるものの、テストが誤ったソースセット(
test/とandroidTest/)で実行される場合は、./setting-up-host-vs-device-tests/SKILL.mdを使います。 - テストはコンパイル・実行できるものの、不安定またはタイムアウトする場合は、
../../synchronization/synchronizing-with-idle/SKILL.mdから始めます。
前提条件
com.android.applicationまたはcom.android.libraryプラグインが適用された Android Gradle Plugin。- Compose が有効なモジュール(
org.jetbrains.kotlin.plugin.composeプラグイン、またはbuildFeatures.compose = true)。 - テストクラスパスに JUnit4 依存関係があること(Compose の
ui-test-junit4アーティファクトは引き続き JUnit4 を使用します。JUnit5 にはサードパーティ製の Vintage エンジンブリッジが必要ですが、ここでは対象外です)。
ワークフロー
-
1. モジュールに必要なテストの種類を決めます。 一般的な Compose 機能モジュールでは、スクリーンショット/RenderThread/フルスタックのテストを行うインストルメンテーションテスト、高速なロジック検証を行うホスト(Robolectric)テスト、そして
createComposeRule()用のマニフェストヘルパーの 3 つが必要です。ステップ 2 のマトリックスから選びます。 -
2. 正しい構成に依存関係を追加します。 モジュールの
build.gradle.ktsに次の内容をコピーします。
dependencies {
// --- Instrumentation tests (src/androidTest/) ---
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
// MUST be debugImplementation (see Pattern: WRONG vs RIGHT for ui-test-manifest below)
debugImplementation("androidx.compose.ui:ui-test-manifest")
// --- Host tests with Robolectric (src/test/) ---
testImplementation("androidx.compose.ui:ui-test") // common test API
testImplementation("androidx.compose.ui:ui-test-junit4") // ComposeTestRule + createComposeRule
testImplementation("androidx.compose.ui:ui-test-manifest") // ComponentActivity manifest entry
testImplementation("org.robolectric:robolectric:4.13") // pin a version
// --- Optional: accessibility validation (API 34+) ---
androidTestImplementation("androidx.compose.ui:ui-test-junit4-accessibility")
// Or, when using runComposeUiTest { } (no Rule):
androidTestImplementation("androidx.compose.ui:ui-test-accessibility")
}
正確な GA バージョンは Compose UI BOM または開発者が選んだ composeVersion に従います。Robolectric は Compose BOM に含まれないため、個別にバージョンを固定します。
- 3. テストが
androidx.activity.ComponentActivityに対するActivityNotFoundExceptionで失敗する場合、99 パーセントはマニフェストアーティファクトが原因です。 このアーティファクトは単一ファイルのライブラリで、compose/ui/ui-test-manifest/src/main/AndroidManifest.xmlにある次の<activity>エントリーをテスト APK のマニフェストにマージします。
<activity android:theme="@android:style/Theme.Material.Light.NoActionBar"
android:name="androidx.activity.ComponentActivity" android:exported="true" />
このエントリーがないと、createComposeRule() と runComposeUiTest { } はどちらもデフォルトで ActivityScenario.launch を介して androidx.activity.ComponentActivity を起動するため、起動時にクラッシュします。原因を特定するには、次を確認します。
-
ui-test-manifestが依存関係の一覧に含まれていることを確認します。 -
debugImplementation(ホストテストの場合はtestImplementation)に設定されていることを確認します。androidTestImplementationに設定されている場合、lint は警告を出しますが、Gradle は依存関係を引き続き組み込みます。ただし、AGP のバリアントモデルではdebugとandroidTestのマニフェストマージが意図的に分離されています。そのため、androidTestImplementationに設定しても、インストルメンテーションテストの実行対象となるホスト APK に<activity>はマージされません。この lint チェックは、まさにこれを検出するためのものです。 -
4.
TestManifestGradleConfigurationの lint 警告に対処するため、依存関係をdebugImplementationに移動します。 lint チェックはcompose/ui/ui-test-manifest-lint/src/main/java/androidx/compose/ui/test/manifest/lint/GradleDebugConfigurationDetector.ktにあります。重大度はSeverity.WARNINGで、クイックフィックスでは設定名をdebugImplementationに置き換えます。このチェックは、成果物がimplementation、api、compileOnly、runtimeOnly、androidTestImplementation、testImplementation、またはandroid/test/サポートされている設定名のいずれかで始まるカスタム設定に指定されている場合に発生します。 -
5. マニフェストの成果物が本当に必要かどうかを判断します。 次の場合に必要です。
- テストで
createComposeRule()を使用する(型パラメーターなし — デフォルトはandroidx.activity.ComponentActivity)。 - テストで
runComposeUiTest { }を使用する(型パラメーターなし — 同じデフォルト)。
次の場合には不要です。
- テストで
createAndroidComposeRule<MyActivity>()を使用し、開発者自身がsrc/androidTest/AndroidManifest.xml(またはsrc/debug/AndroidManifest.xml)に<activity android:name=".MyActivity" .../>を宣言している。 - テストで
createEmptyComposeRule()を使用し、本番マニフェストですでに宣言されている Activity に対して独自のActivityScenarioを起動する。
- テストで
-
6. ホストテストでは、3 つすべての成果物が
testImplementationに指定されていることを確認します。 Robolectric は JVM の Looper を制御しますが、Compose のアイドリングおよびクロックの実装にはui-test(共通)とui-test-junit4(ComposeTestRuleインターフェースおよびcreateComposeRuleの実装)の両方が必要です。ui-test-manifestがtestImplementationに指定されていないと、同じマニフェストを解析するため、Robolectric は同じActivityNotFoundExceptionをスローします。androidx 自体のホストソースセットでもこの設定を使用しています —compose/ui/ui-test/src/androidHostTest/kotlin/androidx/compose/ui/test/RobolectricComposeTest.ktを参照してください。 -
7. 開発者が
enableAccessibilityChecksを呼び出す予定がある場合にのみ、アクセシビリティの成果物を追加します。 これらは JUnit4 のサーフェスとは独立しています。ui-test-accessibilityはComposeUiTest(runComposeUiTest { }のレシーバー)を拡張します。ui-test-junit4-accessibilityはComposeTestRule/AndroidComposeTestRuleを拡張します。 どちらも@RequiresApi(34)で、Robolectric では何も行いません(Build.FINGERPRINT == "robolectric"の場合、警告がログに記録されます)— 詳細は、このリポジトリのアクセシビリティスキルを参照してください。
-
8. Gradle を同期して、テストを再実行します。
./gradlew :app:connectedDebugAndroidTest(インストルメンテーション)または./gradlew :app:testDebugUnitTest(ホスト)をクリーンな状態で実行すると、コンパイルされ、ComponentActivityが見つかるはずです。
パターン
パターン:誤りと正しい例 — ui-test-manifest の設定
// WRONG
dependencies {
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
androidTestImplementation("androidx.compose.ui:ui-test-manifest")
}
// WRONG because: lint emits TestManifestGradleConfiguration (WARNING) and the manifest
// merger does not pull the <activity> entry into the merged APK manifest from the
// androidTest source set. createComposeRule() crashes with ActivityNotFoundException.
// RIGHT
dependencies {
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
debugImplementation("androidx.compose.ui:ui-test-manifest")
}
lint チェックでは debugImplementation のみが明示的に許可され、それ以外のすべての設定に警告が出ます。GradleDebugConfigurationDetector.kt より:
"The androidx.compose.ui:ui-test-manifest dependency is needed for launching a
Compose host, such as with createComposeRule. However, it only needs to be present
in testing configurations therefore use this dependency with the debugImplementation
configuration"
パターン:誤りと正しい例 — ホストテストの依存関係
// WRONG
dependencies {
testImplementation("androidx.compose.ui:ui-test-junit4")
testImplementation("org.robolectric:robolectric:4.13")
// Missing ui-test-manifest -> ActivityNotFoundException at runComposeUiTest launch
// Missing ui-test -> linker errors on common test API symbols
}
// RIGHT
dependencies {
testImplementation("androidx.compose.ui:ui-test")
testImplementation("androidx.compose.ui:ui-test-junit4")
testImplementation("androidx.compose.ui:ui-test-manifest")
testImplementation("org.robolectric:robolectric:4.13")
}
パターン:誤りと正しい例 — 独自のマニフェストエントリーがないカスタム Activity
// WRONG
@get:Rule val rule = createAndroidComposeRule<MyHostActivity>()
// build.gradle.kts has only debugImplementation("androidx.compose.ui:ui-test-manifest")
// and src/androidTest/AndroidManifest.xml does NOT declare MyHostActivity.
// WRONG because: ui-test-manifest only declares ComponentActivity. Custom activities
// must be declared in the test APK manifest by the developer. Result: ActivityNotFoundException.
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity android:name=".MyHostActivity" android:exported="true" />
</application>
</manifest>
パターン:build.gradle.kts の完全なサンプル
plugins {
id("com.android.library")
id("org.jetbrains.kotlin.android")
id("org.jetbrains.kotlin.plugin.compose")
}
android {
namespace = "com.example.feature"
compileSdk = 35
defaultConfig {
minSdk = 23
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildFeatures { compose = true }
testOptions {
unitTests.isIncludeAndroidResources = true // required for Robolectric + Compose
}
}
dependencies {
val composeBom = platform("androidx.compose:compose-bom:2025.06.00")
implementation(composeBom)
androidTestImplementation(composeBom)
testImplementation(composeBom)
// Production
implementation("androidx.compose.ui:ui")
implementation("androidx.activity:activity-compose")
// Instrumentation
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
debugImplementation("androidx.compose.ui:ui-test-manifest")
androidTestImplementation("androidx.test.ext:junit:1.2.1")
androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")
// Host (Robolectric)
testImplementation("androidx.compose.ui:ui-test")
testImplementation("androidx.compose.ui:ui-test-junit4")
testImplementation("androidx.compose.ui:ui-test-manifest")
testImplementation("org.robolectric:robolectric:4.13")
testImplementation("junit:junit:4.13.2")
}
testOptions.unitTests.isIncludeAndroidResources = true は、Compose コンテンツのホストテスト中に Robolectric がマージ済みリソースを読み取るために必要です。
必須ルール
- 必ず、インストルメンテーションテストでは
androidx.compose.ui:ui-test-manifestをdebugImplementationに、ホストテストではtestImplementationに指定してください。androidTestImplementation、implementation、apiには指定しないでください。 - 必ず、
createComposeRule/ComposeTestRuleをインポートするテストと同じソースセットにui-test-junit4を指定してください。同じモジュール内でandroidTestImplementation(インストルメンテーション)とtestImplementation(ホスト)を併用しても問題ありませんが、誤ったテストクラスに指定するとコンパイルエラーになります。 - 必ず、
ComponentActivity以外のテストホスト(カスタム Activity)を、src/androidTest/AndroidManifest.xmlまたはsrc/debug/AndroidManifest.xmlのテスト APK マニフェストで宣言してください。ui-test-manifestアーティファクトが宣言するのはandroidx.activity.ComponentActivityのみです。 lintOptions { disable("TestManifestGradleConfiguration") }でTestManifestGradleConfigurationlint チェックを削除してはいけません。代わりにクイックフィックスを適用してください。このチェックは、テストが気付かないうちに失敗するのを防ぐためのものです。- リリース構成(
releaseImplementation、implementation)にui-test-manifestを指定してはいけません。このアーティファクトはテスト用の足場にすぎず、不要な<activity>エントリを本番 APK に含めてサイズを増やします。 - 推奨: Compose BOM(
androidx.compose:compose-bom)を利用し、すべてのui-test-*アーティファクトのバージョンに一貫性を持たせてください。Robolectric は独立しており、別途バージョンを固定します。 - 推奨: シンボルがどのアーティファクトに属するか判断に迷ったら、推測するのではなく、コーパスから
androidx/compose/ui/ui-test*パスを検索してください。参考資料を参照してください。
検証
-
./gradlew :<module>:connectedDebugAndroidTestがコンパイルされ、androidx.activity.ComponentActivityに対するActivityNotFoundExceptionを起こさず実行される。 -
./gradlew :<module>:lintでTestManifestGradleConfigurationが報告されない。 - ホストテストで
runComposeUiTest { }またはcreateComposeRule()を使用しても、./gradlew :<module>:testDebugUnitTestがコンパイルされる。 - 依存関係ブロックで、
androidTestImplementation(インストルメンテーション)、debugImplementation(マニフェスト)、testImplementation(ホスト用の3つ)が明確に分けられている。 - 開発者がアクセシビリティ関連のアーティファクトを追加した場合、インストルメンテーションテスト内で
enableAccessibilityChecks(...)がコンパイル時に解決される。 - テスト APK のマニフェストに
<activity android:name="androidx.activity.ComponentActivity"/>のエントリが1つだけ含まれている(./gradlew :app:processDebugAndroidTestManifestを実行し、build/intermediates/.../AndroidManifest.xmlを確認する)。
参考資料
- Compose のテスト設定(Android Developers):https://developer.android.com/develop/ui/compose/testing#setup
- Compose のテスト概要:https://developer.android.com/develop/ui/compose/testing
- Compose UI リリースノート:https://developer.android.com/jetpack/androidx/releases/compose-ui
- Compose Multiplatform のテスト:https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-test.html
compose/ui/ui-test-manifest-lint/src/main/java/androidx/compose/ui/test/manifest/lint/GradleDebugConfigurationDetector.kt—TestManifestGradleConfigurationの問題定義(重大度 WARNING、debugImplementationに変更するクイックフィックス)。compose/ui/ui-test-manifest/src/main/AndroidManifest.xml—createComposeRule()が依存する、マージ対象の<activity android:name="androidx.activity.ComponentActivity">エントリ。compose/ui/ui-test/src/androidMain/kotlin/androidx/compose/ui/test/ComposeUiTest.android.kt—runComposeUiTestはデフォルトでComponentActivity::class.javaを起動します(184~197 行目)。compose/ui/ui-test/src/androidHostTest/kotlin/androidx/compose/ui/test/RobolectricComposeTest.kt— Robolectric を使うホストテストクラスの基本構成(@RunWith(AndroidJUnit4::class) @Config(minSdk = RobolectricMinSdk))。compose/ui/ui-test/src/androidHostTest/kotlin/androidx/compose/ui/test/Constants.kt—internal const val RobolectricMinSdk = 23。