Draft page
Access: Prod

Appium

Appium brings the WebDriver model to mobile apps. A test creates a session, describes the target platform and app through capabilities, finds elements in the app UI, performs gestures, asserts outcomes, and ends the session.

This tutorial explains the Appium workflow for Android and iOS, then maps the same concepts to webmate’s app testing documentation, device infrastructure, and Appium Inspector support.

Goal

By the end of this tutorial you will know how to prepare an app for automation, define Appium capabilities, start an Android or iOS session, use stable selectors, inspect the app, and run the same suite in CI or on webmate-managed devices.

Before You Start

You need an installable app package, such as an APK for Android or an IPA for iOS, and a test project using an Appium-compatible client. The examples use WebdriverIO syntax because it is compact, but the same capability model applies to Java, Python, Ruby, C#, and other Appium clients.

For webmate execution, you also need a project, API key, uploaded app or app identifiers, and target device information. Existing webmate App Testing pages describe upload options and available capabilities in more detail.

Appium 2 and 3 Capability Model

Modern Appium follows the W3C WebDriver capability model. Standard capabilities such as platformName and browserName keep their normal names. Appium-specific capabilities use the appium: prefix, such as appium:automationName, appium:app, appium:appPackage, and appium:bundleId.

1
2
3
4
5
6
7
{
  "platformName": "Android",
  "appium:automationName": "UiAutomator2",
  "appium:deviceName": "Android",
  "appium:appPackage": "com.example.app",
  "appium:appActivity": ".MainActivity"
}

Appium also supports grouping extension capabilities under appium:options. Use the style that your client and team prefer, but keep capability names consistent across the suite.

Step 1: Prepare the App

An Appium test can launch an already installed app or install an app package at session start. For Android, the key identifiers are usually the package name and launch activity. For iOS, the key identifier is the bundle ID. If you pass an app file, Appium can install it before starting the session.

For webmate, use the existing app upload documentation when the app package needs to be managed in webmate. If the app is already uploaded or installed on the target device, the test can focus on the identifiers and capabilities needed to launch it.

Step 2: Create an Android Session

The following WebdriverIO example starts an Android session against an Appium server:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
const { remote } = require('webdriverio');

const driver = await remote({
  hostname: process.env.APPIUM_HOST || 'localhost',
  port: Number(process.env.APPIUM_PORT || 4723),
  logLevel: 'info',
  capabilities: {
    platformName: 'Android',
    'appium:automationName': 'UiAutomator2',
    'appium:deviceName': 'Android',
    'appium:appPackage': 'com.example.app',
    'appium:appActivity': '.MainActivity',
    'appium:newCommandTimeout': 120,
  },
});

try {
  const login = await driver.$('~Login');
  await login.click();
} finally {
  await driver.deleteSession();
}

The ~Login selector targets an accessibility ID. Accessibility IDs are usually more stable than XPath because they are explicit app contracts and also improve accessibility.

Step 3: Create an iOS Session

iOS automation normally uses the XCUITest automation backend. Use the bundle ID for an installed app, or provide an app path when the server should install the app.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
const driver = await remote({
  hostname: process.env.APPIUM_HOST || 'localhost',
  port: Number(process.env.APPIUM_PORT || 4723),
  capabilities: {
    platformName: 'iOS',
    'appium:automationName': 'XCUITest',
    'appium:deviceName': 'iPhone',
    'appium:bundleId': 'com.example.app',
    'appium:newCommandTimeout': 120,
  },
});

The test body should stay similar across platforms when the app exposes stable accessibility identifiers. Platform-specific setup belongs in fixtures or capability builders, not in every test.

Step 4: Use Selectors That Survive UI Changes

Prefer accessibility IDs for buttons, inputs, tabs, and important content. They are readable, fast, and stable when the app team treats them as part of the testability contract.

1
2
3
4
await driver.$('~Email').setValue('tester@example.com');
await driver.$('~Password').setValue(process.env.TEST_PASSWORD);
await driver.$('~Sign in').click();
await expect(await driver.$('~Dashboard')).toBeDisplayed();

Use platform selectors only when necessary. XPath can be useful for exploration, but it is often slower and more fragile than accessibility IDs or native selector strategies.

Step 5: Inspect the App

Appium Inspector helps you see the current screen, element tree, selectors, attributes, and possible actions. Use it when creating a new test or diagnosing a selector failure.

In webmate, the Appium Inspector documentation explains how to inspect a running session in the webmate Workbench. That is especially useful when the device is remote and you need to compare the screenshot, app source, and element identifiers at the moment the test failed.

Step 6: Add webmate Capabilities

webmate uses Selenium/Appium capabilities to describe the desired device, Appium version, project, credentials, app, and session metadata. Keep webmate values in environment variables and build the capabilities in one place.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
const capabilities = {
  browserName: 'Appium',
  platformName: 'Android_15',
  browserVersion: '3.0.2',
  'appium:automationName': 'UiAutomator2',
  'appium:appPackage': 'com.example.app',
  'appium:appActivity': '.MainActivity',
  'wm:apikey': process.env.WEBMATE_APIKEY,
  'wm:project': process.env.WEBMATE_PROJECTID,
  'wm:name': 'Android login smoke',
  'wm:tags': ['appium', 'smoke'],
};

Use the Available Capabilities page for the canonical capability list. Use Upload App when the app package needs to be uploaded before execution.

Step 7: Run in CI

CI should package the app, upload or publish it where the test environment can access it, then run the Appium suite with secrets injected as environment variables.

1
2
3
4
5
npm ci
npm run build:app
export WEBMATE_APIKEY="$WEBMATE_APIKEY"
export WEBMATE_PROJECTID="$WEBMATE_PROJECTID"
npm run test:appium

Keep a small smoke suite for every change and a broader device matrix for scheduled runs. Mobile tests involve real devices, app installation, OS state, and network conditions, so the matrix should be intentional rather than enormous by default.

Debugging

If session creation fails, inspect capabilities first. Check platform name, automation name, app path, package name, activity, bundle ID, device availability, Appium version, and credentials. If the app opens but selectors fail, inspect the element tree and confirm the identifier exists in the current screen state.

If a gesture is flaky, verify that the target is visible, enabled, and not covered by a permission dialog or onboarding screen. Handle system permissions explicitly in setup or through capabilities where supported.

Verify the Result

A useful Appium setup can create a session, launch the app, interact through stable selectors, assert a user-visible result, and delete the session. On webmate, a successful run should also be visible in the project with meaningful names and tags so the team can inspect failures later.

Next Steps

Continue with App Testing Getting Started , Use Existing Tests , Available Capabilities , and Appium Inspector for webmate-specific setup.