Search code examples
python-3.xinheritancepytestmobile-developmentpython-appium

Pytest appium tests on multiple devices


I am trying to run the same tests on 2 devices (1 emulator and 1 physical device). conftest.py includes:

  • identifying how many devices are connected / online
  • appium fixture for creating desired_capabilities for each device by incrementing the port for each additional appium server
root: 
- conftest.py
- common.py (incldues a class of common functions with appium commands to 
  find elements etc.). I have used the usefixtures decorator to link the 
  appium fixture to the class and call the driver 
- Tests
-- test01.py (includes a class with the test methods, the class also has the usefixtures 
   decorator for the appium fixture). The test methods do not call the appium driver directly. 
   They just call the functions that are in common.py

Additional info: conftest.py contains code to spawn as many appium drivers as devices in a fixture called 'appium_driver':

desired_caps = {'platformName': 'Android', 'automationName': 'uiautomator2','language': 'en', 'locale': 'US', 'uiautomator2ServerInstallTimeout': 50000, 'udid': device, 'appActivity': ".testapp"}

 appium_server_port = 4723 + count
 appium_server_url = "http://127.0.0.1:" + str(appium_server_port)
 option = AppiumOptions().load_capabilities(desired_caps)
   
 driver = AppiumDriver.Remote(command_executor=appium_server_url, options=option)
 count = count + 1
 request.cls.driver = driver
 return driver

 def teardown():
    request.instance.driver.quit()
 request.addfinalizer(teardown)

common.py contains a class with all the common functions referencing AppiumBy cli. I thought creating an object in class instantiation would allow it to be used in any class method

@pytest.mark.usefixtures("appium_driver")
class CommonCommands():

    def __init__(self):
        self.deviceDrv = self.driver

Error:

AttributeError: 'CommonCommands' object has no attribute 'driver'

Solution

  • After much research and youtube'ing on fixtures and appium drivers etc. I changed the project structure a bit. The challenging part is to keep track of all the drivers (one for each device, irrespective of whether it is an emulator or a real device).

    Fixtures is a pytest concept. So tagging it to a generic Python class, as presented in the problem statement, will not work.

    Here is one approach that works for the above scenario:

    • Define all the appium drivers in conftest.py
    • Yield the fixture object to each test_class instead of common.py and pass the driver as an argument to every class_method in common.py

    Still struggling with the appium drivers sometimes crashing during the tests. But that's a different issue.

    After all this, I have a renewed sense of appreciation for fixtures. While the concept of fixtures is hard to get, once you figure it out you can do wonders with them :)