Appium Testing

Mobile App Testing with Appium

Appium allows users to control apps on real and virtual mobile devices using most popular programming languages, including Java, JavaScript, C#, PHP, Python, and Ruby. Let’s explore Appium testing and how to get started.

Appium Mobile Testing

What is Appium?

Appium is one of the leading tools for controlling a native, hybrid, or mobile app on iOS mobile, Android mobile, and Windows desktop platforms. It allows testers and developers to create automated tests of mobile applications, helping them deliver quality software faster, with less risk.

Appium is a freely available, open-source tool.  This means anyone can use it, read the source code, and contribute new features and suggestions.  This has helped Appium become one of the most popular mobile automation tools, used by software teams worldwide.

The Appium project believes that app automation should be possible from any language or framework, and should work without requiring specific changes to the app code.

Read more on the Appium documentation.

How does Appium Work?

Appium is implemented as a client/server architecture, communicating with a simple, well-documented protocol, similar to the one used by browsers and web servers.

Appium clients (also known as client libraries) are freely available for most popular programming languages.  Client libraries require a small amount of configuration; then, user code can interact with the client as it would any other code. Appium is only an automation library; it can be used from any test suite and test runner.  This makes it easy to add Appium to existing test suites, in any way your team needs.

Appium Client-Server Model

The Client-Server model gives Appium a lot of flexibility. User code can be written in any language.  Users can write cross-platform automation code without significant extra effort and are isolated from device-specific automation protocols.

Clients and servers can be located on different computers, including across the internet.  In turn, this allows teams to make use of services like Sauce Labs to gain access to a wide variety of devices, increasing their delivery speed and lowering risk. 

Using Appium with JUnit

