Skip to content

iOSFindBy & AndroidFindBy annotations are ignored #211

Closed

Description

@justintilson

I've been trying for a couple of days to get iOSFindBy & AndroidFindBy annotations working with page objects and the PageFactory. I've tried versions 2.2.0 and 3.0.0 of the java-client and tests for Android and iOS, all with the same result - which is the same as not including any annotations.

Here is a truncated version of one of my page objects

public class HomePhonePage extends BaseHomePage {

    public HomePhonePage(AppiumDriver driver) {
        super(driver);

        PageFactory.initElements(new AppiumFieldDecorator(driver,
                        IMPLICIT_WAIT,
                        TimeUnit.SECONDS),
                this
        );
    }

    @iOSFindBy(accessibility = "home_landing_my_favorites_count_label")
    private WebElement myFavoritesCountLabel;

    public String getMyFavoritesCountLabel() {
        return myFavoritesCountLabel.getText();
    }
}

My test code:

    @Test
    public void testHomeIsValid() {

        homePhonePage = new HomePhonePage(driver);
        globalNavPage = new GlobalNavigationPage(driver);

        homePhonePage.clickHamburgerMenu(); //FAILS HERE because element was not found
        globalNavPage.clickHome();

    }

When I debug into PageFactory.initElements, I see [unknown locator] for each property that is a WebElement. Then the PageFactory defaults to looking for each page object's property name as the id or name of the WebElement and fails to find anything.

unknown-locator2

I suspect "I'm doing it wrong" but I can't figure out where. It is behaving as if the annotations are not even there.

