name: android-app-testing description: Automated testing for Android applications using Appium with Espresso driver. Use when testing native Android apps (.apk files), verifying mobile UI functionality, automating gestures (swipe, scroll, tap), or running blackbox tests on Android devices/emulators. Covers Espresso (fast, source-required) and UI Automator 2 (black-box) approaches. tags: [android, mobile-testing, appium, espresso, ui-automator]
Android App Testing
Test Android applications using Appium with Espresso driver for fast, reliable automation.
Key Advantage: Espresso driver is 2x faster than UI Automator 2 with automatic UI synchronization -- no manual waits needed.
When to Use
- Testing native Android apps (.apk files)
- Verifying mobile UI functionality
- Automating gestures (swipe, scroll, tap)
- Running blackbox tests on Android devices/emulators
- QA agent workflows in multi-agent teams
Decision Tree
Do you have app source code?
Yes -> Use Espresso driver (FAST, automatic waits)
No -> Use UI Automator 2 driver (black-box testing)
Use Espresso whenever possible (requires app source code but 2x faster).
Prerequisites
- Appium 3.x installed
- Espresso driver:
appium driver install espresso - Python client:
pip install Appium-Python-Client - Device/emulator connected:
adb devices
Quick Start
from appium import webdriver
from appium.options.android import UiAutomator2Options
from appium.webdriver.common.appiumby import AppiumBy
# Configure for Espresso (fast)
options = UiAutomator2Options()
options.platform_name = "Android"
options.automation_name = "Espresso" # Use Espresso for speed
options.app = "/path/to/app.apk"
options.device_name = "Android Emulator"
options.auto_grant_permissions = True
# Start session
driver = webdriver.Remote("http://localhost:4723", options=options)
# Espresso automatically waits - just find and interact
driver.find_element(by=AppiumBy.ID, value="username").send_keys("testuser")
driver.find_element(by=AppiumBy.ID, value="login_button").click()
# Verify result
assert driver.find_element(by=AppiumBy.ID, value="home_screen").is_displayed()
driver.quit()
Element Locator Strategy
| Strategy | Speed | Example |
|---|---|---|
| ID | Fastest | AppiumBy.ID, "button_login" |
| Accessibility ID | Fast | AppiumBy.ACCESSIBILITY_ID, "login" |
| Class Name | Medium | AppiumBy.CLASS_NAME, "android.widget.Button" |
| XPath | Slowest | Avoid unless necessary |
Gesture Automation (Appium 2.0+)
# Tap at coordinates
driver.execute_script('mobile: clickGesture', {'x': 100, 'y': 200})
# Swipe
driver.execute_script('mobile: swipeGesture', {
'left': 100, 'top': 500, 'width': 200, 'height': 200,
'direction': 'up', 'percent': 0.75
})
# Long press
driver.execute_script('mobile: longClickGesture', {
'elementId': element.id, 'duration': 2000
})
Reconnaissance Pattern (Unknown Apps)
- Launch and wait for app to load
- Take screenshot:
driver.save_screenshot('/tmp/screen.png') - Discover elements:
buttons = driver.find_elements(by=AppiumBy.CLASS_NAME, value="android.widget.Button") for btn in buttons: print(f"Button: {btn.text} (ID: {btn.get_attribute('resource-id')})") - Use discovered IDs in tests
Anti-Patterns
| Avoid | Why | Instead |
|---|---|---|
| XPath locators | Very slow | Use ID or Accessibility ID |
| TouchAction class | Removed in Appium 2.0+ | Use mobile: gesture scripts |
time.sleep() with Espresso |
Espresso has automatic waits | Let Espresso handle synchronization |
Missing finally block |
Leaves sessions open | Always driver.quit() in finally |
| Testing before Appium server starts | Tests fail immediately | Start Appium server first: appium |
References
- Source: claude-skills/android-app-testing (MIT License)
- Appium Documentation
- Espresso Driver