On device/emulator run only what the JVM doesn't prove: Compose/Espresso, navigation, intents, permissions. ViewModel unit: android-unit-testing.
Stack and scope
| Item | Role |
|---|---|
| androidTest | Instrumented source set |
| Compose Test | createAndroidComposeRule / semantics |
| Espresso | Legacy XML Views |
| HiltAndroidRule | Test DI if the app uses Hilt |
| UI Automator | Only cross-app / system |
Don't instrument a pure use case. Prefer test/ until it hurts.
What to prioritize
- Happy path of critical screen (login, checkout, permission)
- Visible empty/error states
- Navigation (back stack)
- Basic accessibility (contentDescription on targets)
- UI bug regression
Layout
src/androidTest/kotlin/.../
fakes/
screens/ # robots ou page objects
FooScreenTest.kt
- One class per flow. Robots reduce coupling to semantics.
testInstrumentationRunnerof the project (Hilt runner if Hilt).
Compose Test
composeRule.setContent { AppTheme { Screen(state, onEvent) } }
composeRule.onNodeWithTag("submit").performClick()
composeRule.onNodeWithText("Salvo").assertIsDisplayed()
- Semantics:
testTagstable on test targets; not just fragile i18n text. waitUntil/waitForIdle— withoutThread.sleep.- Inject fake ViewModel or repo fakes via factory/Hilt test module.
- Idle: coroutines —
IdlingResourceonly if the project already has it; Compose waits for recomposition.
Espresso (XML)
onView(withId(...)).perform(click()). Idling for OkHttp if already configured.- Don't mix Espresso and Compose in the same method without the project's bridge.
Isolation
- Build flavor /
debugtest only. No real staging. - Permissions: grant in
GrantPermissionRuleor CI ADB. - Reset DataStore/Room between tests (in-memory test DB or clear).
- Disable animations in the CI runner (
ANIMATOR_DURATION_SCALE=0).
Flakiness
- Common cause: async without idle, animations, time/network.
- Retry on CI only with evidence; prefer fixing idle.
- Avoid
Thread.sleep. - Screenshots on failure on CI if the pipeline already supports it.
Anti-patterns
- Instrumenting 100% of screens
- Assert by coordinate/pixel
- Real network in PR
testTagon all nodes “just in case”- Duplicating ViewModel tests that already pass on the JVM
Integration with other skills
- Unit:
android-unit-testing - Compose:
jetpack-compose - App:
android-development - Coroutines in fakes:
kotlin-coroutines
Completion criteria
- Critical flow covered without sleep
- Fakes/Hilt test; no shared backend
- Stable semantics
- Suite
connectedDebugAndroidTest(or the CI flavor) green in scope