void canSubmit() {
  WebElement submitButton = <AndroidElement>driver.findElementById("android:id/submit");;
  WebDriverWait wait = new WebDriverWait(driver,10);
  WebElement successBanner = <AndroidElement>driver.findElementById("android:id/success");
  assertEquals(successBanner.getText(), "You have placed your order!");

Using Appium with TestNG

public void canSubmit() {
void canSubmit() {
  WebElement submitButton = <AndroidElement>driver.findElementById("android:id/submit");;

  WebDriverWait wait = new WebDriverWait(driver,10);
  WebElement successBanner = <AndroidElement>driver.findElementById("android:id/success");
  assert "You have placed your order!".equals(successBanner.getText())

Using Appium with Python

class AppiumTest:
    def test_canSubmit(self):
        submit_button = WebDriverWait(driver, 10).until(
          EC.element_to_be_clickable((MobileBy.ID, "android:id/submit"))
        success_banner = WebDriverWait(driver, 10).until(
          EC.visibility_of_element_located((MobileBy.ID, "android:id/success"))
        assert "You have placed your order!" in success_banner.text

Using Appium with NodeJS

describe('can Submit', () => {
    it('works', async () => { // pay attention to `async` keyword
        const submit_selector = 'new UiSelector().resourceId("android:id/submit")'
        const submit_button = await $(`android=${submit_selector}`)
        const success_selector = 'new UiSelector().resourceId("android:id/success")'
        const success_banner = $(`android=${success_selector}`)
        await expect(success_banner.getText() === "You have placed your order!")

The Appium server is responsible for managing devices, listening to and executing client commands, and relaying the results.  The Appium server interacts with devices using the various native automation protocols built into the device operating systems.

Appium servers can connect to existing physical or virtual devices, or start new virtual devices on demand.

The Appium server can run on Windows, Mac OS X, or Linux.

Appium and iOS

Appium supports testing Web and Native iOS apps using the XCUITest automation protocol, as well as the older UIAutomator protocol.  The Appium server can automate either iOS Simulators or real iOS devices but must use a computer with macOS 10.11 or higher.

On real devices, Appium can automate apps in .app or .ipa format.  These applications need to be compiled using a valid iOS Development Certificate and Provisioning Profile.  Appium will install a helper application on the device called “WebDriverAgent-Runner” which requires some configuration before installation.

On iOS simulators, Appium can automate any .app format application compiled for the Simulator.

Appium is also able to automate the mobile version of Safari, allowing teams to test web applications.

Sauce Labs’ test cloud provides both real and virtual iOS Devices, as well as managing WebDriverAgent-Runner.

Appium and Android

Appium supports testing Web and Native Android apps using the UIAutomator2 and older UIAutomator automation protocol.  These are provided by the Android operating system.

UIAutomator2 supports all Android versions above 5.0 (Lollipop).  For versions below this, users must use UIAutomator.

Appium can also interact with the Google-provided Espresso API for UI testing.

Appium can automate both real and virtual devices from Windows, macOS, and Linux.

Appium Capabilities

“Capabilities” is the term used to describe configuration values sent between the Appium Client and the Appium Server.  These values are sent to the server as a JSON dictionary, but most client libraries give users idiomatic ways to configure them.

For example, in Java, users can create a new DesiredCapabilities object, then call the setCapabilities method for specific options:

DesiredCapabilities capabilities = new DesiredCapabilities();
       capabilities.setCapability(CapabilityType.BROWSER_NAME, "iOS");

For more on using Java with Appium, see this blog post.

Capability Variety

Appium has a large number of desired capabilities; most configuration options are available via one capacity or another.  Each driver has its own set of capabilities, in addition to those which apply to all sessions.

For a full list of capabilities, check the Appium documentation at this link.

Device Configuration

Many capabilities are used to describe what device to use, as well as the app under test.  Some of the common ones are:

  • platformName, platformVersion, deviceName – Controls what device to automate, eg an iPhone 11 with iOS 12.

  • app, appActivity, appPackage – Controls what app to automate and, on Android, what activity or package to launch

  • language, locale – Configures the device’s locale and language (Note, this doesn’t change the device’s GPS location)

  • automationName – Selects which automation framework to use.  See Automation Framework for more details

  • safariAllowPopups, safariIgnoreFraudWarning – iOS only; Controls whether Safari allows popups or loading unsecured sites when testing mobile apps

Server Configuration

Some capabilities control the behavior of the Appium server itself, instead of the device under control.  Here are some of the common options:

  • Option 1: newCommandTimeout

  • Option 2: printPageSourceOnFailure

  • Option 3: udid

Vendor-Specific Options

Vendors who provide device clouds can add their own desired capabilities to control cloud-specific options.  For example, here are some of Sauce Labs' capabilities:

  • sauceUsername, sauceAccessKey – Sauce Labs user credentials

  • Build – Add a test to a specific build report

  • tabletOnly – Only select Tablet style devices for this test

  • sauceLabsImageInjectionEnabled – Enable Sauce Labs’ camera image injection feature

Unlike the standard Appium capabilities, vendor-specific capabilities are added in a nested namespace.  For Sauce Labs, that namespace is sauce:options.

DesiredCapabilities capabilities = new DesiredCapabilities();
MutableCapabilities sauceOptions = new MutableCapabilities();
sauceOptions.setCapability(“tabletOnly”, true);
capabilities.setCapability(“sauce:options”, sauceOptions);

Capabilities vs Desired Capabilities

Capabilities are sometimes referred to as “Desired Capabilities”.  This is an older name, no longer present in the W3C Draft Standard.

The “Desired” refers to the ability to request that, instead of an exact match, the Appium server give the closest matching device it has.  This allows users to be much less specific in their configuration.  Should users want only specific devices, they can use Required Capabilities instead.

In practice, almost all existent test code and cloud vendors treat Desired Capabilities as an exact match.

Some cloud vendors have their own ‘fuzzy’ matching process for test platforms.  For example, Sauce Labs allows users to specify device names with a wildcard; “iPhone.*” will match any iPhone.

Appium App Compatibility

Native Apps

Native App is the industry term used to describe applications installed on the device.  These apps are installed directly on the device, being distributed through app stores and corporate device management systems and usually have full access to device features.

Mobile Web Apps

Mobile Web App is the industry term used to describe a website or web application being run on a mobile device.  Usually, people use this term to refer to web applications that are specifically optimized to work on mobile devices.  These apps are not installed; Instead, users open them in a web browser like Mobile Chrome or Mobile Safari.

Hybrid Apps

Hybrid App is the industry term used to describe a combination of Native App and Mobile Web App.  Hybrid apps are installed like a native app, but implement some or all of their functionality via an embedded web browser, called a WebView.

When automating a hybrid application, users can switch between the Native and Web “Contexts” in order to control both parts of their application.  See this page for an example.

Appium vs Other Frameworks

Appium VS Espresso

Espresso is an Open Source framework for automating Android applications.  It’s built into the Android SDK and does not support iOS.

Unlike Appium, Espresso code expects to run on the same machine as the device under automation.  The Espresso API is either compiled into the app under automation or installed side-by-side.  Espresso integrates with Android Studio, however, Espresso code must be written in either Java or Kotlin.

Appium can use Espresso as the driver in an Android test, allowing it to make use of Espresso’s close integration with the device UI, while offering all the advantages of language independence and client/server architecture.  This comes at the cost of slower tests, as Appium introduces an additional layer between automation code and device.

Appium VS XCUITest

XCUITest is Apple’s proprietary testing protocol, used for automating apps on iOS.  

XCUITest can be used directly from XCode, Apple’s IDE, in order to run tests on attached iOS Simulators or Real Devices.  When used in this manner, XCUITest code has to be written in Swift or Objective-C.

Appium uses XCUITest behind the scenes to automate iOS apps, with the added advantage of client/server architecture and language independence.  This comes at the cost of slower tests, as Appium introduces an additional layer between automation code and device.

When running XCUITest code directly, users are limited to a single connected device.  With Appium, multiple real devices or simulators can be used to run tests in parallel, speeding up test cycles.

Appium VS Calabash

  • Calabash is BDD in Cucumber

  • Ruby only

  • Separation of logic and test logic

Learn More in our Guided Bootcamp

Sauce Labs has a free Guided Bootcamp, demonstrating how to build and refactor your first automated test with Appium. Check it out here.