Skip to content

Commit

Permalink
feat: update server url and automationName used in Appium 2
Browse files Browse the repository at this point in the history
  • Loading branch information
rgonalo committed Apr 25, 2023
1 parent 469edd8 commit f795a38
Show file tree
Hide file tree
Showing 18 changed files with 187 additions and 53 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.rst
Expand Up @@ -13,14 +13,15 @@ v3.0.0

| It only needs PIL library to compare images and generate the differences images
| Old PerceptualDiff and Magick engines have been removed
| Config property 'visualtests_engine' in [Server] section has been removed
| Config property `engine` in [VisualTests] section has been removed
| Images distance calculation method has changed, it is recommended to review thresholds in tests
- Now `gecko_driver_path`, `chrome_driver_path`, `explorer_driver_path` and `edge_driver_path` config properties
in [Driver] section are optional, due to new SeleniumManager feature, that downloads drivers automatically
- New optional config property `safari_driver_path` in [Driver] section to configure Safari driver
- New optional config property `options` in [Chromer] section to configure Chrome options instead of using old
- New optional config property `options` in [Chrome] section to configure Chrome options instead of using old
property `goog:chromeOptions` in [Capabilities] section.
- New optional config property `base_path` in [Server] section to allow using old Selenium 3 or Appium 1 remote servers
- Update [RANDOM_PHONE_NUMBER] replacement using new `DataGenerator` class
- Remove support for lettuce tests
- Remove deprecated parameter `context` from `map_param` and POEditor methods
Expand Down
2 changes: 1 addition & 1 deletion VERSION
@@ -1 +1 @@
3.0.0a4
3.0.0b1
2 changes: 1 addition & 1 deletion docs/bdd_integration.rst
Expand Up @@ -164,7 +164,7 @@ functions or check the :ref:`dataset <dataset>` module for more implementation d
* :code:`[B]`: Generates a blank space
* :code:`[UUID]`: Generates a v4 UUID
* :code:`[RANDOM]`: Generates a random value
* :code:`[RANDOM_PHONE_NUMBER]`: Generates a random phone number following the pattern +34654XXXXXX, using the language and country specified in dataset.language and dataset.country
* :code:`[RANDOM_PHONE_NUMBER]`: Generates a random phone number for language and country configured in dataset.language and dataset.country
* :code:`[TIMESTAMP]`: Generates a timestamp from the current time
* :code:`[DATETIME]`: Generates a datetime from the current time
* :code:`[NOW]`: Similar to DATETIME without milliseconds; the format depends on the language
Expand Down
27 changes: 16 additions & 11 deletions docs/mobile_configuration.rst
Expand Up @@ -4,25 +4,30 @@ Mobile Configuration
====================

To choose mobile operating system in which Appium will execute the tests, configure *type* property in *[Driver]*
section in properties.cfg file with one of these values: ios or android.
section in properties.cfg file with one of these values: :code:`ios` or :code:`android`. Moreover, configure Appium
properties in *[AppiumCapabilities]* section in properties.cfg file.

The following example shows how to choose Android::
The following example shows how to configure Appium to run tests over TestApp app on an iPhone 14 with iOS 16.1::

[Driver]
type: android
type: ios

[AppiumCapabilities]
automationName: XCUITest
platformName: iOS
deviceName: iPhone 14
platformVersion: 16.1
app: http://server_url/TestApp.zip

Moreover, configure Appium properties in *[AppiumCapabilities]* section in properties.cfg file. The following example
shows how to configure Appium to run tests over TestApp app on an iPhone 6 with iOS 8.3::
And this example shows how to choose Android::

[Driver]
type: ios
type: android

[AppiumCapabilities]
automationName: Appium
platformName: iOS
deviceName: iPhone 6
platformVersion: 8.3
app: http://server_url/TestApp.zip
automationName: UiAutomator2
platformName: Android
deviceName: Android
app: http://server_url/TestApp.apk

