Skip to content

iOS/Android driver compatibility issue on a cross-platform testing #405

Closed

Description

@sbjymc

Description

I'm using java-client 2.10 in my appium test framework, it's working good on my environment both for ios and android native application testing, I can reuse almost all the basic method like below:

public static AppiumDriver driver;

public static void setUp() {
if (PLATFORM_NAME.equals("ios")){
driver = new IOSDriver(new URL(DRIVER_AGENT),capabilities);
}
if (PLATFORM_NAME.equals("android")){
driver = new AndroidDriver(new URL(DRIVER_AGENT),capabilities);
}
}

Then I can create some common method likes 'click a object name' for both ios and android

public static void clickObjectByName(final String ObjectName) {
driver.findElementByName(ObjectName).click();
}

However, the driver is not working when I upgraded Java-client to 3.4.0
it request to create separately 'AndDriver' and 'iOSDRIVER' instance, it means that the common methods which I setup in above example could not be reuse again, and I need to setup 2 different test framework for ios and android.

So I think current Java-Client is not friendly for the cross-platform compatibility. can we make some updates?

And I found several people have the same query, here is the link:
https://discuss.appium.io/t/ios-android-driver-casting-on-a-shared-test-code-base/1095

Activity

  1. SrinivasanTarget commented on Jun 7, 2016

    @SrinivasanTarget
    Member

    @sbjymc I see above link is broken. I recommend to go through our Release log (both client and server) and sync up with the releases every time we update.Since you are using old version of java-client doesn't mean java-client is not user friendly for cross platform compatibility.There are lot more wonderful features/fixes we released there after.

    Try to go through our wiki and the change logs.Incase of any questions please raise in discuss.appium.io. Please do raise issues incase if any along with server logs inform of gist to look further.Happy to help if the issue template is followed properly.

  2. TikhomirovSergey commented on Jun 7, 2016

    @TikhomirovSergey
    Contributor

    There a lot of changes have been added since 2.1.0. It is possible that new releases are not compatible with code that uses very old versions.

    Please follow the @SrinivasanTarget's advice.

  3. TikhomirovSergey commented on Jun 7, 2016

    @TikhomirovSergey
    Contributor

    But we can solve each one separated problem. You can open an issue for each one problem that you face and a bug is suspected.

  4. sbjymc commented on Jun 8, 2016

    @sbjymc
    Author

    @SrinivasanTarget @TikhomirovSergey
    Thanks for your comments, I agree that there are a lot of changes have been added after 2.1.0, and these changes have a lot of wonderful features for ios and android. So I try to upgrade my Java client.

    However, We could not share test code(librarys) between iOS and Android using one driver and this seems to make our framework more complex. we have to setup 2 projects for ios and android since we need to initialize 2 different driver for them.
    I searched the solutions on appium discuss forum, but there is nothing...
    And It would be great if Java-client developer could share a sample code for cross-platform in one framework which could shard the method using the iOS/android driver.

    PS: the link I paste could be opened by copy/paste directly in browser.

    Thanks for your kindly help.

  5. rompic commented on Jun 8, 2016

    @rompic
    Contributor

    i think you should look into
    #267

    to get the most out of the cross platform capabilities
    also look into #240 to start the appium server programmatically

  6. rompic commented on Jun 8, 2016

    @rompic
    Contributor

    I use something like:

    AppiumServiceBuilder serviceBuilder = new AppiumServiceBuilder().usingAnyFreePort();
    service=AppiumDriverLocalService.buildService(serviceBuilder);
    service.start();
    driver = (isTargetAndroid()) ? getAndroidDriver(service.getUrl(), false, false) : getIOSDriver(service.getUrl(), false, false);
    

    where isTargetAndroid() is a private method in my code which returns whether the script was started with android or ios as target.
    the getAndroidDriver and getIOSDriver start the relevant driver.

        public static AppiumDriver getAndroidDriver(URL appiumUrl, boolean fullReset, boolean noReset) {
            DesiredCapabilities capabilities = new DesiredCapabilities();
            capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "**TBD**");
            capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "**TBD**");
            capabilities.setCapability(MobileCapabilityType.APP, appUrl);
            capabilities.setCapability(AndroidMobileCapabilityType.NO_SIGN,true); 
            capabilities.setCapability(AndroidMobileCapabilityType.UNICODE_KEYBOARD,true); //set unicodekeyboard in order to support umlauts 
            capabilities.setCapability(AndroidMobileCapabilityType.RESET_KEYBOARD,true); //reset keyboard after tests
            capabilities.setCapability(AndroidMobileCapabilityType.IGNORE_UNIMPORTANT_VIEWS,true); //speeds up tests, as views that are not important i.e. for accessiblity are not shown on android. Is disabled on demand in tests using driver.ignoreunimporantViews
    
    
            //note that setting appPackage and appActivity is not necessary starting from API level 19 (i.e. 4.4) as it is automatically detected
            //should not be necessary anymore, but detected default is omg.abc.SplashActivity which is never shown on certain flavours of the app
            capabilities.setCapability(AndroidMobileCapabilityType.APP_WAIT_ACTIVITY, "omg.abc.android.bdf.MainActivity"); 
    
            //only on simulator;
            if(simOrEmulator) {
                capabilities.setCapability("language", language);
            }
    
            if (fullReset) {
                capabilities.setCapability("fullReset", fullReset);
            }
            if (noReset) {
                capabilities.setCapability("noReset", noReset);
            }
    
            return new AndroidDriver(appiumUrl,capabilities);
        }
    
        public static AppiumDriver getIOSDriver(URL appiumUrl, boolean fullReset, boolean noReset) {
            DesiredCapabilities capabilities = new DesiredCapabilities();
            capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "9.3");
            capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "iPhone 6");
            capabilities.setCapability(MobileCapabilityType.APP, appUrl);
            capabilities.setCapability("bundleId", "**TBD**"); //todo set from script
    
            //only on simulator;
            if(simOrEmulator) {
                capabilities.setCapability("language", language);
            }
    
            capabilities.setCapability("locationServicesAuthorized", true);
            capabilities.setCapability("locationServicesEnabled", true);
            capabilities.setCapability("autoAcceptAlerts", true);
    
            if (fullReset) {
                capabilities.setCapability("fullReset", fullReset);
            }
            if (noReset) {
                capabilities.setCapability("noReset", noReset);
            }
            return new IOSDriver(appiumUrl,capabilities);
        }
    

    I then use the driver in all of my tests.

  7. rompic commented on Jun 8, 2016

    @rompic
    Contributor

    I also think that the find by name locator strategy has been removed lately.

  8. sbjymc commented on Jun 8, 2016

    @sbjymc
    Author

    @rompic thanks for you kindly help. I have a question in your code:

    driver = (isTargetAndroid()) ? getAndroidDriver(service.getUrl(), false, false) : getIOSDriver(service.getUrl(), false, false);

    The object 'driver' is created by 'AppiumDriver' or 'IOSDriver' or 'AndroidDriver' ?

  9. rompic commented on Jun 8, 2016

    @rompic
    Contributor

    driver is a static class variable of the AppiumDriver type

  10. rompic commented on Jun 8, 2016

    @rompic
    Contributor

    And the instance is created by the relevant method

  11. sbjymc commented on Jun 8, 2016

    @sbjymc
    Author

    thanks @rompic, I will try it on my codes.

  12. sbjymc commented on Jun 8, 2016

    @sbjymc
    Author

    hi @rompic
    Since the instance is created dynamically by the relevant method, In your code, it still could not get the full features for iOS driver or Android driver, it just inherits the methods from AppiumDriver<MobileElement>, but not AppiumDriver<IOSElement> or AppiumDriver<AndroidElement>
    am I right?

  13. sbjymc commented on Jun 8, 2016

    @sbjymc
    Author

    Update my last comments since some code could not be recognized by web scripts

  14. rompic commented on Jun 8, 2016

    @rompic
    Contributor

    What do you mean exactly?
    The correct findby strategies are automatically selected using the page object pattern.please provide an example that doesn't work. Btw. Discuss.appium.io would be a better place for this discussion...

  15. rompic commented on Jun 11, 2016

    @rompic
    Contributor

    @sbjymc i guess I see your point now concerning the features of iOS and Android drivers

    I have a generic AppiumDriver and create an instance of Android or IOSDriver depending on a system property. Now I cannot access driver.toggleLocationServices() which is only available for android.

    @TikhomirovSergey what is the best way to handle this?

  16. rompic commented on Jun 12, 2016

    @rompic
    Contributor
        if(driver instanceof AndroidDriver) {
            ((AndroidDriver) driver).toggleLocationServices();
        }
    

    seems to do the trick

  17. email2vimalraj commented on Jun 13, 2016

    @email2vimalraj
    Contributor

    @rompic : We follow the same approach as you suggested. At run time we get an instance of driver and check whether it belongs to AndroidDriver or iOSDriver. If user access any methods specific to iOS while automating on android, we throw an UnsupportedOperationException.

  18. sbjymc commented on Jun 15, 2016

    @sbjymc
    Author

    Got it, thanks @rompic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions