Skip to main content

pytest-appium-scheduler

pytest-appium-scheduler is a pytest plugin for Appium test execution with:

  • device-aware scheduling
  • pytest-xdist parallel execution
  • function and session driver lifecycle control
  • per-test device targeting via markers
  • debug and trace logs for worker/device visibility

The package is published as pytest-appium-scheduler. After publishing, both of these forms work with pip:

pip install pytest-appium-scheduler

Features

  • distributed mode: spread Appium tests across available devices
  • all mode: run each Appium test on every matching device
  • @pytest.mark.device(...) and @pytest.mark.devices(...)
  • shared device pool with worker-safe leasing
  • driver and device fixtures
  • extensible hooks:
    • pytest_appium_create_driver
    • pytest_appium_modify_caps
  • compact debug output via --appium-debug
  • verbose lifecycle tracing via --appium-trace

Installation

pip install pytest_appium_scheduler

This installs:

  • pytest
  • pytest-xdist
  • PyYAML
  • appium-python-client

Quick Start

Create a device config, for example from device.example.yaml:

devices:
  - name: emulator-5554
    url: http://127.0.0.1:4723
    caps:
      platformName: Android
      automationName: UiAutomator2
      udid: emulator-5554
      systemPort: 8201
      appPackage: com.android.settings
      appActivity: .Settings

  - name: emulator-5556
    url: http://127.0.0.1:4723
    caps:
      platformName: Android
      automationName: UiAutomator2
      udid: emulator-5556
      systemPort: 8202
      appPackage: com.android.settings
      appActivity: .Settings

Write tests:

import pytest


def test_open_app(driver):
    assert driver.session_id


def test_device_fixture(device):
    assert device.name


@pytest.mark.device("emulator-5556")
def test_only_on_specific_device(driver):
    assert driver.session_id


@pytest.mark.device(platform="Android")
def test_only_android(driver):
    assert driver.session_id


class TestNoDevice:
    def test_plain_pytest_case(self):
        assert True

Run in distributed mode:

pytest tests \
  --appium-config=device.yaml \
  --appium-mode=distributed \
  -n 2

Run in all mode:

pytest tests \
  --appium-config=device.yaml \
  --appium-mode=all \
  -n 2

Scheduling Modes

distributed

Use devices as a shared execution pool.

  • Appium tests are scheduled onto matching devices
  • when workers are more than devices, extra workers can stay idle
  • non-Appium tests can still run on idle workers
  • when workers are fewer than devices, workers will rotate across devices instead of permanently starving one

all

Run every matching Appium test on every matching device.

  • each device gets its own execution stream
  • workers do not compete for the same device at the same time
  • non-Appium tests can still run on idle workers

Fixtures

driver

Provides an Appium driver.

device

Provides the selected device model:

def test_device(device):
    assert device.name
    assert device.url
    assert device.caps

Markers

Limit a test to one or more devices:

@pytest.mark.device("pixel_7")
def test_only_pixel(driver):
    ...


@pytest.mark.devices(["pixel_7", "iphone_14"])
def test_specific_devices(driver):
    ...


@pytest.mark.device(platform="iOS")
def test_only_ios(driver):
    ...

Behavior:

  • unmarked tests: all configured devices are eligible
  • unknown device marker: skipped with warning
  • unmatched filter: skipped with warning

CLI Options

--appium-mode=distributed|all
--appium-config=PATH
--appium-device=NAME
--appium-driver-scope=function|session
--appium-retry-session=1
--appium-debug
--appium-trace

Useful examples

Select one device only:

pytest tests \
  --appium-config=device.yaml \
  --appium-device=huawei_p60

Reuse one driver per device session:

pytest tests \
  --appium-config=device.yaml \
  --appium-driver-scope=session

Show compact scheduling logs:

pytest tests \
  --appium-config=device.yaml \
  --appium-mode=distributed \
  --appium-debug \
  -n 2 -q -s

Show verbose lifecycle trace:

pytest tests \
  --appium-config=device.yaml \
  --appium-mode=distributed \
  --appium-trace \
  -n 2 -q -s

Custom Hooks

Modify capabilities

def pytest_appium_modify_caps(caps):
    updated = dict(caps)
    updated["newCommandTimeout"] = 120
    return updated

Create your own driver

pytest_appium_modify_caps is applied before pytest_appium_create_driver, so your custom driver hook receives the updated capabilities.

def pytest_appium_create_driver(device):
    from appium import webdriver
    from appium.options.common.base import AppiumOptions

    options = AppiumOptions()
    options.load_capabilities(device.caps)
    return webdriver.Remote(device.normalized_url(), options=options)

Debug Output

With --appium-debug:

[appium] gw0    target=huawei_p60        device=huawei_p60        PASSED  tests/test_real_device.py::test_open_app  session-123

With --appium-trace:

[pytest-appium-scheduler] action=device-acquire worker=gw0 target=huawei_p60 device=huawei_p60 details=nodeid=...

Development

Create a local environment:

python3 -m venv .venv
source .venv/bin/activate
pip install -e .

Run tests:

.venv/bin/python -m pytest tests/test_plugin.py -q

Build distributions:

.venv/bin/python -m pip install build
.venv/bin/python -m build

License

MIT. See LICENSE.

Release files for pytest-appium-scheduler 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pytest-appium-scheduler 0.1.1
File Size Uploaded
pytest_appium_scheduler-0.1.1.tar.gz 22.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pytest-appium-scheduler 0.1.1
File Interpreter ABI Platform
pytest_appium_scheduler-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size:43.5 kB

Release files / pytest_appium_scheduler-0.1.1.tar.gz

Download URL pytest_appium_scheduler-0.1.1.tar.gz
Size 22.1 kB
Tags Source
SHA-256 checksum
How to use checksums
9270c32a75be3516fb6d64b2d6e2e44f8bcc67b49200cff130b90d34b9ec01de
BLAKE2b-256 checksum
How to use checksums
de5d3ec782ca31f4b32cdf87db8748de0b43c0cf9dd344cd8bc61bfee1c2886b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.10

Release files / pytest_appium_scheduler-0.1.1-py3-none-any.whl

Download URL pytest_appium_scheduler-0.1.1-py3-none-any.whl
Size 21.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
300b1f9d7d8a7c285eda45fcd4c7e115cc8238c2313ba4e78a153988e8c9a718
BLAKE2b-256 checksum
How to use checksums
1e8025ec626ba1d0536be5e49bbe3a304719691ca87f062e53db7e8d64413c6e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.10

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page