| name | configuring-test-dependencies |
| description | Use this skill to wire the correct Gradle dependency matrix for Jetpack Compose UI tests. Covers `androidTestImplementation("androidx.compose.ui:ui-test-junit4")`, the `debugImplementation("androidx.compose.ui:ui-test-manifest")` requirement that makes `createComposeRule()` work, the host-test (Robolectric) trio, the accessibility add-ons (`ui-test-accessibility`, `ui-test-junit4-accessibility`), and the `TestManifestGradleConfiguration` lint warning. Use when the user reports `ActivityNotFoundException: ComponentActivity`, `createComposeRule unresolved`, `lint warning ui-test-manifest`, `Cannot find test rule`, or asks "what dependencies do I need for Compose UI tests" / "why won't my Compose test compile". |
| license | Apache-2.0. See LICENSE for complete terms. |
| metadata | {"author":"Jaewoong Eum (skydoves)","keywords":["jetpack-compose","ui-testing","gradle-dependencies","ui-test-manifest","debug-implementation","createComposeRule","ComponentActivity","ui-test-junit4","robolectric","accessibility-checks"]} |
Configuring Test Dependencies — Get the Gradle Matrix Right
Compose UI tests fail at the dependency layer in three predictable ways: the JUnit4 surface is on the wrong source set, the ui-test-manifest artifact is missing or on the wrong configuration, or the host-test trio is incomplete. This skill encodes the exact matrix and the lint warning that polices it. Subsequent skills (choosing-test-rule-vs-runtest/SKILL.md, setting-up-host-vs-device-tests/SKILL.md) assume the dependencies are correct.
When to use this skill
- The user reports
java.lang.RuntimeException: Could not launch activity within 45 seconds. Examined activities: ... androidx.activity.ComponentActivity or ActivityNotFoundException.
- The IDE flags
createComposeRule as unresolved or import androidx.compose.ui.test.junit4.createComposeRule as red.
- Lint surfaces
TestManifestGradleConfiguration (severity WARNING) on a build.gradle.kts line.
- The user wants to add Robolectric / host (JVM) tests for Compose and asks which artifacts to depend on.
- The user wants to opt into
enableAccessibilityChecks(...) and is unsure which artifact owns it.
When NOT to use this skill
- Dependencies are already correct and the user is choosing between
createComposeRule() and runComposeUiTest { } — use ./choosing-test-rule-vs-runtest/SKILL.md.
- Dependencies compile but the test runs in the wrong source set (
test/ vs androidTest/) — use ./setting-up-host-vs-device-tests/SKILL.md.
- The test compiles and runs but is flaky/timing-out — start with
../../synchronization/synchronizing-with-idle/SKILL.md.
Prerequisites
- Android Gradle Plugin with the
com.android.application or com.android.library plugin applied.
- A Compose-enabled module (the
org.jetbrains.kotlin.plugin.compose plugin or buildFeatures.compose = true).
- A JUnit4 dependency on the test classpath (Compose's
ui-test-junit4 artifact still uses JUnit4; JUnit5 requires a third-party Vintage engine bridge and is out of scope).
Workflow
dependencies {
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
debugImplementation("androidx.compose.ui:ui-test-manifest")
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")
androidTestImplementation("androidx.compose.ui:ui-test-junit4-accessibility")
androidTestImplementation("androidx.compose.ui:ui-test-accessibility")
}
The exact GA versions come from the Compose UI BOM or the developer's chosen composeVersion. Pin Robolectric independently — it does not ship in the Compose BOM.
<activity android:theme="@android:style/Theme.Material.Light.NoActionBar"
android:name="androidx.activity.ComponentActivity" android:exported="true" />
Without that entry, createComposeRule() and runComposeUiTest { } (which both default to launching androidx.activity.ComponentActivity via ActivityScenario.launch) crash at launch time. Diagnosis:
Patterns
Pattern: WRONG vs RIGHT — ui-test-manifest configuration
dependencies {
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
androidTestImplementation("androidx.compose.ui:ui-test-manifest")
}
dependencies {
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
debugImplementation("androidx.compose.ui:ui-test-manifest")
}
The lint check explicitly allows debugImplementation and warns on every other configuration. From 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"
Pattern: WRONG vs RIGHT — host-test dependencies
dependencies {
testImplementation("androidx.compose.ui:ui-test-junit4")
testImplementation("org.robolectric:robolectric:4.13")
}
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")
}
Pattern: WRONG vs RIGHT — custom Activity without its own manifest entry
@get:Rule val rule = createAndroidComposeRule<MyHostActivity>()
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity android:name=".MyHostActivity" android:exported="true" />
</application>
</manifest>
Pattern: complete sample 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
}
}
dependencies {
val composeBom = platform("androidx.compose:compose-bom:2025.06.00")
implementation(composeBom)
androidTestImplementation(composeBom)
testImplementation(composeBom)
implementation("androidx.compose.ui:ui")
implementation("androidx.activity:activity-compose")
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")
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 is required so Robolectric can read merged resources during host tests of Compose content.
Mandatory rules
- MUST put
androidx.compose.ui:ui-test-manifest on debugImplementation for instrumentation tests, and on testImplementation for host tests. Never on androidTestImplementation, implementation, or api.
- MUST keep
ui-test-junit4 on the same source set as the test that imports createComposeRule / ComposeTestRule. Mixing androidTestImplementation (instrumentation) and testImplementation (host) in the same module is fine; mixing them on the wrong test class is a compile error.
- MUST declare any non-
ComponentActivity test host (custom Activity) in the test APK manifest at src/androidTest/AndroidManifest.xml or src/debug/AndroidManifest.xml. The ui-test-manifest artifact only declares androidx.activity.ComponentActivity.
- MUST NOT remove the
TestManifestGradleConfiguration lint check via lintOptions { disable("TestManifestGradleConfiguration") }. Apply the quick fix instead — the check exists to prevent silent test failures.
- MUST NOT put
ui-test-manifest on a release configuration (releaseImplementation, implementation). The artifact is purely a test scaffold and bloats production APKs with an unwanted <activity> entry.
- PREFERRED: rely on the Compose BOM (
androidx.compose:compose-bom) so all ui-test-* artifacts share a coherent version. Robolectric is independent and pins separately.
- PREFERRED: when in doubt about which artifact owns a symbol, search
androidx/compose/ui/ui-test* paths from the corpus rather than guessing — see References.
Verification
References
- Compose testing setup (Android Developers): https://developer.android.com/develop/ui/compose/testing#setup
- Compose testing overview: https://developer.android.com/develop/ui/compose/testing
- Compose UI release notes: https://developer.android.com/jetpack/androidx/releases/compose-ui
- Compose Multiplatform testing: 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 issue definition (severity WARNING, quick-fix to debugImplementation).
compose/ui/ui-test-manifest/src/main/AndroidManifest.xml — the merged <activity android:name="androidx.activity.ComponentActivity"> entry that createComposeRule() depends on.
compose/ui/ui-test/src/androidMain/kotlin/androidx/compose/ui/test/ComposeUiTest.android.kt — runComposeUiTest launches ComponentActivity::class.java by default (lines 184-197).
compose/ui/ui-test/src/androidHostTest/kotlin/androidx/compose/ui/test/RobolectricComposeTest.kt — canonical host-test class skeleton with 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.