Appium tutorial: Execute Python tests on mobile devices

This Appium tutorial will show you how to run automated tests on a real physical device. We estimate skimming through this post will take you 10 minutes. We estimate working through this post, step by step, will take you about 90 minutes. In this post we will cover getting setup with Appium, interfacing with real devices, writing and running Appium tests. We also briefly introduce you to multiple ways to locate UI elements.

NOTE: If you have an Android phone handy, you can follow along easily. If not, you may be interested in a previous post showing you how to get started with Appium on an emulator.


Why this post?

There are two compelling reasons for this post.
1. Mobile devices are taking over the world
In recent times there is a lot of interest in mobile testing. And rightly so. The mobile space is growing. The apps are the new cool thing. The mobile space is ideal for software testers looking to learn new things and keep current.
2. Lack of high quality tutorials on mobile automation
One big challenge in the mobile automation space is the the limited amount of information about the technologies. Quality sources of information on mobile automation is very limited.

So here is a high quality and informative tutorial for the hands-on tester who wants to get started with Appium and mobile automation on a physical mobile device.


Why Appium?

There are quite a few number of tools out there in the mobile automation market like MonkeyTalk, Calabash, Robotium, etc. Each has its own advantages and limitations. Some of these tools require an agent to be installed, the application has to be recompiled so that the tool can interact with the mobile app, etc. However Appium is built on the idea that testing native apps shouldn’t require including an SDK or recompiling the app. Appium is also an open source project – so if you are not happy with it, you can contribute and enhance it. Appium tests run against both on iOS and Android. For me, Appium (while still being extremely immature), looks to be the standout technology that will own the mobile UI automation space. Appium reminds me of the early Selenium versions I used. Based on history, I think Appium will be the front-runner in the mobile UI automation space.


Step by step Appium tutorial

We have already shown you how to run an Appium test using an emulator in one of our previous posts. In this post, I will show you how to test an app using a real device. Being a tennis fan, I decided to test a tennis app. On my Android phone, I downloaded the ATP/WTA app and decided to automate some of the functionality of this app. I will also show you how to navigate through different pages in the app using different locator strategies, get data from a table using Appium and Python and how to use the uiautomator to find UI components of the page.

Overview
1. Appium setup
2. Connect to an Android device
3. Select an app to test, get its package and activity name
4. Use uiautomatorviewer to find UI components of the application
5. Write the test
6. Start and launch Appium server console
7. Run the test
8. View the test result

STEP 1: Appium setup
Download and install Android SDK and Appium along with Appium’s client libraries for Python. Installations are fairly straight forward. However if you need help, please refer to the setup section in our previous blog for a more detailed process on how to set up Appium on your machine.

STEP 2: Connect to an Android device
You have to enable USB debugging in your phone to be able to run your test scripts. For this, first, you need to enable “Developer options” by navigating to Settings/About Phone and tapping build number seven times. You will get a notification saying that you’re now a developer. Ignore it – you are still a tester ;). Once you are a developer you need to navigate to “Developer options” and enable the USB debugging option. You can refer to this link for more details

Build Number in Android Settings

Enable USB Debugging

Developer Option in Android settings

Note: On some devices, you may have to download some device drivers to connect your phone to the PC

STEP 3: Select an app to test, get its package and activity name
You can go to Google Play Store and download the ATP/WTA app. We will automate some of the functionality like navigating to the ATP Singles Rankings view to assert that Novak Djokovic is the first player listed and also get his personal details from the table in players view.

In order to start the app we would need the app Package and Activity name. We can get these details from the apk file of the app. Instead of downloading the apk file and looking into app manifest file for this detail, we can also download some really cool apps which can get you these details. Apk Info is one such app which you can download from Play Store and get the app Package and Activity details. Just download the app and click on Apk Info Icon which will list all the apps on your device. Click on your app to get the details required as shown below

APK Info for getting the Package and Activity name

Details of ATP WTA app

STEP 4: Use uiautomatorviewer to find UI components of the application uiautomatorviewer is a GUI tool to scan and analyze the UI components of an Android application. To click or to navigate to any components in your app you need to identify the UI components of your application. Using uiautomatorviewer you can take the snapshot of the UI screen on any Android device that is connected to your machine. You can then inspect the layout hierarchy and view the properties of the individual UI components that are displayed on the device.

Connect your Android device to your machine and open the app you are testing. In your machine open a terminal window and navigate to the path $android-sdk /tools and run the command to open Uiautomatorviewer

$ uiautomatorviewer

To capture a screen, click the “Device Screenshot button” in the uiautomatorviewer tool. The screenshot of the page in your device is captured. You can move over the snapshot in the left-hand panel to see the UI components identified by the uiautomatorviewer. You can view the component’s properties listed in the lower right-hand panel, and the layout hierarchy in the upper right-hand panel.
UI Automator Viewer

