Appium Tip #2: Using Python to Upload and Configure Your Apps and Tests

  October 02, 2015

This is the second blog of our Things You Should Know About Appium blog series, and this time we’ll continue with some basic things around using Python with Appium. For starters, we’ll take a look at basic examples of how to use Python and write a few lines of code to get your applications automatically uploaded to Bitbar Testing and executed on real Android and/or iOS devices.

If you followed through the first blog where we walked through the basic setup, installation of Python, and some other things, you can continue with the basic code example. If you don’t have Python properly installed or you need to check whether everything is ready to go forward, get our free Appium beginner’s guide to verify your setup and learn how to set up other languages.

Python is a worthwhile script language choice for those who want to get down to business quick and simple. The syntax is really easy to learn and implement and there isn’t typically a huge cluster of different files required. Usually, when I want to test some Appium feature, which I haven’t touched before, I turn to python to check it out.

Creating and Running an Upload Script

Before the actual testing can happen, you need to upload your mobile application to the cloud. The app can be in form of APK or IPA – and to get you an effective start, we’ll create a brief upload script here. The upload script example is also available at Github. For IPA files, please also make sure they’re properly built for use in Bitbar Testing.

    import requests
    import base64
    username = 'USERNAME'
    password = 'PASSWORD'
    upload_url = 'http://appium.testdroid.com/upload'
    myfile = '../../../apps/builds/Testdroid.apk'
    def build_headers():
      return { 'Authorization' : 'Basic %s' % base64.b64encode(username+":"+password) }
    files = {'file': ('Testdroid.apk', open(myfile, 'rb'), 'application/octet-stream')}
    r = requests.post(upload_url, files=files, headers=build_headers())
    print r.text

Configure your usernamepassword and myfile attributes with your Bitbar Testing login credentials, and file path for your application (this can be APK or IPA).

Now, you can run the upload script using the following command:

    $ python update.py

As an output you’ll get something like this:

    {"status":0,"sessionId":"99becd25-3183-4c7f-998e-84ef307de7a5","value":{"message":"uploads successful","uploadCount":1,"rejectCount":0,"expiresIn":1800,"uploads":{"file":"99becd25-3183-4c7f-998e-84ef307de7a5/test.apk"},"rejects":{}}}

From this response message, you need to store the application’s ID and file name in Bitbar Testing. The above example is '99becd25-3183-4c7f-998e-84ef307de7a5/test.apk'.

Creating and Running an Appium Test Script with Python

Generic Settings

There are some common settings that you need to set in all scripts regardless of the app type that you are testing. Each testdroid_*.py file needs to be updated with the appropriate values. For this example, here are all the values that you need to edit:

screenshotDir – where should screenshots be stored on your local drive
testdroid_username – the email that you use to sign up for Bitbar Testing
testdroid_password – your password
testdroid_project – the name of the project you want to use. Each project must have a unique name, which can also be modified later. The project will be automatically created if it doesn’t already exist in the cloud.
testdroid_testrun – the name of this test run. Test run names can also be modified later and they don’t have to be unique.
testdroid_app – the location of the app you uploaded to the cloud. Eg. if you uploaded your app using the upload.py script this would look like ’99becd25-3183-4c7f-998e-84ef307de7a5/test.apk’. An alternative way to this is uploading the app through the cloud portal and then use the value ‘latest’ instead of an id path.

Native Android Specific Settings

You can use our template file as an example: testdroid_android.py from Github.

In order to configure this script for your testing needs and for your own app, you can edit two additional capabilities as follows:

appPackage – Java package of the Android app you want to run
appActivity – Activity name for the Android activity you want to launch from your package. Typically this is the main activity.

Native iOS Specific Settings

You can use our template file as an example: testdroid_ios.py from Github.

NOTE! In addition to other configurations and desired capabilities, Appium requires a bundle id to be included in the test script:

bundleId – this is your application’s unique name. For example, it can be used in your Python test script as follows:

    'bundleId': 'com.bitbar.testdroid.BitbarIOSSample'

