2

I'm currently using page objects in my Appium and Python project to run the tests only on the iOS platform. Now I need to implement the same tests for Android (the app is the same).

I know the locators are different for each platform, but the functions I created I can use for both platforms.

In java the @iOSXCUITFindBy and @AndroidFindBy annotations make design easier for this purpose, but so far I haven't found anything similar to use with Appium and Python.

What strategy can I use to reuse the same functions for both platforms (Android and iOS)?

Rafael C.
  • 2,245
  • 4
  • 29
  • 45

3 Answers3

2
  1. If you're using XPath locator strategy you could use XPath union operator - | to combine iOS and Android locators into a single expression:

    def click_some_button(driver):
        element = driver.find_element_by_xpath("//ios/locator/here | //android/locator/here")
        element.click()
    
  2. You can dynamically return this or that WebElement depending on platformName Desired Capability value:

    if (driver.capabilities.get('platformName') == "android"):
        print("android")
    elif (driver.capabilities.get('platformName') == "ios"):
        #ios specific code
    else:
        #throw error or handle other platform
    
Dmitri T
  • 159,985
  • 5
  • 83
  • 133
  • The answer seems to be good. You can also refer this blog: https://lab.getbase.com/mobile-test-automation-with-appium-page-object/ , Well Explained – Saif Siddiqui Aug 10 '19 at 14:27
  • @dmitri-t Thanks for the answer. The option 1 we all know is bad practice and makes testing 10x slower. I thought in the option 2 as a strategy, but imagine if my test has more than 500 functions, will I need to do an `if / else` on all functions? I think it's impossible. I was thinking of creating a generic function (where I can use for both platforms) just replacing the locator, but I still don't know how to implement. – Rafael C. Aug 12 '19 at 21:59
2

I used Robot Framework (python) to create test suites for testing the development of an iOS and Android app. Same app and started at the same time. Automation was done in sprint. Automated tests as the app was being developed.

Initially we created automated tests for both platforms at the same time. Similar ideas to above...If/Else etc... We ran into issues after a few months. I wasn't as simple as If/Else. Functionality of the SAME APP across two mobile platforms changed during the development. Differences in what you can do (development/technical wise) on iOS vs Android platforms differs in some points.

They essentially were the same app but they had differences created by some technical limitations. Allot of tests were simply not applicable across both platforms and would have required allot of effort and ugly tests to shoehorn them to be.

One platform then became a priority over the other. But laying the groundwork for test functionality for both platforms has an overhead which the business didn't want/need as one platform was a priority (with option for he other to become the priority at a later date).

Dropped dual test suites after six months in favour of Android Test Suite separate to iOS Test Suite.

Sure there was some overlap but it became allot easier to manage.

If I were to start over I would have kept them separate at the start.

tldr :) Keep them separate (folder/suite structure and functionality wise).

Brian O'Neill
  • 329
  • 1
  • 5
1

I'm also automating app for both Android and iOS using Appium and Python and I've had same problem, apps are same but of course locators are different.

In order to reuse same method but with different locators I've came up with this solution, example:

class Header(Page):
    def __init__(self, driver):
        super(Header, self).__init__(driver)
        self.os = str(self.driver.desired_capabilities['platformName']).lower()

    # Android
    login_button_android = (MobileBy.ID, 'com.matchbook.client:id/loginButton')

    #iOS
    login_button_ios = (MobileBy.ACCESSIBILITY_ID, 'LOGIN')

    def open_login_page() 
        self.driver.find_element(*getattr(self, 'login_button_' + self.os)).click() 

When you now call open_login_page from outside class it will know which locator to use (Android or iOS) as we retrieved OS with

self.os =str(self.driver.desired_capabilities['platformName']).lower()

in the __init__ method.

On execution 'login_button_' + self.os will become either 'login_button_android' or 'login_button_ios'.

This way you only need 1 method for any number of OS versions, the only difference is in the name of locator variable, they need to have same name except the suffix at the end which should be _android or _ios.

Mate Ajdukovic
  • 340
  • 3
  • 17