Guides

Appium with Python and pytest

A working pytest suite that drives an Android build on a hosted SpawnDroid runner, with fixtures, waits and the exact environment variables.

This is a complete pytest setup for one Appium session. The only inputs are the WebDriver URL, device serial and package from the session response.

Install

pip install Appium-Python-Client pytest

The fixture

conftest.py
import os
import pytest
from appium import webdriver
from appium.options.android import UiAutomator2Options

@pytest.fixture
def driver():
    options = UiAutomator2Options().load_capabilities({
        "platformName": "Android",
        "appium:automationName": "UiAutomator2",
        "appium:udid": os.environ["SPAWNDROID_UDID"],
        "appium:appPackage": os.environ["SPAWNDROID_APP_PACKAGE"],
        "appium:autoGrantPermissions": True,
    })
    driver = webdriver.Remote(
        os.environ["SPAWNDROID_WD_URL"],
        options=options,
    )
    yield driver
    driver.quit()

Do not set appium:app. The build is already installed on the session.

The test

test_checkout.py
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

def test_add_to_cart(driver):
    wait = WebDriverWait(driver, 20)
    wait.until(
        EC.element_to_be_clickable(
            (AppiumBy.ACCESSIBILITY_ID, "Add to cart")
        )
    ).click()

    total = wait.until(
        EC.visibility_of_element_located(
            (AppiumBy.ID, "com.acme.checkout:id/total")
        )
    )
    assert total.is_displayed()

Run it

Start a runner first, then export the three values it returns:

export SPAWNDROID_WD_URL='https://stream.spawndroid.io/ci/sess_…/token/wd/hub'
export SPAWNDROID_UDID='emulator-5554'
export SPAWNDROID_APP_PACKAGE='com.acme.checkout'
pytest -q --junitxml=reports/junit.xml

On SpawnDroid, a session that goes ready and then runs this suite consumes device-minutes from ready to teardown. Report the result on teardown so the run closes with passed or failed; see CI tests.

In CI

The pytest command is the same. The GitHub Action exports SPAWNDROID_WD_URL, SPAWNDROID_UDID and SPAWNDROID_APP_PACKAGE into the test command, so this fixture needs no change:

- uses: kl3jvi/spawndroid/actions/android-test@v1
  with:
    api-key: ${{ secrets.SPAWNDROID_API_KEY }}
    app-path: app/build/outputs/apk/debug/app-debug.apk
    command: pytest -q --junitxml=reports/junit.xml
    report-path: reports/junit.xml

Run it on SpawnDroid

Start with the cloud Appium guide, or create a free workspace with 200 device-minutes a month.

Was this page helpful?

On this page