Run Python tests when device Slots are limited

Below you can find information on how to organize Python test execution in case of limited device Slots.

Prerequisites

  • Existing test, which is written using PyTest.
  • List of devices, where these tests should be executed.
  • Plan with limited device Slots for the Test Automation.

Parametrize the device UDID

To ensure that tests will be executed on a particular device, it’s better to parametrize the device UDID in a pytest Fixture.
Below you can find an example for a simple Set of parameter values.

import pytest
from appium import webdriver

PROJECT_NAME = "<TEAM_CODE>"
ACCESS_KEY = "mobitru_ak_...."
APPIUM_HUB = "app.mobitru.com"
BROWSER_NAME = "chrome"

@pytest.fixture(scope="function", params=["4C071FDAP002SW", "26281JEGR04493", "R5CY23ZSTNF", "28101FDH3009BP"])
def driver(request):
    """Fixture for setting up and tearing down the Appium driver."""
    desired_capabilities = {
        "platformName": "Android",
        "automationName": "UIAutomator2",
        "browserName": BROWSER_NAME,
        "udid": request.param,
    }
...

Take the Device before the test execution

The Device should be taken in the appropriate Fixture before executing tests.
Below you can find an example for a Fixture with a parametrized device UDID.

import pytest
from appium import webdriver

PROJECT_NAME = "<TEAM_CODE>"
ACCESS_KEY = "mobitru_ak_...."
APPIUM_HUB = "app.mobitru.com"
BROWSER_NAME = "chrome"

@pytest.fixture(scope="function", params=["4C071FDAP002SW", "26281JEGR04493", "R5CY23ZSTNF", "28101FDH3009BP"])
def driver(request):
    """Fixture for setting up and tearing down the Appium driver."""
    desired_capabilities = {
        "platformName": "Android",
        "automationName": "UIAutomator2",
        "browserName": BROWSER_NAME,
        "udid": request.param,
    }
    # Initialize the Appium driver
    driver = webdriver.Remote(
        command_executor=f"https://{PROJECT_NAME}:{ACCESS_KEY}@{APPIUM_HUB}/wd/hub",
        desired_capabilities=desired_capabilities
    )

    # send the Appium driver instance to a Test
    yield driver    

Release the Device after

The Device should be released after the test execution to make the device Slot free.
It can be made in the same Fixture with a parametrized device UDID.
Below you can find an example of the entire Test.

import pytest
from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# Constants
PROJECT_NAME = "<TEAM_CODE>"
ACCESS_KEY = "mobitru_ak_..."
APPIUM_HUB = "app.mobitru.com"
BROWSER_NAME = "chrome"
OPEN_URL = "https://mobitru.com/"
DEFAULT_PAGE_LOAD_TIMEOUT_SEC = 30
DEFAULT_IMPL_TIMEOUT_SEC = 3
DEFAULT_WAIT_TIMEOUT_SEC = 10

@pytest.fixture(scope="function", params=["4C071FDAP002SW", "26281JEGR04493", "R5CY23ZSTNF", "28101FDH3009BP"])
def driver(request):
    """Fixture for setting up and tearing down the Appium driver."""
    desired_capabilities = {
        "platformName": "Android",
        "automationName": "UIAutomator2",
        "browserName": BROWSER_NAME,
        "udid": request.param,
    }

    # Initialize the Appium driver
    driver = webdriver.Remote(
        command_executor=f"https://{PROJECT_NAME}:{ACCESS_KEY}@{APPIUM_HUB}/wd/hub",
        desired_capabilities=desired_capabilities
    )

    driver.set_page_load_timeout(DEFAULT_PAGE_LOAD_TIMEOUT_SEC)
    driver.implicitly_wait(DEFAULT_IMPL_TIMEOUT_SEC)

    yield driver

    # Device release
    driver.quit()


def test_appium_demo(driver):
    """Test to verify navigation to Google and basic checks."""
    # Ensure the app is a browser
    assert driver.contexts, f"Focus is not on '{BROWSER_NAME}'"

    # Navigate to the URL
    driver.get(OPEN_URL)

    # Wait for the Mobitru main page is opened
    WebDriverWait(driver, DEFAULT_WAIT_TIMEOUT_SEC).until(
        EC.presence_of_all_elements_located((By.CSS_SELECTOR, "button[class*='demo']")),
        message="Page was not loaded"
    )

    # Verify the current URL
    assert driver.current_url == OPEN_URL, "Current URL is incorrect."

    # Verify the page title
    assert driver.title == "Mobitru: Intelligent Real Device Cloud for Mobile and Cross-Browser Testing"

Add pytest-xdist plugin to your tests and store the number of threads in the test execution command

The pytest-xdist plugin introduces a new test execution mode, which allows managing the number of simultaneous threads.
The number of threads, here, should be related to the number of available Slots. In this case, avoiding issues with concurrent device usage is possible.
Below, you can find an example of a test execution command for 2 available Slots and the corresponding console output.

Command:

pytest -n2 --disable-warnings /<path_to_file>/demo_test_parallel.py

Output:

================================================================================ test session starts ================================================================================
platform darwin -- Python 3.13.7, pytest-7.2.0, pluggy-1.6.0
rootdir: /.../appium-tests, configfile: pytest.ini
plugins: repeat-0.9.3, html-3.2.0, metadata-3.1.1, xdist-3.0.2
[gw0] Python 3.13.7 (v3.13.7:bcee1c32211, Aug 14 2025, 19:10:51) [Clang 16.0.0 (clang-1600.0.26.6)]
[gw1] Python 3.13.7 (v3.13.7:bcee1c32211, Aug 14 2025, 19:10:51) [Clang 16.0.0 (clang-1600.0.26.6)]
gw0 [4] / gw1 [4]
scheduling tests via LoadScheduling

test/demo/web/demo_test_android_parallel.py::test_appium_demo[R5CY23ZSTNF] 
test/demo/web/demo_test_android_parallel.py::test_appium_demo[4C071FDAP002SW] 
[gw0] [ 25%] PASSED test/demo/web/demo_test_android_parallel.py::test_appium_demo[4C071FDAP002SW] 
test/demo/web/demo_test_android_parallel.py::test_appium_demo[26281JEGR04493] 
[gw1] [ 50%] PASSED test/demo/web/demo_test_android_parallel.py::test_appium_demo[R5CY23ZSTNF] 
test/demo/web/demo_test_android_parallel.py::test_appium_demo[28101FDH3009BP] 
[gw0] [ 75%] PASSED test/demo/web/demo_test_android_parallel.py::test_appium_demo[26281JEGR04493] 
[gw1] [100%] PASSED test/demo/web/demo_test_android_parallel.py::test_appium_demo[28101FDH3009BP] 

================================================================================ 4 passed in 44.12s =================================================================================

Scroll to Top