46Appium / Mobile Native Automation
What you will master here
- What Appium is and how it's the "Selenium for mobile"
- Native vs hybrid vs mobile-web apps
- Appium architecture: client → server → driver → device
- Locators on Android (UiSelector) and iOS (XCUIElement)
- Gestures (W3C Actions), waits, contexts, app management
- Real device vs emulator/simulator vs cloud farm
- Appium 2 plugin model
46.1 Native / Hybrid / Mobile-Web
| App type | What runs | Tool |
|---|---|---|
| Native | Pure platform UI (Activity/UIViewController) | Appium with UiAutomator2 / XCUITest driver |
| Hybrid | Native shell + WebView with HTML/JS | Appium with switchable context (NATIVE_APP vs WEBVIEW_x) |
| Mobile-Web | Mobile Safari/Chrome browser | Selenium/Playwright with mobile emulation OR Appium with browser driver |
46.2 Architecture
Test code → Appium client lib → Appium Server (Node.js)
│
UiAutomator2 driver (Android) / XCUITest driver (iOS)
│
Device / Emulator
Appium speaks the W3C WebDriver protocol — so the same client libs you use for Selenium can drive mobile.
46.3 Setup (Appium 2)
npm i -g appium appium driver install uiautomator2 appium driver install xcuitest appium server --port 4723
// Java client
UiAutomator2Options options = new UiAutomator2Options()
.setDeviceName("Pixel_7_API_34")
.setApp("/path/to/app.apk")
.setAutomationName("UiAutomator2");
AndroidDriver driver = new AndroidDriver(
new URL("http://localhost:4723"), options);
46.4 Locators
// Cross-platform
driver.findElement(AppiumBy.accessibilityId("loginButton"));
driver.findElement(AppiumBy.xpath("//android.widget.Button[@text='Sign in']"));
driver.findElement(AppiumBy.id("com.acme.app:id/email"));
// Android-specific
driver.findElement(AppiumBy.androidUIAutomator(
"new UiSelector().resourceId(\"com.acme.app:id/email\")"));
// iOS-specific
driver.findElement(AppiumBy.iOSClassChain("**/XCUIElementTypeButton[`name == 'Sign in'`]"));
driver.findElement(AppiumBy.iOSNsPredicate("name == 'Sign in'"));
Best locatorAccessibility ID — works cross-platform and the same string the dev uses for a11y labels. Falls back to platform-specific selectors when needed.
46.5 Gestures (W3C Actions)
// Tap
WebElement btn = driver.findElement(AppiumBy.accessibilityId("buy"));
btn.click();
// Swipe up (scroll down)
PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger");
Sequence swipe = new Sequence(finger, 0)
.addAction(finger.createPointerMove(Duration.ZERO,
PointerInput.Origin.viewport(), 500, 1500))
.addAction(finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg()))
.addAction(finger.createPointerMove(Duration.ofMillis(500),
PointerInput.Origin.viewport(), 500, 500))
.addAction(finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg()));
driver.perform(List.of(swipe));
// Long press, pinch, zoom: similar chains
46.6 Hybrid app context switching
// List available contexts
Set<String> contexts = driver.getContextHandles();
// NATIVE_APP, WEBVIEW_com.acme.app
driver.context("WEBVIEW_com.acme.app"); // switch to webview
driver.findElement(By.cssSelector("button.primary")).click();
driver.context("NATIVE_APP"); // back to native
46.7 App lifecycle
driver.installApp("/path/app.apk");
driver.activateApp("com.acme.app");
driver.runAppInBackground(Duration.ofSeconds(5));
driver.terminateApp("com.acme.app");
driver.removeApp("com.acme.app");
// Reset state
driver.executeScript("mobile: clearApp", Map.of("appId", "com.acme.app"));
46.8 Real device vs emulator vs cloud farm
| Option | Pros | Cons |
|---|---|---|
| Android Emulator | Free, fast snapshots | Slow startup, misses some HW behaviour |
| iOS Simulator | Free on macOS | No real cellular/Bluetooth |
| Real device tethered | True behaviour | One per host; setup hassle |
| Cloud farm (BrowserStack/Sauce) | Many devices, parallel | Cost, queueing |
46.9 Appium 2 plugin model
Appium 2 split drivers and the server into plugins. Install only what you need: appium driver install uiautomator2 xcuitest mac2 windows. Plus optional plugins (appium plugin install execute-driver) extend Server capabilities.
Module 46 — Appium Q&A
What's Appium?
An open-source server that automates native, hybrid and mobile-web apps using the W3C WebDriver protocol — "Selenium for mobile". Same client libraries; under the hood it delegates to platform drivers (UiAutomator2 for Android, XCUITest for iOS).
Native vs hybrid app — how do you tell?
Native = built with platform SDK (Android Activity, iOS UIViewController). Hybrid = native shell hosting a WebView with HTML/JS. Test the same way functionally but hybrid requires switching context to WEBVIEW_x.
What's the best locator strategy on mobile?
Accessibility ID — devs typically set it for a11y. Cross-platform, stable, semantic. Fall back to platform-specific (Android: resourceId or UiSelector; iOS: class chain or predicate) when accessibility id missing.
How do you switch from native to WebView?
List contexts (driver.getContextHandles()), then driver.context("WEBVIEW_xxx"). Now standard Selenium commands work on the HTML. Switch back with NATIVE_APP.
How do you perform a swipe?
W3C Actions API — build a Sequence with pointerMove, pointerDown, pointerMove (destination), pointerUp. Or use the Appium-specific
mobile: swipe / mobile: scrollGesture endpoints for higher-level gestures.Real device or emulator — which for tests?
95% emulator/simulator (fast, parallel, free). Real device for final smoke before release (hardware bugs, cellular, sensors). For CI scale, cloud farm with both emulators + selective real devices.
What's new in Appium 2?
Drivers and plugins are now separately installable npm packages. Slimmer server. New endpoint structure. Some breaking changes from Appium 1 — desired capabilities replaced with W3C options objects.