Understanding FindElements in Appium
Shreya Bose, Technical Content Writer at BrowserStack - June 30, 2020
All automated tests must locate specific web elements on a website or app in order to interact with them, simulate user scenarios, and gauge the results. This is also true for Appium, a widely used framework for mobile app testing.
This article will explore the FindElement and FindElements commands which are used by Appium testers to locate web elements.
Let’s begin by understanding the nature and purpose of an Element Locator.
An Element Locator is basically the address by which the framework (Appium, in this article) identified a UI element on the mobile app. Each app screen carries multiple UI elements, which means that each of them needs to be identified with a unique address or parameter. Usually, finding the Element Locator is easy, but sometimes the tester may have to explore further to detect a unique address.
Both the FindElement and FindElements commands in Appium can be used to locate web elements. The Find methods take a locator or query object called By. These locators are discussed below.
Before discussing the parameters for Appium find elements, let’s look at an example of the command to be used:
In this example, By.className is the “locator strategy” AKA the parameter by which to find the element. A button represents the “selector” which the parameter uses to find the element. When used in a test automation script, this call will return an object of type WebElement.
Now, let’s explore the parameters or selectors that can be used to find an element in Appium.
When locating an element with its name, the program will return the first element with the name attribute value matching the location. If there is no element with a matching name attribute, a NoSuchElementException is thrown.
The reason for mentioning the “first element” is that multiple elements can have the same name because the developer chose to use non-unique names or auto-generate the names. In this case, the findElement command will return the first element that carries the specified name.
Take the image below.
To locate the circled elements by name, use the code below:
driver.findElement(By.name("Shop byDepartment")).click(); //or driver.findElementByName("Shop byDepartment").click();
By Class Name
In this case, an element is located by the value of its class attribute. However, since a class usually contains multiple elements, this strategy becomes fairly generic in nature. It is not the best way to find a single unique element.
Take the image below:
To locate the circled element by class name, use the code below:
driver.findElementByClassName("android.widget.ImageView").click(); //or driver.findElement(By.className("android.widget.ImageView")).click();
Note: The code will only yield effective results when there exists a unique class name. Be warned that this is usually not the case in Appium.
When locating web elements by ID, Appium will return the first element with the matching ID attribute. In case no element has that matching ID attribute, the program will throw a NoSuchElementException.
Since each element usually tends to have a unique ID, identifying them with this method is usually the most reliable and efficient locator strategy in Appium scripts.
Take the image below:
To locate the circled element by ID, use the code below:
WebElement element = driver.findElementById("in.amazon.mShop.android.shopping:id/action_bar_burger_icon");<br>element.click(); // or WebElement element = driver.findElement(By.id("in.amazon.mShop.android.shopping:id/action_bar_burger_icon"));<br>element.click(); element.click(); // or driver.findElementById("in.amazon.mShop.android.shopping:id/action_bar_burger_icon").click();
When using Appium findElement by XPath, the program analyzes the XML structure of the app and locates a particular element relative to other elements. In fact, originally this strategy was developed to navigate XML data in order to locate unique UI elements.
Remember that XPath selectors are not cross-platform. Hence this method should be used for finding elements only when there is no name or ID assigned to a UI element. XPath tends to have performance and stability issues and can be brittle when employed across platforms or even devices.
However, locating elements by XPath also has certain advantages:
- Allows the formulation of complex queries
- It can be used to find any element in the XML structure available to Appium. This means that even if an element has no ID or Name, it can still be located with XPath
Note: When using the Appium Inspector for inspecting the application XML structure, Appium will return the XPath directly without extra effort.
Using Parent Node
In certain situations, the only option is to locate an element by getting the parent element first and then get its child object. This is done to perform an action on the child element.
Consider the username text box for the Amazon app. The UserName text box does not have an ID, text value, or content-desc attached to it. The className is populated but that does not help because the className of the Password text box will be the same as the user name.
In this case, one must find a unique parent, which is the Amazon Sign in – depicted in the image below:
To locate the parent element, use the code below:
WebElement parentElement = driver.findElement(By.name("Amazon Sign In"));
After getting the parent element, one can then get the child element Views which exists under the selected parent. Use the code below:
List<WebElement> childElements = parentElement.findElements(By.className("android.view.View"));
On getting the Views element in childElements, one can further locate the 5th View element. Refer to the image below for clarity:
Find the 5th View element with the code below:
//This is to get the 5th child element WebElement mainElement = childElements.get(4);
Note: Mention .get(4) to specify the 5th element because the index starts from zero.
On getting the main element (5th), simply identify it’s child element with the code below:
Here’s the complete code:
WebElement parentElement = driver.findElement(By.name("Amazon Sign In")); List<WebElement> childElements = parentElement.findElements(By.className("android.view.View")); WebElement mainElement = childElements.get(4); mainElement.findElement(By.className("android.widget.EditText")).sendKeys("Your_USerName");
Difference between FindElement and FindElements in Appium
The only difference between findElement and findElements in Appium is that the first command returns either a WebElement object or throws an exception. The latter returns a list of WebElements and can return an empty list if no DOM elements match the query.
Clear knowledge of how to find elements in Appium iOS and Android is integral to building effective and sophisticated test scripts. Because of this, all automated app testing personnel need to be conversant in the findElement and findElements commands. Run the code laid out in this article, and start building accurate and result-driven test suites for mobile apps.