QA Testing (Android)
Android testing automation with Espresso, UIAutomator, and Compose Testing.
Core References: Android Testing Docs, Espresso, Compose Testing
Quick Reference
| Task |
Command |
| List emulators |
emulator -list-avds |
| Start emulator |
emulator @<avd_name> |
| List devices |
adb devices |
| Install APK |
adb install -r <path-to-apk> |
| Run unit tests |
./gradlew test |
| Run instrumented tests (connected) |
./gradlew connectedAndroidTest |
| Run instrumented tests (GMD) |
./gradlew <device><variant>AndroidTest |
| List GMD tasks |
`./gradlew tasks --all |
| Clear app data |
adb shell pm clear <applicationId> |
Quick Start (2026 Defaults)
- Prefer Gradle Managed Devices (GMD) + ATD images for CI; use
connectedAndroidTest for local ad-hoc runs.
- Enable test isolation via AndroidX Test Orchestrator for instrumented tests.
- Disable animations via Gradle
testOptions (preferred) instead of per-runner ADB steps.
- Keep selectors stable:
withId() (Views), testTag (Compose), resource-id/content-desc (UIAutomator).
Recommended Gradle defaults for stable instrumented tests (version catalog names vary by project):
android {
testOptions {
animationsDisabled = true
execution = "ANDROIDX_TEST_ORCHESTRATOR"
}
}
dependencies {
androidTestUtil(libs.androidx.test.orchestrator)
}
When to Use
- Debug or stabilize flaky Android UI tests
- Add Espresso tests for View-based UIs
- Add Compose UI tests for composables
- Add UIAutomator tests for system UI or cross-app flows
- Set up an Android test gate in CI
Inputs to Gather
- UI stack: Views, Compose, or mixed
- Test layer: unit, Robolectric, instrumented UI, UIAutomator/system
- CI target: PR gate vs nightly vs release; emulator vs device farm
- Device matrix: min/target API, form factors, locales (if relevant)
- Flake symptoms: timeouts, missing nodes, idling/sync, device-only issues
- App seams: DI hooks for fakes, feature flags, test accounts/test data
Testing Layers
| Layer |
Framework |
Scope |
| Unit |
JUnit + Mockito |
JVM, no Android |
| Unit (Android) |
Robolectric |
JVM, simulated |
| UI (Views) |
Espresso |
Instrumented |
| UI (Compose) |
Compose Testing |
Instrumented |
| System |
UIAutomator |
Cross-app |
Core Principles (Stability)
Device Matrix
- Default: emulators for PR gates; real devices for release
- Cover: min supported API level, target API level, plus tablet/foldable if supported
Flake Control
- Prefer Gradle
testOptions { animationsDisabled = true } for instrumented tests
- Use AndroidX Test Orchestrator to isolate state and recover from crashes
- Use IdlingResources / Compose idling +
waitUntil instead of sleeps
- Mock network with
MockWebServer (or your DI fake) and avoid live backends
- Reset app state per test (test account/data, storage, feature flags)
Writing Tests
- Espresso (Views): open
references/espresso-patterns.md
- Compose: open
references/compose-testing.md
- UIAutomator (system/cross-app): open
references/uiautomator.md
Workflows
Add a New UI Test (Instrumented)
- Pick framework: Espresso (Views) vs Compose Testing vs UIAutomator boundary.
- Add stable selectors: View
id, Compose Modifier.testTag, system resource-id/content-desc.
- Control externals: fake/mock network + deterministic test data.
- Add waits: IdlingResources / Compose idling +
waitUntil (avoid sleeps).
- Run locally:
./gradlew connectedAndroidTest (or a single test via runner args).
Diagnose a Flaky Instrumented Test
- Confirm reproduces: run the test 10x; isolate to one device/API if needed.
- Remove nondeterminism: network, clock/timezone, locale, feature flags, animations.
- Replace sleeps with idling/explicit waits; validate your IdlingResource actually idles.
- Capture artifacts: logcat + screenshot + screen recording for failures.
- If still flaky, isolate app state (orchestrator + clear data) and bisect the interaction steps.
Add a CI Gate (Preferred: GMD)
- Configure GMD + ATD images (see
references/gradle-managed-devices.md).
- Run PR gate on a small matrix; expand via groups for nightly/release.
- Ensure artifacts upload on failure:
**/build/reports/androidTests/, screenshots/logcat.
ADB Commands (Triage)
# Screenshot
adb exec-out screencap -p > screenshot.png
# Screen recording
adb shell screenrecord /sdcard/demo.mp4
CI Integration
Preferred: Gradle Managed Devices (GMD). See references/gradle-managed-devices.md.
# .github/workflows/android.yml
name: Android CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- uses: gradle/actions/setup-gradle@v3
- run: ./gradlew test pixel6api34DebugAndroidTest
Navigating References
The reference guides are intentionally large; search within them instead of loading everything:
rg -n \"^## \" frameworks/shared-skills/skills/qa-testing-android/references/compose-testing.md
rg -n \"Idling|waitUntil|Synchronization\" frameworks/shared-skills/skills/qa-testing-android/references/compose-testing.md
rg -n \"RecyclerView|Intents\" frameworks/shared-skills/skills/qa-testing-android/references/espresso-patterns.md
Do / Avoid
Do
- Prefer orchestrator + per-test isolation for instrumented tests
- Use IdlingResources /
waitUntil for async waits
- Use Robot/Page Object patterns for readability and reuse
- Run a small device matrix on PRs; expand on nightly/release
Avoid
Thread.sleep() for synchronization
- Tests depending on live network/backends
- Flaky selectors (localized text, position-only selectors)
Resources
| Resource |
Purpose |
| references/espresso-patterns.md |
Espresso matchers, actions |
| references/compose-testing.md |
Compose testing guide |
| references/uiautomator.md |
UIAutomator patterns (system UI) |
| references/gradle-managed-devices.md |
Managed Devices for CI |
| data/sources.json |
Documentation links |
Templates
| Template |
Purpose |
| assets/template-android-test-checklist.md |
Stability checklist |
Related Skills
1---2name: qa-testing-android3description: Android testing with Espresso, UIAutomator, and Compose Testing; layered strategy, flake control, device matrix, CI integration, and ADB automation.4---5
6# QA Testing (Android)
7
8Android testing automation with Espresso, UIAutomator, and Compose Testing.
9
10**Core References**: [Android Testing Docs](https://developer.android.com/training/testing), [Espresso](https://developer.android.com/training/testing/espresso), [Compose Testing](https://developer.android.com/develop/ui/compose/testing)
11
12## Quick Reference
13
14| Task | Command |
15|------|---------|
16| List emulators | `emulator -list-avds` |
17| Start emulator | `emulator @<avd_name>` |
18| List devices | `adb devices` |
19| Install APK | `adb install -r <path-to-apk>` |
20| Run unit tests | `./gradlew test` |
21| Run instrumented tests (connected) | `./gradlew connectedAndroidTest` |
22| Run instrumented tests (GMD) | `./gradlew <device><variant>AndroidTest` |
23| List GMD tasks | `./gradlew tasks --all | rg -n \"AndroidTest|managedDevice|ManagedDevices\"` |
24| Clear app data | `adb shell pm clear <applicationId>` |
25
26## Quick Start (2026 Defaults)
27
28- Prefer Gradle Managed Devices (GMD) + ATD images for CI; use `connectedAndroidTest` for local ad-hoc runs.
29- Enable test isolation via AndroidX Test Orchestrator for instrumented tests.
30- Disable animations via Gradle `testOptions` (preferred) instead of per-runner ADB steps.
31- Keep selectors stable: `withId()` (Views), `testTag` (Compose), resource-id/content-desc (UIAutomator).
32
33Recommended Gradle defaults for stable instrumented tests (version catalog names vary by project):
34
35```kotlin
36android {
37 testOptions {
38 animationsDisabled = true
39 execution = "ANDROIDX_TEST_ORCHESTRATOR"
40 }
41}
42
43dependencies {
44 androidTestUtil(libs.androidx.test.orchestrator)
45}
46```
47
48## When to Use
49
50- Debug or stabilize flaky Android UI tests
51- Add Espresso tests for View-based UIs
52- Add Compose UI tests for composables
53- Add UIAutomator tests for system UI or cross-app flows
54- Set up an Android test gate in CI
55
56## Inputs to Gather
57
58- UI stack: Views, Compose, or mixed
59- Test layer: unit, Robolectric, instrumented UI, UIAutomator/system
60- CI target: PR gate vs nightly vs release; emulator vs device farm
61- Device matrix: min/target API, form factors, locales (if relevant)
62- Flake symptoms: timeouts, missing nodes, idling/sync, device-only issues
63- App seams: DI hooks for fakes, feature flags, test accounts/test data
64
65## Testing Layers
66
67| Layer | Framework | Scope |
68|-------|-----------|-------|
69| Unit | JUnit + Mockito | JVM, no Android |
70| Unit (Android) | Robolectric | JVM, simulated |
71| UI (Views) | Espresso | Instrumented |
72| UI (Compose) | Compose Testing | Instrumented |
73| System | UIAutomator | Cross-app |
74
75## Core Principles (Stability)
76
77### Device Matrix
78
79- Default: emulators for PR gates; real devices for release
80- Cover: min supported API level, target API level, plus tablet/foldable if supported
81
82### Flake Control
83
84- Prefer Gradle `testOptions { animationsDisabled = true }` for instrumented tests
85- Use AndroidX Test Orchestrator to isolate state and recover from crashes
86- Use IdlingResources / Compose idling + `waitUntil` instead of sleeps
87- Mock network with `MockWebServer` (or your DI fake) and avoid live backends
88- Reset app state per test (test account/data, storage, feature flags)
89
90## Writing Tests
91
92- Espresso (Views): open `references/espresso-patterns.md`
93- Compose: open `references/compose-testing.md`
94- UIAutomator (system/cross-app): open `references/uiautomator.md`
95
96## Workflows
97
98### Add a New UI Test (Instrumented)
99
100- Pick framework: Espresso (Views) vs Compose Testing vs UIAutomator boundary.
101- Add stable selectors: View `id`, Compose `Modifier.testTag`, system `resource-id`/`content-desc`.
102- Control externals: fake/mock network + deterministic test data.
103- Add waits: IdlingResources / Compose idling + `waitUntil` (avoid sleeps).
104- Run locally: `./gradlew connectedAndroidTest` (or a single test via runner args).
105
106### Diagnose a Flaky Instrumented Test
107
108- Confirm reproduces: run the test 10x; isolate to one device/API if needed.
109- Remove nondeterminism: network, clock/timezone, locale, feature flags, animations.
110- Replace sleeps with idling/explicit waits; validate your IdlingResource actually idles.
111- Capture artifacts: logcat + screenshot + screen recording for failures.
112- If still flaky, isolate app state (orchestrator + clear data) and bisect the interaction steps.
113
114### Add a CI Gate (Preferred: GMD)
115
116- Configure GMD + ATD images (see `references/gradle-managed-devices.md`).
117- Run PR gate on a small matrix; expand via groups for nightly/release.
118- Ensure artifacts upload on failure: `**/build/reports/androidTests/`, screenshots/logcat.
119
120## ADB Commands (Triage)
121
122```bash
123# Screenshot
124adb exec-out screencap -p > screenshot.png
125
126# Screen recording
127adb shell screenrecord /sdcard/demo.mp4
128```
129
130## CI Integration
131
132Preferred: Gradle Managed Devices (GMD). See `references/gradle-managed-devices.md`.
133
134```yaml
135# .github/workflows/android.yml
136name: Android CI
137on: [push, pull_request]
138jobs:
139 test:
140 runs-on: ubuntu-latest
141 steps:
142 - uses: actions/checkout@v4
143 - uses: actions/setup-java@v4
144 with:
145 java-version: '17'
146 distribution: 'temurin'
147 - uses: gradle/actions/setup-gradle@v3
148 - run: ./gradlew test pixel6api34DebugAndroidTest
149```
150
151## Navigating References
152
153The reference guides are intentionally large; search within them instead of loading everything:
154
155- `rg -n \"^## \" frameworks/shared-skills/skills/qa-testing-android/references/compose-testing.md`
156- `rg -n \"Idling|waitUntil|Synchronization\" frameworks/shared-skills/skills/qa-testing-android/references/compose-testing.md`
157- `rg -n \"RecyclerView|Intents\" frameworks/shared-skills/skills/qa-testing-android/references/espresso-patterns.md`
158
159## Do / Avoid
160
161### Do
162
163- Prefer orchestrator + per-test isolation for instrumented tests
164- Use IdlingResources / `waitUntil` for async waits
165- Use Robot/Page Object patterns for readability and reuse
166- Run a small device matrix on PRs; expand on nightly/release
167
168### Avoid
169
170- `Thread.sleep()` for synchronization
171- Tests depending on live network/backends
172- Flaky selectors (localized text, position-only selectors)
173
174## Resources
175
176| Resource | Purpose |
177|----------|---------|
178| [references/espresso-patterns.md](references/espresso-patterns.md) | Espresso matchers, actions |
179| [references/compose-testing.md](references/compose-testing.md) | Compose testing guide |
180| [references/uiautomator.md](references/uiautomator.md) | UIAutomator patterns (system UI) |
181| [references/gradle-managed-devices.md](references/gradle-managed-devices.md) | Managed Devices for CI |
182| [data/sources.json](data/sources.json) | Documentation links |
183
184## Templates
185
186| Template | Purpose |
187|----------|---------|
188| [assets/template-android-test-checklist.md](assets/template-android-test-checklist.md) | Stability checklist |
189
190## Related Skills
191
192| Skill | Purpose |
193|-------|---------|
194| [software-mobile](../software-mobile/SKILL.md) | Android development |
195| [qa-testing-strategy](../qa-testing-strategy/SKILL.md) | Test strategy |
196| [qa-testing-mobile](../qa-testing-mobile/SKILL.md) | Cross-platform mobile |