Skip to content

Commit

Permalink
added AppiumClient support and update stf client (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
jupe authored Sep 16, 2022
1 parent 6166f81 commit 2fa18a5
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 19 deletions.
27 changes: 23 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,37 @@ prepare remote adb connection and starts appium server that tests could utilize
## Usage example

Test script: sample.py

```python
def test_create(selected_phone):
device, adb, appium = selected_phone

from appium.webdriver.webdriver import WebDriver


def test_create(appium_client):
client, appium, adb, phone = appium_client
# device is dictionary of device metadata
# adb: AdbServer instance, that is already connected
# appium: AppiumServer instance that provide server address for appium client
print(device)
print(f'wd_hub: {appium.get_wd_hub_uri()}')
print(phone)
print(f'wd_hub: {appium.get_api_path()}')

client: WebDriver
client, *_ = appium_client
URL = 'https://google.com'
client.get(URL)
url = client.current_url
assert url == URL, 'Wrong URL'
```

Execution
```
> pytest sample/test_samples.py --stf_host localhost --stf_token $TOKEN --phone_requirements platform=Android
```


See more examples from [sample/test_samples.py](sample/test_samples.py).

custom capabilities:
```
> pytest --appium_capabilities cab=val1&cab=val2
```
90 changes: 80 additions & 10 deletions pytest_stf/plugin.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import os
import pytest
from stf_appium_client import StfClient
from stf_appium_client.StfClient import StfClient
from stf_appium_client.tools import parse_requirements
from stf_appium_client.AdbServer import AdbServer
from stf_appium_client.Appium import Appium
from stf_appium_client.AppiumServer import AppiumServer
from stf_appium_client.AppiumClient import AppiumClient
from appium.webdriver.webdriver import WebDriver


def pytest_addoption(parser):
Expand All @@ -29,9 +31,13 @@ def pytest_addoption(parser):
)
group.addoption(
"--stf_allocation_timeout",
default=10,
default=1000,
help="Allocation timeout",
)
group.addoption(
"--appium_capabilities",
help="Appium capabilities"
)


def pytest_configure(config):
Expand All @@ -58,11 +64,28 @@ def pytest_unconfigure(config):
del config._openstf # pylint: disable=protected-access


@pytest.fixture(name="selected_phone", scope="session")
def fixture_selected_phone(pytestconfig):
@pytest.fixture(name='allocated_phone', scope="session")
def fixture_allocated_phone(pytestconfig):
"""
Allocate required phone, create ADB tunnel to phone via STF and start appium server for tests.
Yields tuple (device: dict, adb: AdbServer, appium: Appium)
Allocate required phone via STF.
Yields device details as dict.
e.g.
{
"abi": "arm64-v8a",
"airplaneMode": false,
"battery": {...},
"browser": {...},
"cpuPlatform": "...",
"manufacturer": "...",
"marketName": "Pixel 4",
"model": "Pixel 4",
"network": {...},
"platform": "Android",
"sdk": "32",
"serial": "...",
"version": "12",
...
}
"""
assert hasattr(pytestconfig, '_openstf'), 'stf_host or stf_token missing'

Expand All @@ -74,6 +97,53 @@ def fixture_selected_phone(pytestconfig):
requirements = parse_requirements(requirements)

with stf.allocation_context(requirements, timeout_seconds=timeout) as device:
with AdbServer(device['remote_adb_url']) as adb:
with Appium() as appium:
yield device, adb, appium
yield device


@pytest.fixture(name='phone_with_adb', scope="session")
def fixture_phone_with_adb(allocated_phone):
"""
Allocate required phone and create ADB tunnel to phone via STF.
Yields tuple (adb: AdbServer, device: dict)
"""
with AdbServer(allocated_phone['remote_adb_url']) as adb:
yield adb, allocated_phone


@pytest.fixture(name='appium_args', scope='session')
def fixture_appium_args():
# overridable list of appium server args
return []

@pytest.fixture(name="appium_server", scope="session")
def fixture_appium_server(phone_with_adb, appium_args):
"""
Allocate required phone, create ADB tunnel to phone via STF and start appium server for tests.
Yields tuple (appium: Appium, adb: AdbServer, device: dict )
"""
adb, phone = phone_with_adb
with AppiumServer(appium_args) as appium:
yield appium, adb, phone


@pytest.fixture(name='capabilities', scope='session')
def fixture_capabilities(pytestconfig, allocated_phone):
kwargs = {
"desired_capabilities": {
'platformName': allocated_phone['platform']
}
}
extra_capabilities = pytestconfig.getoption('appium_capabilities')
if extra_capabilities:
extra_capabilities = parse_requirements(extra_capabilities)
kwargs['desired_capabilities'].update(extra_capabilities)
yield kwargs


@pytest.fixture(name="appium_client", scope="session")
def fixture_appium_client(appium_server, capabilities):
appium, adb, phone = appium_server
client = AppiumClient(command_executor=appium.get_api_path(), **capabilities)
with client as driver:
driver: WebDriver
yield driver, appium, adb, phone
70 changes: 66 additions & 4 deletions sample/test_samples.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,66 @@
def test_create(selected_phone):
device, adb, appium = selected_phone
print(device)
print(f'wd_hub: {appium.get_wd_hub_uri()}')
import pytest
from appium.webdriver.webdriver import WebDriver

from stf_appium_client import AppiumServer, AdbServer


def test_allocated_phone(allocated_phone: dict):
# allocated_phone is dictionary of phone metadata
print(allocated_phone)


def test_adb(phone_with_adb):
# allocated phone with adb proxy
adb, phone = phone_with_adb
adb: AdbServer
response = adb._execute('shell getprop ro.build.version.release', 10)
assert response.stdout == phone.get('version'), 'Wrong Android version'


def test_appium(appium_server):
# allocated phone with adb and appium server
appium, adb, phone = appium_server
appium: AppiumServer
print(f'wd_hub: {appium.get_api_path()}')


@pytest.fixture(scope='session')
def fixture_capabilities(pytestconfig):
values = pytestconfig.getoption('appium_capabilities')


@pytest.fixture(name='appium_args', scope='session')
def fixture_appium_args():
# overridable list of appium server args
# https://appium.io/docs/en/writing-running-appium/server-args/
return []


@pytest.fixture(name='capabilities', scope='session')
def fixture_capabilities(pytestconfig, allocated_phone):
# Allows to overwrite WebDriver arguments
# Under the hoods these are used like `WebDriver(**kwargs)`
kwargs = {
"desired_capabilities": {
'platformName': allocated_phone['platform'],
#'udid': '', #allocated_phone['serial'],
'automationName': 'UiAutomator2',
'browserName': 'Chrome',
}
}
yield kwargs


def test_client(appium_client):
# allocated phone with adb+appium server + appium client (WebDriver)
driver, appium, adb, phone = appium_client

# adb: AdbServer instance, that is already connected
# appium: AppiumServer instance that provide server address for appium client
#
driver: WebDriver
test_url = 'https://www.google.com/'

driver.get(test_url)
url = driver.current_url
assert url == test_url, 'Wrong URL'
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
install_requires=[
"pytest>=5.0",
"pytest-metadata",
"stf-appium-client==0.7.0"],
"stf-appium-client==0.9.0"],
# List additional groups of dependencies here (e.g. development
# dependencies). Users will be able to install these using the "extras"
# syntax, for example:
Expand Down

0 comments on commit 2fa18a5

Please sign in to comment.