Appium automates native, hybrid and mobile-web apps on Android and iOS using the same WebDriver API you know from Selenium. This tutorial covers how Appium works, setting it up, writing the first test, locating elements and performing gestures, and handling hybrid apps. For interview preparation, see the 25 Appium interview questions.

How Appium Works

Your test (Java client) sends W3C WebDriver commands to the Appium server. The server passes each command to a driver for the platform: UiAutomator2 for Android or XCUITest for iOS, which uses the platform's own automation framework to act on the device and returns the result.

Advertisement

Setup (Appium 2)

npm install -g appium
appium driver install uiautomator2      # Android
appium driver install xcuitest          # iOS (macOS only)
appium                                  # starts the server on http://127.0.0.1:4723

Android also needs the Android SDK with an emulator or a device with USB debugging enabled; iOS needs a Mac with Xcode. Add the io.appium:java-client dependency to your Maven project.

First Android Test

UiAutomator2Options options = new UiAutomator2Options()
        .setDeviceName("Pixel_7_API_34")
        .setApp(System.getProperty("user.dir") + "/apps/app-debug.apk");

AndroidDriver driver = new AndroidDriver(new URL("http://127.0.0.1:4723"), options);
try {
    driver.findElement(AppiumBy.accessibilityId("username")).sendKeys("asha");
    driver.findElement(AppiumBy.accessibilityId("password")).sendKeys("secret");
    driver.findElement(AppiumBy.accessibilityId("login")).click();
    assertTrue(driver.findElement(AppiumBy.accessibilityId("welcome")).isDisplayed());
} finally {
    driver.quit();
}

Locators and Gestures

  • Prefer accessibility IDs (content-desc on Android, accessibilityIdentifier on iOS), then resource IDs; avoid long XPath, which is slow on mobile.
  • Scrolling on Android: AppiumBy.androidUIAutomator("new UiScrollable(new UiSelector().scrollable(true)).scrollIntoView(new UiSelector().text(\"Settings\"))")
  • Gestures: use W3C actions or driver commands such as mobile: swipeGesture; the old TouchAction API is deprecated.

Mobile Testing with Appium: Core Questions

What is Appium? How does it differ from Selenium?

AppiumSelenium WebDriver
Mobile automation — iOS and AndroidWeb automation — desktop browsers
Uses UIAutomator2 (Android) and XCUITest (iOS)Uses ChromeDriver, GeckoDriver, EdgeDriver
Supports native, hybrid, and mobile web appsSupports web apps only
No app source code modification neededNo app modification needed either
Extends WebDriver protocol for mobileOriginal WebDriver W3C protocol
Requires Appium Server + device/emulatorRequires browser + browser driver only

What are Desired Capabilities in Appium? List key ones for Android.

✔ Desired Capabilities (or Options) tell Appium which device and app to use.

  • platformName: 'Android' — required, specifies mobile OS
  • deviceName: 'emulator-5554' or 'Samsung Galaxy S21' — target device
  • appPackage: 'com.amazon.mShop.android.shopping' — app package name
  • appActivity: 'com.amazon.mShop.android.activity.MainActivity' — launch activity
  • automationName: 'UIAutomator2' — Appium automation driver for Android
  • app: '/path/to/app.apk' — specify if app is not already installed
  • noReset: true — don't reset app state between sessions (faster)
  • autoGrantPermissions: true — automatically grant app permissions

What locator strategies are specific to Appium mobile testing?

✔ Appium supports standard Selenium locators plus mobile-specific ones.

  • accessibility id (BEST): Maps to contentDescription (Android) and accessibilityLabel (iOS)
  • driver.findElement(AppiumBy.accessibilityId("Search"));
  • -android uiautomator: Powerful Android-specific selector
  • new UiSelector().text("Login").className("android.widget.Button")
  • -ios predicate string: iOS NSPredicate-based queries
  • "name == 'Login' AND type == 'XCUITypeButton'"
  • -ios class chain: Faster than predicate for iOS
  • "**/XCUIElementTypeButton[`name == 'Login'`]"
  • xpath: Works but slower on mobile — use as last resort

iOS Testing and Context Switching

What are the key capabilities for iOS in Appium? How do you set up an iOS test?

iOS automation requires a Mac machine and uses XCUITest driver. The setup is more complex than Android.

PREREQUISITES for iOS

macOS machine (mandatory — iOS tools only work on Mac)
Xcode installed from App Store

