Mobile Apps
WebdriverIO automates Android and iOS through Appium, which speaks the WebDriver protocol. Your tests use the same browser object (aliased as driver), $/$$ selectors and expect matchers as browser tests. Appium routes each session to a platform driver chosen by appium:automationName. For Android that is UiAutomator2, with Espresso as an alternative that unlocks extra selector strategies. For iOS and iPadOS it is XCUITest. With these drivers you can test native apps and mobile web in Chrome on Android or Safari on iOS. You can also test hybrid apps, switching between the native context and embedded webviews. Sessions can run on Android emulators, iOS simulators, real devices, or device clouds such as Sauce Labs, BrowserStack, TestingBot and TestMu AI. The @wdio/appium-service starts and stops a local Appium server for you. On top of the raw Appium API, WebdriverIO adds cross-platform mobile commands such as tap, swipe, longPress, scrollIntoView and switchContext.
Quick start
Prerequisites: Android Studio with an Android SDK and an emulator for Android; Xcode and a simulator on macOS for iOS. npx appium-installer guides you through the environment setup, and npm init wdio@latest . scaffolds a mobile project (choose Android or iOS). To set up by hand:
npm install --save-dev @wdio/cli @wdio/local-runner @wdio/mocha-framework @wdio/spec-reporter @wdio/appium-service appium tsx
npx appium driver install uiautomator2 # Android
npx appium driver install xcuitest # iOS
{
"compilerOptions": {
"types": ["node", "@wdio/globals/types", "@wdio/mocha-framework"]
}
}
export const config: WebdriverIO.Config = {
runner: 'local',
port: 4723,
specs: ['./test/specs/**/*.ts'],
capabilities: [{
platformName: 'Android',
'appium:deviceName': 'Android GoogleAPI Emulator',
'appium:platformVersion': '12.0',
'appium:automationName': 'UiAutomator2',
'appium:app': './path/to/app.apk'
}],
services: ['appium'],
logLevel: 'info',
waitforTimeout: 10000,
framework: 'mocha',
reporters: ['spec'],
mochaOpts: {
ui: 'bdd',
timeout: 60000
}
}
import { expect, driver, $ } from '@wdio/globals'
describe('My app', () => {
it('should open the contacts screen', async () => {
await $('~Contacts').click()
await expect($('~Add contact')).toBeDisplayed()
})
it('should interact with a webview', async () => {
await driver.switchContext({ title: 'My Webview Title' })
await expect($('h1')).toBeDisplayed()
})
})
npx wdio run ./wdio.conf.ts
~ is the accessibility id selector: it maps to content-description on Android and accessibilityIdentifier on iOS, and is the preferred cross-platform strategy. Replace the example ids, the webview title and the app path with your own.
Other targets only change the capabilities:
{
platformName: 'iOS',
'appium:deviceName': 'iPhone Simulator',
'appium:platformVersion': '16.4',
'appium:automationName': 'XCUITest',
'appium:app': './path/to/MyApp.app' // .app for simulators, signed .ipa for real devices
}
{
platformName: 'Android',
browserName: 'Chrome',
'appium:deviceName': 'Android GoogleAPI Emulator',
'appium:platformVersion': '12.0',
'appium:automationName': 'UiAutomator2'
}
For iOS mobile web, use platformName: 'iOS', browserName: 'Safari' and 'appium:automationName': 'XCUITest'.
Choose your path
- Appium Setup: which platforms Appium covers (iOS, Android, Tizen, TV apps) and how to install the toolchain.
- Appium Service: service options (
args,command,logPath),npx start-appium-inspectorto open the Appium Inspector, and a beta optimizer for slow XPath selectors. - Mobile Commands: cross-platform gestures and helpers. Covers hybrid apps with
getContextsandswitchContext, plus the webview capabilities for iOS. - Mobile Selectors: accessibility id, Android UiAutomator, Espresso data/view matchers and iOS predicate strings and class chains.
- Appium protocol commands: the raw Appium endpoints available on
driver. - Flutter apps: why Flutter needs the Appium Flutter Driver, then prepare the app, configure Appium, set up WebdriverIO and write tests.
- Cloud Services: connect to Sauce Labs, BrowserStack, TestingBot, TestMu AI, Perfecto or RobotActions to run on hosted real devices.
- Visual Testing: image comparison for native apps, hybrid apps and mobile browsers. For Percy on mobile, see App Percy.
- Multiremote: coordinate several devices or browsers in one test.
Emulating a device viewport in a desktop browser with browser.emulate('device', ...) is not mobile testing. Desktop browser engines differ from mobile ones, so use Appium with a real mobile browser instead.
Troubleshooting
- Session doesn't start: make sure the Appium driver for your
appium:automationNameis installed and the emulator or simulator is running. Useport: 4723unless you changed the Appium port. - iOS can't find a webview: try
appium:webviewConnectRetries,appium:webviewConnectTimeoutorappium:includeSafariInWebviews(see Hybrid Apps). - Android webview is slow to appear: tune
androidWebviewConnectionRetryTimeandandroidWebviewConnectTimeoutongetContexts/switchContext. - Flutter widgets aren't found with native selectors: that's expected. Use the Flutter driver and finders described in the Flutter guide.
Next steps
- Configuration and Capabilities references.
- Page Object Pattern to share screens between Android and iOS specs.
- MCP to let an AI agent drive iOS and Android sessions through Appium.
- Other platforms: Web Browsers, Desktop Apps, Extensions & Editors.