See https://appium.github.io/appium/docs/en/2.0/guides/caps/ for the complete Appium capabilities list.
16 changes: 8 additions & 8 deletions docs/page_objects.rst
Expand Up @@ -222,28 +222,28 @@ The corresponding Android page object, where page elements are defined with thei

.. code-block:: python
from selenium.webdriver.common.by import By
from appium.webdriver.common.appiumby import AppiumBy
from toolium.pageelements import InputText, Button
from toolium_examples.pageobjects.base.login import BaseLoginPageObject
class AndroidLoginPageObject(BaseLoginPageObject):
username = InputText(By.ID, 'io.appium.android.apis:id/username')
password = InputText(By.ID, 'io.appium.android.apis:id/password')
login_button = Button(By.ID, "io.appium.android.apis:id/login_button")
username = InputText(AppiumBy.ID, 'io.appium.android.apis:id/username')
password = InputText(AppiumBy.ID, 'io.appium.android.apis:id/password')
login_button = Button(AppiumBy.ID, "io.appium.android.apis:id/login_button")
And the iOS page object, where page elements are defined with their specific iOS locators:

.. code-block:: python
from appium.webdriver.common.mobileby import MobileBy
from appium.webdriver.common.appiumby import AppiumBy
from toolium.pageelements import InputText, Button
from toolium_examples.pageobjects.base.login import BaseLoginPageObject
class IosLoginPageObject(BaseLoginPageObject):
username = InputText(MobileBy.IOS_UIAUTOMATION, '.textFields()[0]')
password = InputText(MobileBy.IOS_UIAUTOMATION, '.secureTextFields()[0]')
login_button = Button(MobileBy.IOS_UIAUTOMATION, '.buttons()[0]')
username = InputText(AppiumBy.IOS_UIAUTOMATION, '.textFields()[0]')
password = InputText(AppiumBy.IOS_UIAUTOMATION, '.secureTextFields()[0]')
login_button = Button(AppiumBy.IOS_UIAUTOMATION, '.buttons()[0]')
Base, Android and iOS page objects must be defined in different files following this structure::
Expand Down
9 changes: 8 additions & 1 deletion docs/remote_configuration.rst
Expand Up @@ -19,6 +19,7 @@ section in properties.cfg file::
video_enabled: false
logs_enabled: false
log_types: all
base_path:

enabled
~~~~~~~
Expand Down Expand Up @@ -61,13 +62,19 @@ logs_enabled
| *false*: webdriver and GGR logs are downloaded and saved to local files only if the test fails
log_types
~~~~~~~~~~
~~~~~~~~~
| Comma-separated list of webdriver log types that will be downloaded if remote test fails or if *logs_enabled* is true
|
| *all*: all available log types in remote server will be downloaded (default value)
| '': setting an empty string, no log types will be downloaded
| *client,server*: in this example, only client and server logs will be downloaded
base_path
~~~~~~~~~
| Base path to use as prefix for all webdriver routes running on the server, empty by default.
|
| */wd/hub*: use this base path with old Selenium 3 or Appium 1 remote servers

Remote Driver Capabilities
--------------------------
Expand Down
3 changes: 2 additions & 1 deletion toolium/config_driver.py
Expand Up @@ -102,7 +102,7 @@ def _create_remote_driver(self):
capabilities = self._get_capabilities_from_driver_type()

# Get server url
server_url = f'{self.utils.get_server_url()}/wd/hub'
server_url = f"{self.utils.get_server_url()}{self.config.get_optional('Server', 'base_path', '')}"

driver_name = self.utils.get_driver_name()
if driver_name in ('android', 'ios', 'iphone'):
Expand Down Expand Up @@ -192,6 +192,7 @@ def _add_capabilities_from_properties(self, capabilities, section):
cap_type = {'Capabilities': 'server', 'AppiumCapabilities': 'Appium server'}
try:
for cap, cap_value in dict(self.config.items(section)).items():
cap = f'appium:{cap}' if section == 'AppiumCapabilities' else cap
self.logger.debug("Added %s capability: %s = %s", cap_type[section], cap, cap_value)
cap_value = cap_value if cap == 'browserVersion' else self._convert_property_type(cap_value)
self._update_dict(capabilities, {cap: cap_value}, initial_key=cap)
Expand Down
2 changes: 1 addition & 1 deletion toolium/test/conf/android-properties.cfg
Expand Up @@ -3,7 +3,7 @@ type: android
appium_app_strings: true