Appium server: npm install -g appium

XCUITest driver: appium driver install xcuitest

For simulator: no Apple account needed

For real device: Apple Developer account + provisioning profile + code signing cert

  • iOS CAPABILITIES (XCUITestOptions):
XCUITestOptions options = new XCUITestOptions();
options.setPlatformName("iOS");
options.setPlatformVersion("17.0");
options.setDeviceName("iPhone 15 Pro");     // simulator name
options.setAutomationName("XCUITest");       // mandatory
options.setBundleId("com.example.myapp");    // for pre-installed app
// OR: options.setApp("/path/to/MyApp.app"); // install and launch
options.setUdid("auto");                     // 'auto' picks available sim
options.setAutoAcceptAlerts(true);           // auto-dismiss system alerts
options.setWdaLocalPort(8100);               // WebDriverAgent port
options.setUseNewWda(false);                 // reuse WDA (faster startup)
IOSDriver driver = new IOSDriver(new URL("http://127.0.0.1:4723"), options);
  • iOS LOCATORS:
driver.findElement(AppiumBy.accessibilityId("Login"));  // best — maps to accessibilityLabel
driver.findElement(AppiumBy.iOSNsPredicateString("name == \"Login\" AND type == \"XCUIElementTypeButton\""));
driver.findElement(AppiumBy.iOSClassChain("**/XCUIElementTypeButton[`name == \"Login\"`]"));
  • iOS GESTURES:
driver.executeScript("mobile: swipe", ImmutableMap.of("direction", "up"));
driver.executeScript("mobile: pressButton", ImmutableMap.of("name", "home"));
driver.executeScript("mobile: pressButton", ImmutableMap.of("name", "volumeup"));

iOS vs Android KEY DIFFERENCES

iOS: bundleId vs Android: appPackage + appActivity
iOS: XCUITest driver vs Android: UIAutomator2 driver
iOS: Requires Mac vs Android: Windows/Linux/Mac all work
iOS: WebDriverAgent (WDA) installed on device vs Android: uses ADB

How do you handle hybrid apps in Appium? Explain context switching with a full example.

Hybrid apps contain both native UI and WebView components. You must switch context to interact with each part.

WHAT IS CONTEXT

NATIVE_APP — interact with native UI elements (buttons, lists, etc.)
WEBVIEW_com.example.app — interact with web content inside WebView

STEP 1 — Get all available contexts

Set<String> contexts = driver.getContextHandles();
System.out.println(contexts);
// Output: [NATIVE_APP, WEBVIEW_com.example.myapp]

STEP 2 — Wait for WebView to be available

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(15));
wait.until(d -> d.getContextHandles().size() > 1);

STEP 3 — Switch to WebView

String webviewContext = driver.getContextHandles().stream()
  .filter(c -> c.startsWith("WEBVIEW"))
  .findFirst()
  .orElseThrow(() -> new RuntimeException("WebView context not found"));
driver.context(webviewContext);

STEP 4 — Use Selenium-style locators in WebView

driver.findElement(By.id("webLoginBtn")).click();  // By.id, By.cssSelector etc.
driver.findElement(By.cssSelector(".web-form input[name=\"email\"]")).sendKeys("test@test.com");

STEP 5 — Switch back to native

driver.context("NATIVE_APP");
driver.findElement(AppiumBy.accessibilityId("Back")).click(); // native locators again

GET CURRENT CONTEXT

String current = driver.getContext(); // returns current context name
  • ANDROID REQUIREMENT for WebView debugging:

App must enable: WebView.setWebContentsDebuggingEnabled(true)

Set chromedriver: options.setChromedriverExecutableDir("/path/to/chromedriver/");

Match chromedriver version with WebView Chrome version on device
  • iOS WebView:
Uses Safari WebInspector — no chromedriver needed

Enable: iOS Settings → Safari → Advanced → Web Inspector ON

FAQs

Is Appium the same as Selenium?

Appium uses the same WebDriver protocol and client style as Selenium, but it automates mobile apps through platform drivers such as UiAutomator2 and XCUITest instead of browsers.

Do I need a Mac to test iOS apps with Appium?

Yes. The XCUITest driver depends on Xcode, which only runs on macOS; Android testing works on Windows, macOS or Linux.

Should I use emulators or real devices?

Use emulators and simulators for everyday automated runs, and real devices (or a device cloud) for performance, hardware features and final release checks.