An Example Template for Appium Desired Capabilities and Python Setup

You can find all the template scripts from our Github repository. There are examples for Android, iOS, Safari, Chrome, and additionally Android hybrid for hybrid apps.

Okay, let’s look at a concrete Python test script example then and what goes in the code:

Imported libraries, bundles and other libraries/dependencies:

    import os
    import sys
    import time
    import unittest
    from time import sleep
    from appium import webdriver
    from device_finder import DeviceFinder
    from selenium.common.exceptions import WebDriverException

Next, let’s create a class with the device, log in and configuration specific desired capabilities. For example:

    class AndroidTest(unittest.TestCase):
        def setUp(self):
        self.screenshotDir = os.environ.get('TESTDROID_SCREENSHOTS') or "/absolute/path/directory"
        testdroid_url = os.environ.get('TESTDROID_URL') or "https://cloud.testdroid.com"
        testdroid_username = os.environ.get('TESTDROID_USERNAME') or "[email protected]"
        testdroid_password = os.environ.get('TESTDROID_PASSWORD') or "password"
        appium_url = os.environ.get('TESTDROID_APPIUM_URL') or 'http://appium.testdroid.com/wd/hub'

To choose a device from Bitbar Testing, you can search for the desired model from our Device Groups page. Once you found the model you want to use, simply copy the full name of the device to testdroid_device variable.

You can also use the DeviceFinder class to automatically find an available freemium device for your test run on Bitbar Testing:

    deviceFinder = None
    testdroid_device = os.environ.get('TESTDROID_DEVICE')
    deviceFinder = DeviceFinder(username=testdroid_username, password=testdroid_password, url=testdroid_url)
    if testdroid_device == "":
      # Loop will not exit until free device is found
      while testdroid_device == "":
            testdroid_device = deviceFinder.available_free_android_device()

Then, to choose correct automation backend for the server, you need to fetch the API level of the device which will be used for a test run:

    apiLevel = deviceFinder.device_API_level(testdroid_device)

Finally, let’s take a look at the desired capabilities configuration with your Python script.

    desired_capabilities_cloud = {}
    desired_capabilities_cloud['testdroid_username'] = testdroid_username
    desired_capabilities_cloud['testdroid_password'] = testdroid_password
    if apiLevel > 17:
      desired_capabilities_cloud['testdroid_target'] = 'Android'
    else:
      desired_capabilities_cloud['testdroid_target'] = 'Selendroid'
    desired_capabilities_cloud['testdroid_project'] = os.environ.get('TESTDROID_PROJECT') # eg.'Demo'
    desired_capabilities_cloud['testdroid_testrun'] = os.environ.get('TESTDROID_TESTRUN') # eg.'MyTest'
    desired_capabilities_cloud['testdroid_device'] = testdroid_device
    desired_capabilities_cloud['testdroid_app'] = 'sample/BitbarSampleApp.apk'
    desired_capabilities_cloud['platformName'] = 'Android'
    desired_capabilities_cloud['deviceName'] = 'Android Phone'
    desired_capabilities_cloud['appPackage'] = 'com.bitbar.testdroid'
    desired_capabilities_cloud['appActivity'] = '.BitbarSampleApplicationActivity'

One more thing! Let’s initiate and set up WebDriver:

    desired_caps = desired_capabilities_cloud;
    self.driver = webdriver.Remote(appium_url, desired_caps)

Appium Python Tips!

You can set Environment Variables to store all the desired capabilities that won’t be changing often. This logic is already included in the sample scripts so all you need to do is set the variables! For example, to set up your Bitbar username, simply apply [email protected] to your environment and the script will then find it with the os.environ.get() function. If the variable doesn’t exist, the script will move on to the next declaration after the ‘or’ keyword.

Playing around with the Android appPackage and appActivity values may be useful when creating tests to automate specific activity screens of your app. There is also a command to launch another app while one is already being tested! This functionality is available for Android only though.

Happy Appium Testing (and weekend)! We’ll be continuing with a new topic on Monday!