[AppiumCapabilities]
automationName: Android
automationName: UiAutomator2
platformName: Android
deviceName: Android Emulator
browserName:
Expand Down
2 changes: 1 addition & 1 deletion toolium/test/conf/properties.cfg
Expand Up @@ -43,7 +43,7 @@ selenoid___options: {'enableVNC': True, 'enableVideo': True}
cloud___options: {'name': 'test'}

[AppiumCapabilities]
automationName: Appium
automationName: UiAutomator2
platformName: Android
deviceName: Android Emulator
browserName:
Expand Down
38 changes: 30 additions & 8 deletions toolium/test/test_config_driver_appium.py
Expand Up @@ -78,6 +78,28 @@ def test_create_remote_driver_appium(appiumdriver_mock, driver_type, config, uti

config_driver._create_remote_driver()

# Check that appium options contain expected capabilities
args, kwargs = appiumdriver_mock.Remote.call_args
options = kwargs['options']
assert isinstance(options, AppiumOptions)
assert options.capabilities == expected_capabilities
appiumdriver_mock.Remote.assert_called_once_with(command_executor=server_url, options=options)


@mock.patch('toolium.config_driver.appiumdriver')
@pytest.mark.parametrize('driver_type', appium_driver_types)
def test_create_remote_driver_appium_basepath(appiumdriver_mock, driver_type, config, utils):
utils.get_driver_name.return_value = driver_type
config.set('Driver', 'type', driver_type)
config.set('Server', 'base_path', '/wd/hub')
server_url = 'http://10.20.30.40:5555'
utils.get_server_url.return_value = server_url
config_driver = ConfigDriver(config, utils)
DriverWrappersPool.output_directory = ''
expected_capabilities = DEFAULT_CAPABILITIES

config_driver._create_remote_driver()

# Check that appium options contain expected capabilities
args, kwargs = appiumdriver_mock.Remote.call_args
options = kwargs['options']
Expand All @@ -92,15 +114,15 @@ def test_create_remote_driver_android_capabilities(appiumdriver_mock, config, ut
utils.get_driver_name.return_value = driver_type
config.set('Driver', 'type', driver_type)
config.add_section('AppiumCapabilities')
config.set('AppiumCapabilities', 'automationName', 'Appium')
config.set('AppiumCapabilities', 'automationName', 'UiAutomator2')
config.set('AppiumCapabilities', 'platformName', 'Android')
server_url = 'http://10.20.30.40:5555'
utils.get_server_url.return_value = server_url
config_driver = ConfigDriver(config, utils)
DriverWrappersPool.output_directory = ''
expected_capabilities = DEFAULT_CAPABILITIES
expected_capabilities['automationName'] = 'Appium'
expected_capabilities['platformName'] = 'Android'
expected_capabilities['appium:automationName'] = 'UiAutomator2'
expected_capabilities['appium:platformName'] = 'Android'

config_driver._create_remote_driver()

Expand All @@ -109,7 +131,7 @@ def test_create_remote_driver_android_capabilities(appiumdriver_mock, config, ut
options = kwargs['options']
assert isinstance(options, AppiumOptions)
assert options.capabilities == expected_capabilities
appiumdriver_mock.Remote.assert_called_once_with(command_executor=f'{server_url}/wd/hub', options=options)
appiumdriver_mock.Remote.assert_called_once_with(command_executor=server_url, options=options)


@mock.patch('toolium.config_driver.appiumdriver')
Expand All @@ -118,15 +140,15 @@ def test_create_remote_driver_ios_capabilities(appiumdriver_mock, config, utils)
utils.get_driver_name.return_value = driver_type
config.set('Driver', 'type', driver_type)
config.add_section('AppiumCapabilities')
config.set('AppiumCapabilities', 'automationName', 'Appium')
config.set('AppiumCapabilities', 'automationName', 'XCUITest')
config.set('AppiumCapabilities', 'platformName', 'iOS')
server_url = 'http://10.20.30.40:5555'
utils.get_server_url.return_value = server_url
config_driver = ConfigDriver(config, utils)
DriverWrappersPool.output_directory = ''
expected_capabilities = DEFAULT_CAPABILITIES
expected_capabilities['automationName'] = 'Appium'
expected_capabilities['platformName'] = 'iOS'
expected_capabilities['appium:automationName'] = 'XCUITest'
expected_capabilities['appium:platformName'] = 'iOS'

config_driver._create_remote_driver()

Expand All @@ -135,4 +157,4 @@ def test_create_remote_driver_ios_capabilities(appiumdriver_mock, config, utils)
options = kwargs['options']
assert isinstance(options, AppiumOptions)
assert options.capabilities == expected_capabilities
appiumdriver_mock.Remote.assert_called_once_with(command_executor=f'{server_url}/wd/hub', options=options)
appiumdriver_mock.Remote.assert_called_once_with(command_executor=server_url, options=options)
23 changes: 21 additions & 2 deletions toolium/test/test_config_driver_chrome.py
Expand Up @@ -245,6 +245,25 @@ def test_create_remote_driver_chrome(webdriver_mock, config, utils):

config_driver._create_remote_driver()

# Check that chrome options contain expected capabilities
args, kwargs = webdriver_mock.Remote.call_args
options = kwargs['options']
assert isinstance(options, Options)
assert options.capabilities == expected_capabilities
webdriver_mock.Remote.assert_called_once_with(command_executor=server_url, options=options)


@mock.patch('toolium.config_driver.webdriver')
def test_create_remote_driver_chrome_basepath(webdriver_mock, config, utils):
config.set('Driver', 'type', 'chrome')
config.set('Server', 'base_path', '/wd/hub')
server_url = 'http://10.20.30.40:5555'
utils.get_server_url.return_value = server_url
config_driver = ConfigDriver(config, utils)
expected_capabilities = DEFAULT_CAPABILITIES

config_driver._create_remote_driver()

# Check that chrome options contain expected capabilities
args, kwargs = webdriver_mock.Remote.call_args
options = kwargs['options']
Expand All @@ -270,7 +289,7 @@ def test_create_remote_driver_chrome_with_version_and_platform(webdriver_mock, c
options = kwargs['options']
assert isinstance(options, Options)
assert options.capabilities == expected_capabilities
webdriver_mock.Remote.assert_called_once_with(command_executor=f'{server_url}/wd/hub', options=options)
webdriver_mock.Remote.assert_called_once_with(command_executor=server_url, options=options)


@mock.patch('toolium.config_driver.webdriver')
Expand All @@ -290,4 +309,4 @@ def test_create_remote_driver_chrome_with_version_and_platform_uppercase(webdriv
options = kwargs['options']
assert isinstance(options, Options)
assert options.capabilities == expected_capabilities
webdriver_mock.Remote.assert_called_once_with(command_executor=f'{server_url}/wd/hub', options=options)
webdriver_mock.Remote.assert_called_once_with(command_executor=server_url, options=options)
24 changes: 22 additions & 2 deletions toolium/test/test_config_driver_edge.py
Expand Up @@ -137,6 +137,26 @@ def test_create_remote_driver_edge(webdriver_mock, config, utils):

config_driver._create_remote_driver()

# Check that edge options contain expected capabilities
args, kwargs = webdriver_mock.Remote.call_args
options = kwargs['options']
assert isinstance(options, Options)
assert options.capabilities == expected_capabilities
webdriver_mock.Remote.assert_called_once_with(command_executor=server_url, options=options)


@mock.patch('toolium.config_driver.webdriver')
def test_create_remote_driver_edge_basepath(webdriver_mock, config, utils):
config.set('Driver', 'type', 'edge')
config.set('Server', 'base_path', '/wd/hub')
server_url = 'http://10.20.30.40:5555'
utils.get_server_url.return_value = server_url
config_driver = ConfigDriver(config, utils)
DriverWrappersPool.output_directory = ''
expected_capabilities = DEFAULT_CAPABILITIES

config_driver._create_remote_driver()

# Check that edge options contain expected capabilities
args, kwargs = webdriver_mock.Remote.call_args
options = kwargs['options']
Expand All @@ -163,7 +183,7 @@ def test_create_remote_driver_edge_with_version_and_platform(webdriver_mock, con
options = kwargs['options']
assert isinstance(options, Options)
assert options.capabilities == expected_capabilities
webdriver_mock.Remote.assert_called_once_with(command_executor=f'{server_url}/wd/hub', options=options)
webdriver_mock.Remote.assert_called_once_with(command_executor=server_url, options=options)


@mock.patch('toolium.config_driver.webdriver')
Expand All @@ -184,4 +204,4 @@ def test_create_remote_driver_edge_with_version_and_platform_uppercase(webdriver
options = kwargs['options']
assert isinstance(options, Options)
assert options.capabilities == expected_capabilities
webdriver_mock.Remote.assert_called_once_with(command_executor=f'{server_url}/wd/hub', options=options)
webdriver_mock.Remote.assert_called_once_with(command_executor=server_url, options=options)
26 changes: 23 additions & 3 deletions toolium/test/test_config_driver_firefox.py
Expand Up @@ -263,6 +263,26 @@ def test_create_remote_driver_firefox(webdriver_mock, config, utils):

config_driver._create_remote_driver()

# Check that firefox options contain expected capabilities
args, kwargs = webdriver_mock.Remote.call_args
options = kwargs['options']
assert isinstance(options, Options)
assert options.capabilities == expected_capabilities
webdriver_mock.Remote.assert_called_once_with(command_executor=server_url, options=options)


@mock.patch('toolium.config_driver.webdriver')
def test_create_remote_driver_firefox_basepath(webdriver_mock, config, utils):
config.set('Driver', 'type', 'firefox')
config.set('Server', 'base_path', '/wd/hub')
server_url = 'http://10.20.30.40:5555'
utils.get_server_url.return_value = server_url
config_driver = ConfigDriver(config, utils)
DriverWrappersPool.output_directory = ''
expected_capabilities = DEFAULT_CAPABILITIES

config_driver._create_remote_driver()

# Check that firefox options contain expected capabilities
args, kwargs = webdriver_mock.Remote.call_args
options = kwargs['options']
Expand All @@ -289,7 +309,7 @@ def test_create_remote_driver_firefox_with_version_and_platform(webdriver_mock,
options = kwargs['options']
assert isinstance(options, Options)
assert options.capabilities == expected_capabilities
webdriver_mock.Remote.assert_called_once_with(command_executor=f'{server_url}/wd/hub', options=options)
webdriver_mock.Remote.assert_called_once_with(command_executor=server_url, options=options)


@mock.patch('toolium.config_driver.webdriver')
Expand All @@ -310,7 +330,7 @@ def test_create_remote_driver_firefox_with_version_and_platform_uppercase(webdri
options = kwargs['options']
assert isinstance(options, Options)
assert options.capabilities == expected_capabilities
webdriver_mock.Remote.assert_called_once_with(command_executor=f'{server_url}/wd/hub', options=options)
webdriver_mock.Remote.assert_called_once_with(command_executor=server_url, options=options)


@mock.patch('toolium.config_driver.webdriver')
Expand All @@ -331,7 +351,7 @@ def test_create_remote_driver_firefox_extension(webdriver_mock, config, utils):
options = kwargs['options']
assert isinstance(options, Options)
assert options.capabilities == expected_capabilities
webdriver_mock.Remote.assert_called_once_with(command_executor=f'{server_url}/wd/hub', options=options)
webdriver_mock.Remote.assert_called_once_with(command_executor=server_url, options=options)

# Check that extension has been added to driver
webdriver_mock.Firefox.install_addon.assert_called_once_with(webdriver_mock.Remote(),
Expand Down

0 comments on commit f795a38

Please sign in to comment.