Mobile automation crosses several boundaries: the Appium server, a platform driver, a client library, the operating system, and the application. A working example must fit all of them. Treat this compatibility matrix as part of the framework instead of assuming that upgrading the server upgrades every driver.
Keep the installation matrix explicit
The Appium 3 migration guide lists changed runtime requirements and removed deprecated endpoints. Check the server’s Node and npm requirements, then the selected driver’s requirements separately. Record the server, driver, Python client, Selenium dependency, device OS, and application build in CI artifacts.
appium --version
appium driver list --installed
# Install only the driver your target requires.
appium driver install uiautomator2
# XCUITest is for an appropriately configured macOS/iOS environment.
# appium driver install xcuitestThis is an installation outline, not a full device setup. Android SDK configuration, emulator images, iOS signing, and WebDriverAgent setup remain platform-specific. Test an upgrade with a small representative suite before changing the full device matrix.
Use current gesture APIs
The Python client removed legacy TouchAction and MultiAction APIs. Use W3C pointer actions or a documented mobile: extension from the installed driver. This touch swipe assumes driver is an active native session; coordinates must fit the current device.
from selenium.webdriver import ActionChains
from selenium.webdriver.common.actions import interaction
from selenium.webdriver.common.actions.action_builder import ActionBuilder
from selenium.webdriver.common.actions.pointer_input import PointerInput
actions = ActionChains(driver)
actions.w3c_actions = ActionBuilder(
driver, mouse=PointerInput(interaction.POINTER_TOUCH, "touch")
)
pointer = actions.w3c_actions.pointer_action
pointer.move_to_location(100, 600)
pointer.pointer_down()
pointer.pause(0.2)
pointer.move_to_location(100, 200)
pointer.release()
actions.perform()Select the intended WebView
A hybrid app may expose no WebView yet, several WebViews, or a context that is not ready. Do not use contexts[1]. Select the expected context and wait for a meaningful DOM condition. Replace the prefix below with the app’s actual context name.
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 15)
context = wait.until(lambda d: next(
(name for name in d.contexts
if name.startswith("WEBVIEW_com.example.app")), None
))
driver.switch_to.context(context)
try:
wait.until(EC.element_to_be_clickable(
(By.CSS_SELECTOR, "button.submit")
)).click()
wait.until(EC.visibility_of_element_located(
(By.CSS_SELECTOR, "[data-testid='confirmation']")
))
finally:
driver.switch_to.context("NATIVE_APP")Control state instead of hiding it
- Use fresh install or cleared state for first-launch and permission tests.
- Reuse an app session only where fixtures restore accounts, data, navigation, and permissions deliberately.
- Allocate a device and its service ports per parallel worker. Sharing an emulator does not isolate tests.
- Capture screenshots, device logs, driver logs, and the current context on failure; review them for sensitive data before sharing.
Performance checks should use a documented platform tool or supported driver extension. CPU sampling, launch timing, and rendered-frame performance measure different things; a fast WebDriver command does not establish a responsive application.
Appium 3 migration guide and Appium Python client migration examples, reviewed September 5, 2026.

