Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Parallel Device Initialization with Appium 2.X

Tech 1

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.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.