This is the fourth in a series of posts that discuss using Appium with Sauce Labs.
Appium, by and large, supports the desired capabilities you’re familiar with from Selenium. However, given that it also exposes mobile-specific functionality, we have some mobile-specific desired capabilities. We even have capabilities that are specific to one mobile platform: iOS or Android. For the full list of capabilities Appium supports, please see the capabilities doc.
The main differences you’ll recognize will have to do with selecting which type of mobile environment you want to automate. Appium has adopted the “Selenium 4″ style of session capabilities, which means that, instead of capabilities like this, for example:
You would specify the following, for Mobile Safari on iOS 7.1:
The new capabilities
deviceName are _required_ for every session. Valid platforms are
To automate a native or hybrid app instead of a mobile browser, you omit the
browserName capability and include the
app capability, which is a fully-resolved local path or URL to your application (.app, .ipa, or .apk). For example:
Sometimes we might want to run an Android test on an older device, and so we need to use Appium’s built-in Selendroid support for older devices. To specify that you want to use the Selendroid backend, keep everything else the same, but specify the
automationName capability, as follows:
And of course, if you’re running any tests on Sauce Labs, make sure to specify the version of Appium you’d like to use with the
Here are some other cross-platform capabilities that affect how your session will run.
Whether to have Appium install and launch your app.
Change the default language on the device. (Emulator only)
Change the default locale on the device. (Emulator only)
Unique device identifier for a connected physical device. Helps Appium determine the device on which to execute tests.
Change the starting orientation of the device. (Emulator only)
When your test starts, have Appium move directly into Webview context.
Don’t reset app state before this session.
(iOS) Delete the entire simulator folder. (Android) Reset app state by uninstalling app instead of clearing app data. On Android, this will also remove the app after the session is complete.
Managing Packages and Activities
Android application execution sometimes involves multiple packages and activities. For example, your application might have a splash screen or users might launch one activity from another. Appium offers
appWaitPackage to allow you to test these more complex scenarios. If you want to wait for activity A to be visible before launching activity B, as you would in the case of a splash screen, your capabilities might look like this:
If you’re would like to run a test suite that is Instrumentation-compatible, you can specify it using the
Running tests using Android’s Instrumentation (which is what powers the Selendroid automation backend) requires that binaries containing tests be signed with the same certificate as the apk. Appium normally uses a self-signed certificate under the hood to take care of this, but you can override Appium’s default behavior by using capabilities to specify the keystore of your choice.
Chrome and Chromedriver
Appium on Android uses Chromedriver for testing mobile browsing and hybrid applications. To facilitate these tests, Appium offers capabilities that expose many of Chromedrivers features. If you’ve written a hybrid application and would like to capture Chromedriver’s performance logging, set
true. If you’re using a Chromium embedded browser, you can specify which socket port Chromedriver should use to connect as a devtools client via
androidDeviceSocket. Appium also allows you to override the Chromedriver version by supplying the
chromedriverExecutable capability. Finally, you can control the amount of time that Chromedriver, and hence Appium, waits for a webview to become active by using the
Many Android applications are launched by intent messages. To enable these scenarios in a testing environment, Appium provides a group of capabilities that allow you launch your application by intent. The intent options are straightforward and map closely to ADB’s
intent command line interface.
Appium also provides a few other pieces of capability magic to help power your tests.
stopAppOnReset ensures that your app is completely stopped between sessions, and is on by default. At the beginning of each session, Appium stops the application process using ADB, and then restarts it. This behavior may not be desireable in cases where a controlling instance launches child processes. Set this capability to
false when you want to keep the controlling process alive between Appium sessions.
Many applications rely on unicode characters. Unfortunately, Android’s UI Automator framework silently strips everything that is not in the ASCII range. So sending, say,
sūkṣma, just sends
skma to the application under test. By setting
true, Appium encodes strings using modified UTF-7, then decodes it back into the full character in the IME on the device. That prevents data loss when working with unicode strings. You can use
resetKeyboard to ensure the keyboard is returned to its original state (i.e., returned to the keyboard that was active before we switched to the Unicode keyboard) after running Unicode tests with the
Finally, Appium provides the
ignoreUnimportantViews which calls the
setCompressedLayoutHierarchy() UiAutomator function. This capability can speed up test execution, since Accessibility commands will run faster, ignoring some elements. The ignored elements will not be findable, which is why this capability has also been implemented as a toggle-able setting as well as a capability.
For iOS tests, there is a pretty large difference between what we can control on an iOS simulator versus and iOS real device. This is because we can modify the various settings files that determine the simulator behavior on the host machine, whereas we have no access to the bits of a real device that determine the equivalent behavior. Thus the iOS section is divided into two: capabilities that work everywhere and capabilities that work only on simulators.
General iOS Capabilities
Sometimes, we want to test against an app that is already installed on the simulator or device, and we don’t have an .app or .ipa file locally. In that case, we can use the
bundleId capability to tell Appium to simply try to automate the existing app (of course it needs to be signed and valid for your device):
When launching iOS tests, we use Apple’s Instruments binary. Instruments is unfortunately quite flakey and sometimes simply hangs on startup. The only thing we can do about that is time out and try again. You can fine-tune the timeout value (in milliseconds) after observing how long it should take on your particular configuration for Instruments to launch the simulator successfully:
After Instruments launches a test session, Appium tries to make sure that it doesn’t let your test code keep running until it knows your app has actually launched. To determine this, it checks to see whether there are any elements in your app. For whatever reason, some apps have trouble reporting that there are any such elements, and so the session never begins. In these cases, you can actually customize the UIAutomation script we use to determine the test can proceed. For example, you might just tell Appium to wait 5 seconds and continue, assuming the app is ready:
If you’re starting up a webview-based app, or a web test using Safari, Appium will attempt to establish a remote debugger session with the webview so that it can send it the necessary web automation commands. Sometimes the connection isn’t established instantly and we have to retry. You can customize the number of times we retry before giving up. The default is 8.
Sometimes your application or the operating system will throw up alerts during execution. If you don’t care about handling these intentionally using the WebDriver alerts API, you can tell Appium to simply accept or dismiss any that it can, with these two capabilities (which are mutually exclusive, of course):
If your app doesn’t have its localized strings in
en.lproj, you can specify exactly where Appium should look to find them (if you want to use the string translation features):
You can send command-line arguments that your app can use to modify its behavior (say if you want to set a backend server address, or something), using the
Appium uses Apple’s UIAutomation’s typing methods to send keystrokes to your app’s input fields. Sometimes we’ve observed that UIAutomation tries to do it too quickly and messes up (just like a real user, perhaps?). In some cases, telling it to slow down helps. You can do this using the
interKeyDelay capability (in milliseconds). This will cause extra time to be added between each keystroke. You can also change the strategy that Appium uses to send keys entirely. There are three:
oneByOne (each key is typed on its own),
grouped (the default, where we send the whole string to UIAutomation and let it figure it out), and
setValue, where we bypass the keyboard entirely and simply set the value of the field.
It is sometimes convenient to debug what’s going on with your app by looking at your app’s logs or the iOS simulator logs. You can extract these using the WebDriver log API in your test code. You can also tell Appium to simply show you those logs, interleaved with its own logs:
Sometimes, when trying to take a screenshot of an app with a lot of elements, it can take UIAutomation an extremely long time to generate the image. Sometimes it takes so long that it runs afoul of a timeout we have set to make sure the screenshot command doesn’t hang forever. If you get timeouts waiting for screenshots, you might want to bump the default (which is 10 seconds) to something higher. Note that this capability is in seconds!
Simulator-only iOS Capabilities
The following capabilities will only work on the simulator, because they involve changing files on the system that hosts the simulator (which obviously won’t work on a real device).
First of all, we use a special tool called instruments-without-delay to work around a limitation of Apple’s UIAutomation, which inserts an artificial 1-second delay between _every_ automation command. Usually there are no problems injecting this tool into the automation engine, but if you want to be absolutely sure it’s not causing problems, you can always turn it off with:
You can set the calendar format the device uses:
You can make sure that the device has location services enabled, and authorized for your app (which requires you to also tell us the
bundleId of your app). This prevents a nasty authorization box from popping up in the middle of your test!
Finally, if you have a test setup where you rely on keychain data for a simulator, you can instruct Appium not to wipe this data during its reset process (where it would normally trash it for total cleanliness):
That wraps up this deeper dive into the wide and weird world of Appium’s capabilities! As mentioned earlier, keep an eye on the Appium docs for any new ones that crop up. Also note that for good and practical reasons, some capabilities aren’t allowed on Sauce Labs (for example, you won’t have an Android keystore on any of our freshly-created VMs, so it doesn’t make sense to say that it’s supported). Happy testing!