Appium Tip #11: How To Speed Up Device Acquisition for Tests

  November 24, 2015

We’ll continue our Things You Should Know About Appium blog series with a new topic that helps you to get your Appium tests executed on a real device cloud instantly. Historically through different versions of development tools and platforms (e.g. from Eclipse to Android Studio, and all possible different Xcode versions) the device connection has been one of those things that raise frustration among developers and testers.

Getting devices configured and set up for ADB or Xcode access (with all different stunts required) is no longer a problem as devices can be nicely and quickly acquired from the cloud and you’ll have your tests running in few seconds.

Acquiring a device for Appium test is trivial nowadays. As we’ve been describing how to set up an environment for Appium testing, with using specific language of your choice, you can also define in your script what devices you want to use for testing. But if you don’t have a proper Appium environment, it won’t work as expected anyway. Download our free Appium beginner’s guide and follow the instructions of setting up a proper Appium environment.

Most importantly, you should always run your test scripts on as many real Android and/or iOS devices as possible to get the best outcome from your testing effort. The great thing also in test automation is that it can be done simultaneously and even if you are using client-side execution of Appium you can start multiple test runs on devices that are available at that moment. Also, you can start test runs with these examples run by run and get everything thoroughly tested.

This blog explains and showcases an example written in Python of how to find an available device for your testing.

Device Finder for Appium Tests Using Real Devices Online

First, we build a path for API call to get list of all devices. As guided in Bitbar API document, you should use in initialization. Also, you can now use API Key authentication instead of OAuth authentication.

import requests, sys
class DeviceFinder:
    # Cloud URL (not including API path)
    url = None
    """ Full constructor
    def __init__(self, url="", download_buffer_size=65536):
        self.cloud_url = url
        self.download_buffer_size = download_buffer_size
    """ Append dictionary items to header
    def _build_headers(self, headers=None):
        hdrs = {}
        hdrs["Accept"] = "application/json"
        if headers != None:
        return hdrs
    """ Returns list of devices
    def get_devices(self, limit=0):
        return self.get("devices?limit=%s" % (limit))
    """ GET from API resource
    def get(self, path=None, get_headers=None):
        url = "%s/api/v2/%s" % (self.cloud_url, path)
        res =  requests.get(url, headers=self._build_headers(get_headers))
        if res.ok:
            return res.json()
            print "Could not retrieve devices."
            sys.exit -1

The API key is generated per user when signing up for the service. The API key significantly simplifies the login procedure as you are not required to use access token all the time. The API key also improves the security model of passing information between two ends as you are not required to play with your credentials and expose those with your test scripts.

The API key is configurable under your profile on Bitbar Testing, Profile -> My account -> API key:

And if you need to reset your API key, just click ‘Reset API key’ button next to the key. The text string is enabled for copy-paste.

Configuring Devices for Tests in Your Desired Capabilities

Appium provides a way to specify what device will be used for a test run. As described earlier in this blog series, it can be done through desired capabilities. Also, it can be further specified as a table – and even using a cross-platform approach (e.g. listing both Android and iOS devices).

Here a basic example of how to list devices in Python for these described scripts:

   AndroidDeviceList = [“Acer Iconia Tab 8 A1-840FHD US”,
                        “Asus Google Nexus 7 ME370T 4.3 JWR66Y”,
                        “Dell Venue 8 3840 EU”,
                        “HTC One M7 5.0.2”,
                        “HTC One M9”,
                        “Huawei Honor 6 H60-L01”,
                        “LG Google Nexus 5 6.0”,
                        “Lenovo Lemon K3 K30-T”,
                        “Motorola DROID RAZR HD XT926”,
                        “Motorola Google Nexus 6 XT1100 5.1 EU”,
                        “NVIDIA Shield Tablet”,
                        “Samsung Galaxy Note 5 SM N920R4”,
                        “Samsung Galaxy S5 SM-G900T (T-Mobile) -US”,
                        “Samsung Galaxy Tab 4 10.1 SM-T530NU”,
                        “Sony Xperia Tablet Z”,
                        “Sony Xperia Z SO-02E (Sony Yuga)”,
                        “Xiaomi MI 3 (Tegra 4 powered)”,
                        “Xiaomi Redmi 2 LTE”,
                        “Yota Phone 2 YD201”,
                        “ZTE V5 Red Bull U9180”
   for each device in AndroidDeviceList:
       testdroid_device =  DeviceFinder.getDevice(device)
       if testdroid_device is not None:

That’s pretty basic pseudo-code example to be used for instigator script enabling you to launch the test by running on multiple devices. Let’s look more in-depth on how to acquire Android and/or iOS devices.

Acquiring Any Android Device for Appium Tests (API level tip)

In addition to prior pseudo-code example, you can use more specific search parameters in your device acquisition. For example, you can combine the script below with your instigator script to acquire and access just specific device you want for your test run.

    """ Find available Android device
    def available_android_device(self, limit=0):
        print "Searching Available Android Device..."
        for device in self.get_devices(limit)['data']:
            if device['locked'] == False and device['osType'] == "ANDROID"
               and device['softwareVersion']['apiLevel'] > 16:
                print "Found device '%s'" % device['displayName']
                print ""
                return str(device['displayName'])
        print "No available device found."
        print ""
        return ""

The API level matters in Android and even Appium uses different foundations for older versions of Android. For example, if your app must run on devices with API level below 17, Appium is using Selendroid as a basis and on newer API levels it will use uiautomator. Furthermore, you can use something as follows for checking the API level of any Android device:

    def device_API_level(self, deviceName):
        print "Searching for API level of device '%s'" % deviceName
            device = self.get(path="devices", get_headers={'search':deviceName})
            apiLevel = device['data'][0]['softwareVersion']['apiLevel']
            print "Found API level: %s" % apiLevel
            return apiLevel
        except Exception, e:
            print "Error: %s" % e

Acquiring Any iOS Device for Appium Test Run (Apple iPad Example)

In iOS device acquisition, the OS version isn’t important. Instead, you should pre-define those devices in some table before calling the available_ios_device(). Here is one example of how to use pre-defined devices for this search:

   iOSDeviceList = [“Apple iPad 3 A1416 8.2”,
                    "Apple iPad 4 A1458 8.4",
                    "Apple iPad Air 2 A1566 8.4",
                    "Apple iPad Air A1474 8.1.3",
                    "Apple iPad Air A1474 9.0.2",
                    "Apple iPad Mini 2 A1489 9.0.2",
                    "Apple iPad Mini 3 A1599 9.0.2"
   for each device in iOSDeviceList:
       testdroid_device =  DeviceFinder.getDevice(device)
       if testdroid_device is not None:

In order to find those available iOS devices you can use the following type of script to identify those and get the device up and running with your app and tests just in seconds:

    def available_ios_device(self, limit=0):
        print "Searching Available iOS Device..."
        for device in self.get_devices(limit)['data']:
            if device['locked'] == False and device['osType'] == "IOS":
                print "Found device '%s'" % device['displayName']
                print ""
                return str(device['displayName'])
        print "No available device found."
        print ""
        return ""

Conclusion and The Benefits of Device Finder

Appium provides a great framework for testing but parallel test execution hasn’t been too easy just by defining a group of devices where your app and test should do its heavy-lifting. With these instructions and few examples, you should be able to build tests that 1) get started instantly (as we’re looking those devices that are available at that moment), 2) enable simultaneous test runs (with instigator script where you define devices that you want to run on) and 3) provide you results from devices you see important for your app.

Happy Appium Testing, folks!