STEP 5: Write the test
We will launch the ATP WTA app using the package and activity name we found out and then navigate through various pages using different locator strategies. While we do not recommend using multiple locator strategies, we are doing so in this tutorial only to make you aware of your options. Then we will confirm that Novak Djokovic is the top player listed in ATP Singles Rankings list view and get his personal details from a table in Players view.

"""
Qxf2: Example script to run one test against ATP_WTA app using Appium
The test will navigate to ATP Singles Rankings list and confirm that Novak
Djokovic is the top player listed and get his personal details from a table.
 
"""
 
import unittest, time, os
from appium import webdriver
from time import sleep
 
class Android_ATP_WTA(unittest.TestCase):
    "Class to run tests against the ATP WTA app"
    def setUp(self):
        "Setup for the test"
        desired_caps = {}
        desired_caps['platformName'] = 'Android'
        desired_caps['platformVersion'] = '4.4'
        desired_caps['deviceName'] = '$ Your device name'
        # Since the app is already installed launching it using package and activity name
        desired_caps['appPackage'] = 'atpwta.live'
        desired_caps['appActivity'] = '.activity.Main'
        # Adding appWait Activity since the activity name changes as the focus shifts to the ATP WTA app's first page
        desired_caps['appWaitActivity'] = '.activity.root.TournamentList'
        self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
 
    def tearDown(self):
        "Tear down the test"
        self.driver.quit()
 
    def test_atp_wta(self):
        "Testing the ATP WTA app "
        self.driver.implicitly_wait(30)
        time.sleep(5)
 
        # click on Navigation Bar MainMenu by finding element by xpath
        menubar = self.driver.find_element_by_xpath("//android.widget.Spinner[@resource-id='atpwta.live:id/NavBarMainMenuSpinner']")
        menubar.click()
 
        # From list of options available click on Rankings by finding element using uiautomator
        rankings = self.driver.find_element_by_android_uiautomator('new UiSelector().text("Rankings")')
        rankings.click()
 
        # click on ATP Singles by finding element using id
        singles = self.driver.find_element_by_id('atpwta.live:id/RankingsListItem')
        singles.click()
 
        # Assert that Novak Djokovic is the top listed player
        elmnt = self.driver.find_element_by_id('atpwta.live:id/Player1TV')
        self.assertEqual('Novak Djokovic', elmnt.get_attribute('text'))
        print elmnt.get_attribute('text')
 
        elmnt = self.driver.find_element_by_xpath("//android.widget.LinearLayout[@index=0]")
        elmnt.click()
 
        # Print the contents of Table listed for the top ranked player
        table = self.driver.find_element_by_android_uiautomator("new UiSelector().className(android.widget.TableLayout)")
        rows = table.find_elements_by_class_name('android.widget.TableRow')
        for i in range(0, len(rows)):
            cols = rows[i].find_elements_by_class_name('android.widget.TextView')
            for j in range(0, len(cols)):
                print(cols[j].get_attribute('text')+" -- "),
            print("")
 
 
#---START OF SCRIPT
if __name__ == '__main__':
    suite = unittest.TestLoader().loadTestsFromTestCase(Android_ATP_WTA)
    unittest.TextTestRunner(verbosity=2).run(suite)

STEP 6: Start and launch Appium server
Start Appium server console by double-clicking on the Appium file. Click on the ‘rocket’ icon to launch the Appium node server.
Please refer to the 6th and 7th step of our previous blog if you need more details on starting appium server.
Start Appium

STEP 7: Run the test
You can run the test any way you like. We will run it using the command prompt. The app gets launched in your device and navigates to a different screen.

ATP WTA Live PagePlayers PageATP Rankings List Page

STEP 8: View the test result
BrowserStack Test Result


Game. Set. Match. You learnt how to do mobile automation using Appium on a real device! If you are still hungry for more, take a tour of our open-sourced web and mobile automation framework.


Subscribe to our weekly Newsletter


View a sample