Activity

  1. Simon-Kaz commented on Jul 1, 2015

    @Simon-Kaz

    Hey, could you post your capabilities as well? I've been using page factory extensively and haven't encountered this issue.

  2. justintilson commented on Jul 1, 2015

    @justintilson
    Author
    System.out.println(driver.getCapabilities().toString());

    outputs for an Android test:

    Capabilities [{networkConnectionEnabled=true, desired={}, platformVersion=4.4.4, warnings={}, webStorageEnabled=false, locationContextEnabled=false, browserName=Android, takesScreenshot=true, javascriptEnabled=true, databaseEnabled=false, deviceName=192.168.56.101:5555, platform=LINUX}]

    and for an iOS test:

    Capabilities [{networkConnectionEnabled=false, desired={}, warnings={}, webStorageEnabled=false, locationContextEnabled=false, browserName=iOS, takesScreenshot=true, javascriptEnabled=true, databaseEnabled=false, platform=MAC}]

    I also dug a bit deeper into the debugger for the particular field I've included above as it's being decorated by the PageFactory and it shows no annotations (I'm not sure if it should):

    no-annotations

  3. TikhomirovSergey commented on Jul 1, 2015

    @TikhomirovSergey
    Contributor

    @justintilson Hi!
    Is it native app? Maybe hybrid. Maybe you are trying to run test with mobile browser?

  4. TikhomirovSergey commented on Jul 1, 2015

    @TikhomirovSergey
    Contributor

    Capabilities [{networkConnectionEnabled=true, desired={}, platformVersion=4.4.4, warnings={}, webStorageEnabled=false, locationContextEnabled=false, browserName=Android, takesScreenshot=true, javascriptEnabled=true, databaseEnabled=false, deviceName=192.168.56.101:5555, platform=LINUX}]

    Are you tryng to use iOSFindBy for Android

    @iOSFindBy(accessibility = "home_landing_my_favorites_count_label")

    ?

    Please improve your page object as follows

    @iOSFindBy(accessibility = "home_landing_my_favorites_count_label")
    @AndroidFindBy(your locator for android)
        private WebElement myFavoritesCountLabel;

    What the result?

  5. justintilson commented on Jul 1, 2015

    @justintilson
    Author

    @TikhomirovSergey, I'm testing native apps on Android and iOS.

    I have separate tests and page objects for Android and iOS and use the appropriate @findby in each.

  6. justintilson commented on Jul 1, 2015

    @justintilson
    Author

    Here are the desired capabilities that are passed into the Android driver:

    dcs-passed-to-android-driver

    and for the iOS

    dcs-passed-to-ios-driver

  7. justintilson commented on Jul 1, 2015

    @justintilson
    Author

    And if it helps:

    appium-android-settings

    appium-ios-settings

  8. TikhomirovSergey commented on Jul 1, 2015

    @TikhomirovSergey
    Contributor

    Ok. If I clearly understand you

    Appuim features allow to implement one page object for Android/iOS/browser testing. Please look at this

    @iOSFindBy(locator_for_ios) //this locater is used when here is iOS native content
    @AndroidFindBy(locator_for_android)//this locator is used when here 
    //is Android native content
    @FindBy(locator_for_HTML)//this locator is used when here mobile 
    //or desktop browser or webview
     private WebElement myFavoritesCountLabel;

    Ok. Is this used with Android

    public class HomePhonePage extends BaseHomePage {
    
        public HomePhonePage(AppiumDriver driver) {
            super(driver);
    
            PageFactory.initElements(new AppiumFieldDecorator(driver,
                            IMPLICIT_WAIT,
                            TimeUnit.SECONDS),
                    this
            );
        }
    
        @iOSFindBy(accessibility = "home_landing_my_favorites_count_label")
        private WebElement myFavoritesCountLabel;
    
        public String getMyFavoritesCountLabel() {
            return myFavoritesCountLabel.getText();
        }
    }

    ?

    Capabilities [{networkConnectionEnabled=true, desired={}, platformVersion=4.4.4, warnings={}, webStorageEnabled=false, locationContextEnabled=false, browserName=Android, takesScreenshot=true, javascriptEnabled=true, databaseEnabled=false, deviceName=192.168.56.101:5555, platform=LINUX}]

  9. TikhomirovSergey commented on Jul 1, 2015

    @TikhomirovSergey
    Contributor

    ...I am just trying to understand your problem and usecase :)

  10. justintilson commented on Jul 1, 2015

    @justintilson
    Author

    @TikhomirovSergey - I understand that I can use a single page object to test both platforms but I've found in this particular instance it didn't work out well because the implementations are somewhat different and evolving at different rates.

    Here is the Android page object (same as iOS in this instance but in a different package):

    public class HomePhonePage extends BaseHomePage {
    
        public HomePhonePage(AppiumDriver driver) {
            super(driver);
    
            PageFactory.initElements(new AppiumFieldDecorator(driver,
                            IMPLICIT_WAIT,
                            TimeUnit.SECONDS),
                    this
            );
        }
    
        @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"com.wholefoods.wholefoodsmarket:id/tvFavOrangeBubble\")")
        private MobileElement myFavoritesCountLabel;
    
        public String getMyFavoritesCountLabel() {
            return myFavoritesCountLabel.getText();
        }
    }
  11. TikhomirovSergey commented on Jul 1, 2015

    @TikhomirovSergey
    Contributor

    ok. Now it is clear. Is your app hybrid? Appium-specific annotations were designed for native contents. What does return .getContext() method before your test is failed?

  12. justintilson commented on Jul 1, 2015

    @justintilson
    Author

    System.out.println(driver.getContext());

    prints: NATIVE_APP

  13. TikhomirovSergey commented on Jul 1, 2015

    @TikhomirovSergey
    Contributor

    Ok. Is it possible that your project is still depending on java_client 2.2.0 or lower? Please look at your dependencies hierarchy.

  14. justintilson commented on Jul 1, 2015

    @justintilson
    Author

    I thought that might have had something to do with it so I upgraded yesterday. Here is my build.gradle file:

    dependencies {
        testCompile 'org.testng:testng:6.8.21'
        testCompile 'org.seleniumhq.selenium:selenium-java:2.46.0'
        testCompile 'io.appium:java-client:3.0.0'
        testCompile 'com.google.code.gson:gson:2.3.1'
        testCompile 'org.json:json:20140107'
        testCompile 'org.apache.httpcomponents:httpclient:4.3.6'
        testCompile 'net.sf.opencsv:opencsv:2.3'
    }
    

    and the gradle cache:

    gradle-cache

  15. TikhomirovSergey commented on Jul 1, 2015

    @TikhomirovSergey
    Contributor

    androidcaps

    And when you are running

    System.out.println(driver.getCapabilities().toString());

    it is printing

    Capabilities [{networkConnectionEnabled=true, desired={}, platformVersion=4.4.4, warnings={}, webStorageEnabled=false, locationContextEnabled=false, browserName=Android, takesScreenshot=true, javascriptEnabled=true, databaseEnabled=false, deviceName=192.168.56.101:5555, platform=LINUX}]

    Am I right? It interesting where is platformName = "Android".

  16. 1 remaining item

  17. justintilson commented on Jul 1, 2015

    @justintilson
    Author

    I changed the 'platformName' desired capability to 'platform' with no difference and then tried both platform and platformName with the same result.

    Here is the DesiredCapabilities instance that is passed to the AndroidDriver's constructor:

    dcs-passed-to-android-driver3

    and this is how they read after the driver has been instantiated:

    dcs-read-from-driver-after-instantiation

    I'm not sure where LINUX is coming from but it's not something I seem to be able to control.

  18. justintilson commented on Jul 2, 2015

    @justintilson
    Author

    I tried switching to node server (instead of Appium.app) and got the same results. It's still trying to use the property name of the page object to find elements instead of using the values provided in the annotations.

  19. TikhomirovSergey commented on Jul 6, 2015

    @TikhomirovSergey
    Contributor

    @justintilson The PR is proposed and now it is waiting for the merging.

  20. justintilson commented on Jul 6, 2015

    @justintilson
    Author

    @TikhomirovSergey - thanks for the update and your speedy fix. How long is typical for a merge? Our tiny team of two is somewhat blocked by this issue.

  21. TikhomirovSergey commented on Jul 6, 2015

    @TikhomirovSergey
    Contributor

    It is depending on @Jonahss

  22. added a commit that references this issue on Jul 6, 2015
    0936596
  23. Jonahss commented on Jul 6, 2015

    @Jonahss
    Member

    @justintilson merged!
    Are you ok compiling on your own from this repo? Or would you prefer we do a full release to the Maven Central Repository?

  24. justintilson commented on Jul 6, 2015

    @justintilson
    Author

    @Jonahss - our current gradle build script pulls from the Maven repo. I could probably tweak it to download the source and compile it if you weren't planning to do a release for a while. If it's relatively effortless to do a release, that would accelerate things on my side.

  25. Jonahss commented on Jul 6, 2015

    @Jonahss
    Member

    @justintilson Yeah I can do a release :)
    It's relatively effortless compared to gardening in my backyard. But is an incredible amount of effort compared to using npm :P

    I'll start running the test suite now.

  26. Jonahss commented on Jul 6, 2015

    @Jonahss
    Member

    @justintilson Ok, released version 3.1.0

  27. justintilson commented on Jul 6, 2015

    @justintilson
    Author

    It works! I tested on both Android and iOS. @TikhomirovSergey, @Jonahss Thanks so much for moving this issue through so quickly!

  28. Jonahss commented on Jul 6, 2015

    @Jonahss
    Member

    Yay!

    On Mon, Jul 6, 2015 at 3:57 PM, Justin Tilson notifications@github.com
    wrote:

    It works! I tested on both Android and iOS. @TikhomirovSergey
    https://github.com/TikhomirovSergey, @Jonahss
    https://github.com/Jonahss Thanks so much for moving this issue through
    so quickly!

    —
    Reply to this email directly or view it on GitHub
    #211 (comment).

  29. TikhomirovSergey commented on Jul 7, 2015

    @TikhomirovSergey
    Contributor

    I'm happy :)

  30. umer-ali-khan commented on May 17, 2016

    @umer-ali-khan

    one question. Do I need to change the context of the driver before I try to locate webview elements (hybrid app - like FB login) by using Page Objects/Factory as mentioned above?

    FindBy(locator_for_HTML)//this locator is used when here mobile
    //or desktop browser or webview
    private WebElement myFavoritesCountLabel;

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions