10
votes

I am testing my Android application using Appium framework. I have an android screen that doesn't have ids for its views (and I don't want to add...), so I thought using Xpath.

This is how the screen looks like in UI Automator Viewer: enter image description here

I want to get all the relative layouts (marked in red - sixteen items)

I tried the following:

 List<WebElement> webElementslist =
 mAppDriver.findElementsByXPath("//android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.ViewAnimator[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.RelativeLayout[1]/android.widget.RelativeLayout[1]/android.widget.ScrollView[1]/android.widget.LinearLayout[1]/android.widget.LinearLayout[1]/android.widget.LinearLayout[2]");

But I didn't get any items.

I searched the web and found the next xpath tutorials, tried more options, but again with no success.

http://www.zvon.org/comp/r/tut-XPath_1.html#intro

http://www.w3.org/TR/xpath/

Would appreciate any help.

4
That's looks too verbose, how about something like this: //LinearLayout[TextView]/LinearLayout/LinearLayout/RelativeLayout? (I'm not familiar with XPath in appium though) - har07
Still not good, giving me zero items. I tried also less detailed, still with no results. - Ofir A.
If it is Me, I'd start with simplest XPath that return something then tweak it further to return only the elements I wanted. Is //android.widget.LinearLayout[android.widget.TextView] or even //android.widget.TextView return something? - har07
This is what strange about it. When the xPath is only //android.widget.TextView I get all the TextViews I have, but it multiplies them - if I have 16 TextViews I get 240.. - Ofir A.
Put up a gist to the server logs please. - Jess

4 Answers

8
votes

Right now there's a couple nasty bugs with XPath on android that explain the behaviors you're seeing. They are scheduled to be fixed in the 1.3.1 release

  1. You can't search by root nodes.. link
    • Unfortunately, this means that a verbose xpath is likely the xpath(pun) to success
  2. You sometimes get 240 of an element when you only have 16 link

Ideally, you could look for the resource-id of the android.widget.LinearLayout parent of all 16 RelativeLayouts and then do something like:

//android.widget.LinearLayout[@resource-id="foo"]/android.widget.RelativeLayout

Your verbose solution did not work because you gave one of the layouts a position of [2].

Here it is, fixed:

//android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.ViewAnimator[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.RelativeLayout[1]/android.widget.RelativeLayout[1]/android.widget.ScrollView[1]/android.widget.LinearLayout[1]/android.widget.LinearLayout[1]/android.widget.LinearLayout/android.widget.RelativeLayout

.... please, please use the first solution.

I'm looking into a solution for your problem using UiAutomator locator strategy, but no answers yet (because .fromChild() and .fromParent() seem to be broken)

1
votes

Keeping in mind the fact that //foo[1] returns all foo nodes which are the first children of a their parent (not the first child of the foo node) try something like this:

//ScrollView/LinearLayout/LinearLayout[2]/LinearLayout/RelativeLayout

Not tested, but it should give you all the RelativeLayouts which are a child of a LinearLayout which is a child of a LinearLayout which is the second child of a LinearLayout which is the child of a ScrollView.

1
votes

Just try this u can access easily

driver.findElement(By.xpath("//*[@class='android.widget.FrameLayout' and @bounds='[418,564][780,885]']")).click();

Screenshot of UI

0
votes

The following code worked for me:

WebElement webElement = driver.findElementByXPath("//android.widget.ListView[1]/android.widget.LinearLayout[1]");

Courtesy: Unable to locate element using xpath in Appium