9/23/16

How to use Locators in Appium

The next thing to do is to interact with the different elements of the application and for that it is required to locate elements first before interacting. Locating elements can be done on theAndroidDriver instance itself, as it gives us ‘Find Element and ‘Find Elements method to locate elements on the Appium. In this chapter we will learn to use FindElement andFindElements commands or how to locate elements with Appium UiAutomatorViewer/Appium Inspector with different attributes.


How to Use FindElement & FindElements Method in Appium

The difference between Find Element and Find Elements method is the first returns aWebElement object otherwise it throws an exception and the latter returns a list ofWebElements, it can return an empty list if no DOM elements match the query. The Findmethods take a locator or query object called By. ‘By’ strategies are listed below.

By Name

This is also an efficient way to locate an element but again the problem is same as with ID that UI developer make it having non-unique names on a page or auto-generating the names. With this strategy, the first element with the name attribute value matching the location will be returned. If no element has a matching name attribute, a NoSuchElementException will be raised.
Example 1: If an element is given like this:
UIAutomatorViewer_2_2
The above element can be located with the below commands:

Example 2: If an element is given like this:
UIAutomatorViewer_4
The above element can be located with the below commands:

How to find element using ‘content-desc‘ attribute in Appium?

content-desc attribute can be used exactly like text attribute with findElementByName.Look at the example below:
Example 3: If an element is given like this:
UIAutomatorViewer_5
The above element can be located with the below commands:

By Class Name

With this you can find elements based on the value of the class attribute. If an element has many classes then this will match against each of them. A class can contain many elements.
Example: If an element is given like this:
UIAutomatorViewer_3
The above element can be located with the below commands:
Note: This will only work efficiently when this is a unique class name, which is generally not a case in Appium. But still we can use the className in conjunction with other, we will have a detailed example below for it.

By ID

With this strategy, the first element with the id attribute value matching the location will be returned. If no element has a matching id attribute, a NoSuchElementException will be raised. This is the most efficient and preferred way to locate an element, as most of the times IDs are unique.
Example: If an element is given like this:
UIAutomatorViewer_2
The above element can be located with the below commands:

By XPath

Xpath is a true blessing in Appium, as you will end up many situation where you do not have any options but to use xpathXpath can be relative and absolute but it is suggested to always use relative xpath.
Let’s look at the example below for Password field of Amazon Sign In module. Password text box does not have any ID attached to it, not any text value and content-desc. But in this case we have className populated but again that is not help, as the className of the UserNametext box is also same.
Example: If an element is given like this
UIAutomatorViewer_7
If you inspect ‘(5) View{Password} […][…]‘ you will notice that the element got content-desc value as ‘Password‘. It means we can easily locate the (5)element with the attributecontent-desc and then traverse down to (6)element and with that we can easily reach out to its child element EditText.
To locate the (5)element, xpath can be used:

How to use Siblings in Xpath

But our scenario says that we need to locate child of the (6)element. Hence first it is required to locate (6) which is sibling of (5). In Xpath, there is a way to locate siblings elements. Below statement will locate the (6)element:
Once we reach to (6)element, it is easy to locate the Password text field which is child of (6) and that can be done with this:

A complete code would look like this now:


How to find Element using Parent node?

This is again a very important technique to locate element in Appium. There will be many situations where the only option to locate element is to get the parent element first and then get its child object to perform any action on child element.
Consider Username text box for this scenario. UserName text box does not have any IDattached to it, not any text value and content-desc. But in this case we have classNamepopulated but again that is not help, as the className of the Password text box is also same as ‘android.widget.EditText‘. If we go one step up to the parent of EditText, it is View with theclassName as ‘android.view.View‘ which is again not unique. So, we need to go one more step up for finding unique parent, which is Amazon Sign In shown in the below image:
UIAutomatorViewer_7_1
The above element can be located with the below commands:
With using above statement, we would be able to get the parent element, but we are interested in the child elements of the parent. With the below statement, we will get all the child elements ‘Views‘ which is under selected parent:
Now we have all the Views element with us in childElements, but we are interested in the 5th child element, as username text box is under that 5th View element. See the below screenshot for help.
UIAutomatorViewer_6
The above element can be located with the below commands:
Note: We have mention .get(4) for 5th element because the index starts from zero.
Once we get the main element(5th), it is easy to point it’s child element:
A complete code would look like this now:

Exercise

1) Start Appium Node Server
2) Launch Amazon App
3) Click on ‘Shop By Department’ using By.ID.
4) Click on Menu button using By.ClassName to display the menu list.
5) Click on Home link using By.Name to navigate back to the Home Screen.
6) Click on the SIgn In link using By.Name to Log In in to the application.
7) Enter text in the UserName field using By.xpath & Sibling strategy
8) Enter text in the Password field using Parent node strategy
9) Click on the Submit button using content-desc attribute.

import io.appium.java_client.android.AndroidDriver;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
public class Amazon_LogIn_Test {
private static AndroidDriver driver;
public static void main(String[] args) throws MalformedURLException {
File classpathRoot = new File(System.getProperty("user.dir"));
File appDir = new File(classpathRoot, "/Apps/Amazon/");
File app = new File(appDir, "in.amazon.mShop.android.shopping.apk");
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(CapabilityType.BROWSER_NAME, "");
capabilities.setCapability("deviceName", "Micromax A311");
capabilities.setCapability("platformVersion", "4.4.2");
capabilities.setCapability("platformName", "Android");
capabilities.setCapability("app", app.getAbsolutePath());
capabilities.setCapability("appPackage", "in.amazon.mShop.android.shopping");
capabilities.setCapability("appActivity", "com.amazon.mShop.home.HomeActivity");
driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
driver.manage().timeouts().implicitlyWait(80, TimeUnit.SECONDS);
// Click on Shop by Deparment link
driver.findElementById("in.amazon.mShop.android.shopping:id/web_home_shop_by_department_label").click();
// Click on Main menu
driver.findElementByClassName("android.widget.ImageView").click();
// Click on Home link under Main menu
driver.findElement(By.name("Home")).click();
// Click on Sign In link on the Home Screen
driver.findElementByName("Sign inHello. Link").click();
// Entering UserName using Parent node strategy
WebElement parentElement = driver.findElement(By.name("Amazon Sign In"));
List childElements = parentElement.findElements(By.className("android.view.View"));
WebElement mainElement = childElements.get(4);
mainElement.findElement(By.className("android.widget.EditText")).sendKeys("Your_UserName");
// Entering Password using Xpath & Sibling strategy
driver.findElementByXPath("//android.view.View[@content-desc='Password']/following-sibling::android.view.View/android.widget.EditText").sendKeys("Your_Password");
// Click on Sign In button
driver.findElement(By.name("Sign in")).click();
// This is to kill the Android driver
driver.quit();
}
}




Google Q&A Forum