Parallel Device Initialization with Appium 2.X
Multi-Device Setup: Launching Multiple Appium Services
1) Configuration Parameters for Application Launch
Application launch parameters are managed through a structured data abstraction approach.
1.1) platformName – Defaults to Android.
1.2) platformVersion – Specifies the Android OS version.
1.3) deviceName – A customizable identifier for the device; cannot be omitted.
1.4) udid – Unique device identifier for physical devices, retrievable via adb devices.
1.5) appPackage – Package name of the application under test.
1.6) appActivity – Activity name of the application under test.
1.7) automationName – Framework used for automation testing.
1.8) noReset – Controls whether the application state is reset between test runs. Setting noReset=True preserves app data and cache.
1.9) resetKeyboard – Resets keyboard input state to ensure reliability and consistency.
2) Implementation Code
2.1) multi_device.py – Code utilizing YAML data.
from appium import webdriver
from appium.options.android import UiAutomator2Options
import yaml
import logging
import logging.config
from datetime import datetime
LOG_CONFIG = "../config/log.conf"
logging.config.fileConfig(LOG_CONFIG)
logger = logging.getLogger()
with open("../config/multi_device.yaml", "r", encoding="utf-8") as config_file:
config_data = yaml.safe_load(config_file)
device_ids = ["device_one", "device_two"]
def initialize_driver(device_udid, server_port):
capabilities = {}
capabilities["platformName"] = config_data["platformName"]
capabilities["platformVersion"] = config_data["platformVersion"]
capabilities["deviceName"] = config_data["deviceName"]
capabilities["udid"] = device_udid
capabilities["appPackage"] = config_data["appPackage"]
capabilities["appActivity"] = config_data["appActivity"]
capabilities["automationName"] = config_data["automationName"]
capabilities["noReset"] = config_data["noReset"]
capabilities["resetKeyboard"] = config_data["resetKeyboard"]
logger.info(f"Appium server on port {server_port} for device {device_udid} at {datetime.now()}")
server_url = f"http://{config_data['ip']}:{server_port}"
logger.info(server_url)
driver = webdriver.Remote(server_url, options=UiAutomator2Options().load_capabilities(capabilities))
driver.implicitly_wait(5)
return driver
if __name__ == "__main__":
initialize_driver(device_ids[0], 4723)
initialize_driver(device_ids[1], 4725)
2.2) multi_device.yaml – Data abstraction file.
platformName: Android
platformVersion: '14'
deviceName: custom_device
appPackage: com.example.app
appActivity: com.example.app.MainActivity
automationName: UiAutomator2
noReset: False
resetKeyboard: True
ip: 127.0.0.1
2.3) Note: YAML syntax requires a space between keys and values.
Multi-Device Launch: Concurrent Device Initialization with Multiprocessing
1) Creating and Menaging Process Groups
1.1) multi_device_concurrent.py – Implementation using multiprocessing.
import multiprocessing
from appium import webdriver
from appium.options.android import UiAutomator2Options
import yaml
import logging
import logging.config
from datetime import datetime
LOG_CONFIG = "../config/log.conf"
logging.config.fileConfig(LOG_CONFIG)
logger = logging.getLogger()
with open("../config/multi_device_concurrent.yaml", "r", encoding="utf-8") as config_file:
config_data = yaml.safe_load(config_file)
device_ids = ["device_one", "device_two"]
def initialize_driver(device_udid, server_port):
capabilities = {}
capabilities["platformName"] = config_data["platformName"]
capabilities["platformVersion"] = config_data["platformVersion"]
capabilities["deviceName"] = config_data["deviceName"]
capabilities["udid"] = device_udid
capabilities["appPackage"] = config_data["appPackage"]
capabilities["appActivity"] = config_data["appActivity"]
capabilities["automationName"] = config_data["automationName"]
capabilities["noReset"] = config_data["noReset"]
capabilities["resetKeyboard"] = config_data["resetKeyboard"]
logger.info(f"Appium server on port {server_port} for device {device_udid} at {datetime.now()}")
server_url = f"http://{config_data['ip']}:{server_port}"
logger.info(server_url)
driver = webdriver.Remote(server_url, options=UiAutomator2Options().load_capabilities(capabilities))
driver.implicitly_wait(5)
return driver
# Initialize process list
processes = []
# Create and add processes to the list
for index, device_id in enumerate(device_ids):
port_number = 4723 + 2 * index
process = multiprocessing.Process(target=initialize_driver, args=(device_id, port_number))
processes.append(process)
if __name__ == "__main__":
# Start all processes concurrently
for proc in processes:
proc.start()
# Wait for all processes to complete
for proc in processes:
proc.join()
1.2) multi_device_concurrent.yaml – Configuration data.
platformName: Android
platformVersion: '14'
deviceName: custom_device_name
appPackage: com.example.app
appActivity: com.example.app.MainActivity
automationName: UiAutomator2
noReset: False
resetKeyboard: True
ip: 127.0.0.1
2) Test Outcome: Parallel Application Launch on Multiple Devices
2.1) Multiprocessing Concepts Review
In multiprocessing, each process maintains its own copy of variables, ensuring isolation and preventing interference. In contrast, multithreading shares variables across all threads, which can lead to data corruption if multiple threads modify the same variable simultaneously.
2.2) The multiprocessing Module
The multiprocessing module in Python facilitates parallel processing and multi-process programming, enabling efficient utilization of multi-core CPUs. Key features include:
- Process Creation: Easily spawn new processes, each with independent memory space.
- Inter-Process Communication: Supports mechanisms like Queue, Pipe, and shared memory (Value/Array) for safe data exchange.
- Synchronization: Provides locks, semaphores, and events to manage shared resources in concurrent environments.
- Cross-Platform Compatibility: Functions consistently across Windows, Linux, and macOS.
- Simplified API: Offers high-level interfaces to streamline parallel code development.
Using multiprocessing enhances performance for CPU-intensive tasks by leveraging system resources effectively.