Appium Python Client
An extension library for adding WebDriver Protocol and Appium commands to the Selenium Python language binding for use with the mobile testing framework Appium.
Getting the Appium Python client
There are three ways to install and use the Appium Python client.
-
Install from PyPi, as
'Appium-Python-Client'.
pip install Appium-Python-Client
You can see the history from here
-
Install from source, via PyPi. From 'Appium-Python-Client',
download and unarchive the source tarball (Appium-Python-Client-X.X.tar.gz).
tar -xvf Appium-Python-Client-X.X.tar.gz
cd Appium-Python-Client-X.X
python setup.py install
-
Install from source via GitHub.
git clone git@github.com:appium/python-client.git
cd python-client
python setup.py install
Compatibility Matrix
Appium Python Client | Selenium binding | Python version |
---|
4.3.0 + | 4.26.0 + | 3.8+ |
3.0.0 - 4.2.1 | 4.12.0 - 4.25.0 | 3.8+ |
2.10.0 - 2.11.1 | 4.1.0 - 4.11.2 | 3.7+ |
2.2.0 - 2.9.0 | 4.1.0 - 4.9.0 | 3.7+ |
2.0.0 - 2.1.4 | 4.0.0 | 3.7+ |
1.0.0 - 1.3.0 | 3.x | 3.7+ |
0.52 and below | 3.x | 2.7, 3.4 - 3.7 |
The Appium Python Client depends on Selenium Python binding, thus
the Selenium Python binding update might affect the Appium Python Client behavior.
For example, some changes in the Selenium binding could break the Appium client.
Note
We strongly recommend you manage dependencies with version management tools such as Pipenv and requirements.txt
to keep compatible version combinations.
Quick migration guide from v3 to v4
- Removal
MultiAction
and TouchAction
are removed. Please use W3C WebDriver actions or mobile:
extensions
- Deprecated
AppiumBy.WINDOWS_UI_AUTOMATION
, which has no usage right now.
Quick migration guide from v2 to v3
options
keyword argument in the webdriver.Remote
constructor such as XCUITestOptions
instead of desired_capabilities
- Replacement
- Removal
end_test_coverage
method is no longer availablesession
property is no longer availableall_sessions
property is no longer available
Quick migration guide from v1 to v2
- Enhancement
- Updated base Selenium Python binding version to v4
- Removed
forceMjsonwp
since Selenium v4 and Appium Python client v2 expect only W3C WebDriver protocol
- Methods
ActionHelpers#scroll
, ActionHelpers#drag_and_drop
, ActionHelpers#tap
, ActionHelpers#swipe
and ActionHelpers#flick
now call W3C actions as its backend
- Please check each behavior. Their behaviors could slightly differ.
- Added
strict_ssl
to relax SSL errors such as self-signed ones
- Deprecated
MultiAction
and TouchAction
are deprecated. Please use W3C WebDriver actions or mobile:
extensionslaunch_app
, close_app
, and reset
are deprecated. Please read issues#15807 for more details
MultiAction/TouchAction to W3C actions
Some elements can be handled with touch
pointer action instead of the default mouse
pointer action in the Selenium Python client.
For example, the below action builder is to replace the default one with the touch
pointer action.
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"))
actions.w3c_actions.pointer_action.move_to_location(start_x, start_y)
actions.w3c_actions.pointer_action.pointer_down()
actions.w3c_actions.pointer_action.pause(2)
actions.w3c_actions.pointer_action.move_to_location(end_x, end_y)
actions.w3c_actions.pointer_action.release()
actions.perform()
Usage
The Appium Python Client is fully compliant with the WebDriver Protocol
including several helpers to make mobile testing in Python easier.
To use the new functionality now, and to use the superset of functions, instead of
including the Selenium webdriver
module in your test code, use that from
Appium instead.
from appium import webdriver
From there much of your test code will work with no change.
As a base for the following code examples, the following set up the UnitTest
environment:
import pytest
from appium import webdriver
from appium.options.android import UiAutomator2Options
from appium.options.ios import XCUITestOptions
from appium.webdriver.appium_service import AppiumService
from appium.webdriver.common.appiumby import AppiumBy
APPIUM_PORT = 4723
APPIUM_HOST = '127.0.0.1'
@pytest.fixture(scope='session')
def appium_service():
service = AppiumService()
service.start(
args=['--address', APPIUM_HOST, '-p', str(APPIUM_PORT)],
timeout_ms=20000,
)
yield service
service.stop()
def create_ios_driver(custom_opts = None):
options = XCUITestOptions()
options.platformVersion = '13.4'
options.udid = '123456789ABC'
if custom_opts is not None:
options.load_capabilities(custom_opts)
return webdriver.Remote(f'http://{APPIUM_HOST}:{APPIUM_PORT}', options=options)
def create_android_driver(custom_opts = None):
options = UiAutomator2Options()
options.platformVersion = '10'
options.udid = '123456789ABC'
if custom_opts is not None:
options.load_capabilities(custom_opts)
return webdriver.Remote(f'http://{APPIUM_HOST}:{APPIUM_PORT}', options=options)
@pytest.fixture
def ios_driver_factory():
return create_ios_driver
@pytest.fixture
def ios_driver():
driver = create_ios_driver()
yield driver
driver.quit()
@pytest.fixture
def android_driver_factory():
return create_android_driver
@pytest.fixture
def android_driver():
driver = create_android_driver()
yield driver
driver.quit()
def test_ios_click(appium_service, ios_driver_factory):
with ios_driver_factory({
'appium:app': '/path/to/app/UICatalog.app.zip'
}) as driver:
el = driver.find_element(by=AppiumBy.ACCESSIBILITY_ID, value='item')
el.click()
def test_android_click(appium_service, android_driver_factory):
with android_driver_factory({
'appium:app': '/path/to/app/test-app.apk',
'appium:udid': '567890',
}) as driver:
el = driver.find_element(by=AppiumBy.ACCESSIBILITY_ID, value='item')
el.click()
Available options
Appium Python Client has a common options class named AppiumOptions
but the available commands are minimal.
It does not have driver/automationName specific commands unless adding commands with add_command
method.
Available options for each automation name below will help to check what options are already defined.
Please use proper options for your automaiton usage.
automationName | Package path |
---|
any | appium.options.common.base.AppiumOptions |
uiautomator2 | appium.options.android.Uiautomator2Options |
espresso | appium.options.android.EspressoOptions |
xcuitest | appium.options.ios.XCUITestOptions |
safari | appium.options.ios.SafariOptions |
mac2 | appium.options.mac.Mac2Options |
windows | appium.options.WindowsOptions |
gecko | appium.options.GeckoOptions |
flutterintegration | appium.options.flutter_integration.FlutterOptions |
Direct Connect URLs
If your Selenium/Appium server decorates the new session capabilities response with the following keys:
directConnectProtocol
directConnectHost
directConnectPort
directConnectPath
Then python client will switch its endpoint to the one specified by the values of those keys.
from appium import webdriver
from appium.options.ios import XCUITestOptions
options = XCUITestOptions().load_capabilities({
'platformVersion': '13.4',
'deviceName': 'iPhone Simulator',
'app': '/full/path/to/app/UICatalog.app.zip',
})
driver = webdriver.Remote(
'http://127.0.0.1:4723',
options=options,
direct_connection=True
)
Relax SSL validation
strict_ssl
option allows you to send commands to an invalid certificate host like a self-signed one.
from appium import webdriver
from appium.options.common import AppiumOptions
options = AppiumOptions()
options.platform_name = 'mac'
options.automation_name = 'safari'
options.set_capability('browser_name', 'safari')
driver = webdriver.Remote('http://127.0.0.1:4723', options=options, strict_ssl=False)
Since Appium Python client v4.3.0, we recommend using selenium.webdriver.remote.client_config.ClientConfig
instead of giving strict_ssl
as an argument of webdriver.Remote
below to configure the validation.
from appium import webdriver
from selenium.webdriver.remote.client_config import ClientConfig
client_config = ClientConfig(
remote_server_addr='http://127.0.0.1:4723',
ignore_certificates=True
)
driver = webdriver.Remote(client_config.remote_server_addr, options=options, client_config=client_config)
Set custom AppiumConnection
The first argument of webdriver.Remote
can set an arbitrary command executor for you.
- Set init arguments for the pool manager Appium Python client uses to manage HTTP requests.
from appium import webdriver
from appium.options.ios import XCUITestOptions
import urllib3
from appium.webdriver.appium_connection import AppiumConnection
init_args_for_pool_manage = {
'retries': urllib3.util.retry.Retry(total=3, connect=3, read=False)
}
appium_executor = AppiumConnection(
remote_server_addr='http://127.0.0.1:4723',
init_args_for_pool_manage=init_args_for_pool_manage
)
options = XCUITestOptions()
options.platformVersion = '13.4'
options.udid = '123456789ABC'
options.app = '/full/path/to/app/UICatalog.app.zip'
driver = webdriver.Remote(appium_executor, options=options)
- Define a subclass of
AppiumConnection
from appium import webdriver
from appium.options.ios import XCUITestOptions
from appium.webdriver.appium_connection import AppiumConnection
class CustomAppiumConnection(AppiumConnection):
pass
custom_executor = CustomAppiumConnection(remote_server_addr='http://127.0.0.1:4723')
options = XCUITestOptions().load_capabilities({
'platformVersion': '13.4',
'deviceName': 'iPhone Simulator',
'app': '/full/path/to/app/UICatalog.app.zip',
})
driver = webdriver.Remote(custom_executor, options=options)
The AppiumConnection
can set selenium.webdriver.remote.client_config.ClientConfig
as well.
Relaxing HTTP request read timeout
Appium Python Client has 120
seconds read timeout on each HTTP request since the version v4.3.0 because of
the corresponding selenium binding version.
You have two methods to extend the read timeout.
- Set
GLOBAL_DEFAULT_TIMEOUT
environment variable - Configure timeout via
selenium.webdriver.remote.client_config.ClientConfig
timeout
argument, orinit_args_for_pool_manager
argument for urllib3.PoolManager
Documentation
Development
- Code Style: PEP-0008
- Apply
ruff
as pre commit hook - Run
make
command for development. See make help
output for details
- Docstring style: Google Style
gitchangelog
generates CHANGELOG.rst
Setup
pip install --user pipenv
python -m pipenv lock --clear
- If you experience
Locking Failed! unknown locale: UTF-8
error, then refer pypa/pipenv#187 to solve it.
python -m pipenv install --dev --system
pre-commit install
Run tests
You can run all of the tests running on CI via tox
in your local.
$ tox
You also can run particular tests like below.
Unit
$ pytest test/unit
Run with pytest-xdist
$ pytest -n 2 test/unit
Functional
$ pytest test/functional/ios/search_context/find_by_ios_class_chain_tests.py
In parallel for iOS
- Create simulators named 'iPhone X - 8100' and 'iPhone X - 8101'
- Install test libraries via pip,
pip install pytest pytest-xdist
- Run tests
$ pytest -n 2 test/functional/ios/search_context/find_by_ios_class_chain_tests.py
Release
Follow the below steps.
$ pip install twine
$ pip install git+git://github.com/vaab/gitchangelog.git
$ DRY_RUN=1 ./release.sh
$ ./release.sh
If the pypi
was not able to publish with user name and password, please try out -u
and -p
option by yourself with twine
such as twine upload -u <name> -p <pass> dist/Appium-Python-Client-4.1.0.tar.gz
.
License
Apache License v2