91 thoughts on “Appium tutorial: Execute Python tests on mobile devices

  1. Hi,

    I have followed the exact steps given here, however I am getting the below error. I have restarted appium server several times. Still I am getting the same error.

    Error
    Traceback (most recent call last):
    File “C:\Python27\lib\unittest\case.py”, line 320, in run
    self.setUp()
    File “D:\python_program\calci\atp.py”, line 20, in setUp
    self.driver = webdriver.Remote(‘http://localhost:4723/wd/hub’, desired_caps)
    File “C:\Python27\lib\site-packages\appium\webdriver\webdriver.py”, line 36, in __init__
    super(WebDriver, self).__init__(command_executor, desired_capabilities, browser_profile, proxy, keep_alive)
    File “C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.py”, line 87, in __init__
    self.start_session(desired_capabilities, browser_profile)
    File “C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.py”, line 141, in start_session
    ‘desiredCapabilities’: desired_capabilities,
    File “C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.py”, line 199, in execute
    response = self.command_executor.execute(driver_command, params)
    File “C:\Python27\lib\site-packages\selenium\webdriver\remote\remote_connection.py”, line 395, in execute
    return self._request(command_info[0], url, body=data)
    File “C:\Python27\lib\site-packages\selenium\webdriver\remote\remote_connection.py”, line 463, in _request
    resp = opener.open(request, timeout=self._timeout)
    File “C:\Python27\lib\urllib2.py”, line 429, in open
    response = self._open(req, data)
    File “C:\Python27\lib\urllib2.py”, line 447, in _open
    ‘_open’, req)
    File “C:\Python27\lib\urllib2.py”, line 407, in _call_chain
    result = func(*args)
    File “C:\Python27\lib\urllib2.py”, line 1228, in http_open
    return self.do_open(httplib.HTTPConnection, req)
    File “C:\Python27\lib\urllib2.py”, line 1198, in do_open
    raise URLError(err)
    URLError:

    Also at appium side I am getting below error,

    Launching Appium server with command: C:\Program Files (x86)\Appium\node.exe lib\server\main.js –address 127.0.0.1 –port 4723 –pre-launch –platform-name Android –platform-version 23 –automation-name Appium –device-name “38fcda2f” –log-no-color
    > info: [debug] Starting Appium in pre-launch mode
    > info: Pre-launching app
    > info: [debug] No appActivity desired capability or server param. Parsing from apk.
    > info: [debug] No appPackage desired capability or server param. Parsing from apk.
    > error: No app set; either start appium with –app or pass in an ‘app’ value in desired capabilities, or set androidPackage to launch pre-existing app on device
    > info: [debug] Got configuration error, not starting session
    > info: [debug] Cleaning up appium session
    > error: Could not pre-launch appium: Error: No app set; either start appium with –app or pass in an ‘app’ value in desired capabilities, or set androidPackage to launch pre-existing app on device
    >

    1. Hii Roshni,
      1. Are you testing in Simulator or real physical device?
      2. Do you have the app already installed, if not then get the .apk file of the app and set ‘app’ field in desired capabilities with the path of the .apk file .Refer https://qxf2.com/blog/appium-mobile-automation/ on how to set desired capabilities for ‘app’ field.
      3. If this doesn’t solve your problem then kindly tell us what desired capabilities are you passing in setup code.

      1. Hi Rohan,
        Thanks for the quick reply. I have already installed the app mentioned in this article on my device. I am not using any simulator.
        The below are the desired capabilities which I have mentioned in the program,
        def setUp(self):
        “Setup for the test”
        desired_caps = {}
        desired_caps[‘platformName’] = ‘Android’
        desired_caps[‘platformVersion’] = ‘6.0.1’
        desired_caps[‘deviceName’] = ’38fcda2f’
        # Since the app is already installed launching it using package and activity name
        desired_caps[‘appPackage’] = ‘atpwta.live’
        desired_caps[‘appActivity’] = ‘.activity.Main’
        # Adding appWait Activity since the activity name changes as the focus shifts to the ATP WTA app’s first page
        desired_caps[‘appWaitActivity’] = ‘.activity.root.TournamentList’
        self.driver = webdriver.Remote(‘http://127.0.0.1:4722/wd/hub’, desired_caps)

        Also, this http://127.0.0.1:4722 , I have mentioned in appium server settings.

      2. Hi Roshini,
        Sorry for the delayed response. Your desired capabilities seem to be fine. I am not sure why you are getting the error. Probably you can try these two things
        1) Double check the appPackage and appActivity name of the app. If that’s fine try the below approach also
        2) Get the .apk file of the app and set ‘app’ field in desired capabilities with the path of the .apk file.

        Thanks & Regards
        Avinash Shetty

  2. Hi
    I am e desired_caps[‘platformName’] = ‘Android’
    ^
    IndentationError: unindent does not match any outer indentation level

    What am I doing wrong ?

    1. Hi,
      Have you mixed up tabs and space to indent the python code by any chance? If not can you post your complete code so that i can debug it better?

  3. How to run multiple test cases one after other without killing Appium session?
    I do not want to restart the app in between a test case is completed and second test case starts to run.

    1. Hi
      The setup and teardown methods are the ones that bring up an Appium session & kill it after test case execution(I am assuming you are using unittest — Unit testing framework). To run the setup and teardown only once before executing set of test cases looks like you have to use the setUpClass and tearDownClass. Pls refer – https://stackoverflow.com/questions/8389639/unittest-setup-teardown-for-several-tests

      P.S We have started using pytest as our test runner.

  4. I’m getting exception

    Traceback (most recent call last):
    File “/Users/dev/PycharmProjects/appiumLaunch/s.py”, line 14, in
    driver = webdriver.Remote(‘http://localhost:4723/wd/hub’, desired_caps)
    File “/Users/dev/PycharmProjects/appiumLaunch/venv/lib/python2.7/site-packages/appium/webdriver/webdriver.py”, line 36, in __init__
    super(WebDriver, self).__init__(command_executor, desired_capabilities, browser_profile, proxy, keep_alive)
    File “/Users/dev/PycharmProjects/appiumLaunch/venv/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py”, line 154, in __init__
    self.start_session(desired_capabilities, browser_profile)
    File “/Users/dev/PycharmProjects/appiumLaunch/venv/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py”, line 243, in start_session
    response = self.execute(Command.NEW_SESSION, parameters)
    File “/Users/dev/PycharmProjects/appiumLaunch/venv/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py”, line 312, in execute
    self.error_handler.check_response(response)
    File “/Users/dev/PycharmProjects/appiumLaunch/venv/lib/python2.7/site-packages/selenium/webdriver/remote/errorhandler.py”, line 242, in check_response
    raise exception_class(message, screen, stacktrace)
    selenium.common.exceptions.WebDriverException: Message: An unknown server-side error occurred while processing the command. Original error: Unable to launch WebDriverAgent because of xcodebuild failure: “xcodebuild failed with code 65”. Make sure you follow the tutorial at https://github.com/appium/appium-xcuitest-driver/blob/master/docs/real-device-config.md. Try to remove the WebDriverAgentRunner application from the device if it is installed and reboot the device.
    Process finished with exit code 1

    Please let me know whats wrong with below code

    if driver is None:
    driver = webdriver.Remote(‘http://localhost:4723/wd/hub’, desired_caps)
    print(“defined driver”)
    else:
    print(‘driver is not None’)

  5. Hi Team,

    Thanks for writing such a detailed artcile. I have followed all the steps mentioned in the arcticle. However when i run the script, immediately i get the below error:

    This file doesn’t have an app associated with it for performing this action. Please install an app or, if one is already installed, create an association in the default Apps settings page

    I looked for a solution online, but didn’t get any help. Request you to help me solve this issue.

    1. Hi Pradeep,
      Can you check that you have used the proper package and activity name of the app and also have you downloaded the app in your device?.

      1. Hi Annapoorani,

        Please find the package name and app activity name i’m using below:

        desired_caps[‘platformName’] = ‘Android’
        desired_caps[‘platformVersion’] = ‘4.4’
        desired_caps[‘deviceName’] = ‘$ $ Your device name’
        # Since the app is already installed launching it using package and activity name
        desired_caps[‘appPackage’] = ‘atpwta.live’
        desired_caps[‘appActivity’] = ‘atpwta.live.activity.Main’

        I have installed the app as well.

  6. Hi Sir , Please help me on below query:

    I created two python scripts. In launch.py, it goes through the onboarding part of our app, and in login.py, it goes through the rest of the app. My issue is that in order for login to work, the app needs to be on the screen that launch.py ends on. So what i’m looking for is how I can run launch.py, then run login.py with the app in the same state as python1 left it.

      1. Hi Mohan,
        i am Really appreciated your help!
        is there any thing on Appium with Python framework for POM and Appium with Robot framework.
        I would appreciate a reply at your earliest convenience.

        Regards
        Raj

  7. Hello, Very Useful tutorial to know about Mobile automation using Python and Appium. Followed the steps mentioned in the article. Used different app then mentioned in the article and able to automate. My only observation is when i am using as mentioned in the __ Main __ method
    suite = unittest.TestLoader().loadTestsFromTestCase(Android_ATP_WTA)
    unittest.TextTestRunner(verbosity=2).run(suite)
    then the setUp() method not initiating so did small change to the above step and ran and it was successfully initiated the setUp() method and the changes are
    def suite():
    suite = unittest.TestSuite()
    suite.addTest(Android_Actiwoo(‘test_actiwoo’))
    #suite.addTest(Android_Actiwoo(‘test_quickguide’))
    return suite

    if __name__ == ‘__main__’:
    #suite = unittest.TestLoader().loadTestsFromTestCase(Android_Actiwoo)
    runner = unittest.TextTestRunner(verbosity=2)
    runner.run(suite())

Leave a Reply

Your email address will not be published. Required fields are marked *