How to make better xpaths for web tests.

How to make better xpaths for web tests.

Problem

My web-based steps in Cycle are not finding the elements I want them to, or finding the wrong elements and giving me false-positives.

Solution

When possible, it is best to define elements to interact with on a web page by a static value that is unique to the element you are looking for or interacting with. For example, on google.com the search box might be selected with:

And I click element "name:q" in web browser

However, some web pages are rendered with dynamic element names, descriptions, and IDs making it difficult or sometimes impossible to identify an element with a unique, unchanging identifier specific to that element. In these instances, you may need to use a relative xpath to identify the element.

 

What is a relative XPath?

A relative XPath gives you the ability to identify an element by determining a unique starting point to look for the element, then defining a relative path to that element. Identifying a relative xpath can be a tedious process that may involve some trial and error to identify a unique relative xpath to the element you are trying to identify. There may be other elements on the screen that share similar attributes to the element you are trying to interact with and you may unintentionally interact with one of those elements rather than the intended element.

 

How do I create and test one?

Using the Console Drawer in Google Chrome's Inspect Element Panel can save time and allow you to ensure the relative xpath you have defined is the proper relative xpath for the element you want to interact with. Once you have used the method described below to validate your xpath, you can simply copy and paste into your Feature and know that Cycle will identify the correct element.

You can use the console to write your relative xpath and to test it against other elements on the page. The steps below use the inspect element and console built into Google Chrome, but there are Chrome extensions such as ChroPath and Natu WebSync that provide the same functionality and additional features.

 

Example

The JDA web interface uses dynamic web element identifiers with numerical values in the element names that can change each time a change is deployed to an environment. The following example shows how I can use the console within the Chrome inspect element panel to identify and test a relative xpath for a specific element.

In this example, I want to find the “LPNs” button on the Inventory screen so I can click it to see the LPNs in inventory.

I start by right clicking on the element I want Cycle to interact with and choosing “Inspect” in the web browser. This will open the inspector within the web browser and show me the DOM tree of elements on the web page:

xpath1c.png

xpath1b.png

I know I can’t use the element’s ID “rpCountButton-1157-btnInnerEl” because the “1157” in the id may change in the future and my feature will no longer work if that value changes. So, I need to define a relative xpath to the same element.

It might make sense to simply look for a “span” object containing the text “LPN’s”. That should help me pinpoint the element I want Cycle to interact with, but that might not be enough to specify the correct element.

I can use the console drawer to test my potential xpath to make sure it gives me the expected results.

1) Open the console drawer by clicking the vertical ellipsis in the inspect element toolbar and selecting the option “Show console drawer”

xpath2.png

This opens the console drawer within inspector. You may need to resize the console drawer to give more room to review results when you start searching for xpaths in the web page. A prompt appears at the bottom of the drawer. This is where you can evaluate the xpath you intend to use by searching for it within the web page and  DOM tree.

 

xpath3b.png

 

2) Use the following syntax to search for an xpath replacing the "//your_xpath_here" with the xpath of the element you want to identify.

$x(“//your_xpath_here”)

In my example, I want to find a span object with text ‘LPNs’. So I enter the following xpath in the console and press Enter:

$x("//span[contains(text(),'LPNs')]")

Note: You will need to change the innermost quotes from double quotes to single quotes if you are trying to copy and paste an xpath into this format.

3) The results show that there are 2 span objects found using the xpath from above. Click the arrow icon to expand the results and see the elements listed:

 

xpath4.png

4) Hovering the mouse over the element in the list will highlight the element on the web page. This will allow you to quickly identify which of the returned elements is the one you need to find a more specific relative xpath to identify for Cycle. Clicking the element name in the console will take you directly to the element in the DOM tree displayed in the inspector.

First span object returned by xpath search:

xpath5.png

 

Second span object returned by xpath search:

xpath6.png

 

 

5) I can see that the first element returned by my xpath search is the element I want to identify. Now, I can use additional parameters to narrow my search so only one result is returned.

In this instance, I can see that the id for the span with “LPNs” text that I need to click starts with “rpCountButton” whereas the other span ID starts with “gridcolumn”. So, I will update my xpath search and test it to see if it is specific enough to only return the object I am interested in.

$x("//span[starts-with(@id,'rpCountButton') and contains(text(),'LPNs')]")

6) After making the xpath search more specific, the specific element I need to click is returned in the console.

 

xpath8.png

 

7) I can then take the xpath I searched for in the console and use it as the xpath in my Cycle feature.

And I see element "xPath:// span[starts-with(@id,'rpCountButton') and contains(text(),'LPNs')]" in web browser within $wait_short seconds

 

In this way, by combining: span[starts-with() and contains()] you can create relative xpaths that point to a very specific element of a webpage but do not use unreliable dynamically generated ids.

 

    • Related Articles

    • How to use Web API steps

      Web API steps introduced in Cycle 2.5 can be used to send HTTP requests to exposed web API endpoints. The Cycle Web API steps support POST and GET request methods using the JSON data format. Cycle also includes steps for handling HTTP responses ...
    • How to make better Cycle tests with Backgrounds and After Scenarios.

      Problem Cycle Features can often require set-ups before a system is in the correct state to begin the test or cleanup after having run to return everything to a clean state. Solution Cycle includes the ability to use two special types of Scenarios ...
    • How To Disable Chrome Auto-Update for Test Environments

      Problem Google Chrome will auto-update when a new version becomes available.  When this occurs, the Chrome Webdriver being used by Cycle will no longer match the version of Chrome and may become unstable. Solution To prevent unexpected issues, Chrome ...
    • How To Use WinAppDriver UI Recorder to Record xPath

      Why You Might Use WinAppDriver (WAD) UIRecorder Cycle native app steps using WinAppDriver allow for the use of several object locator types to identify objects within the app. Whenever possible, it is best to identify application objects using the ...
    • How To Post Jenkins Pipeline Results from the Cycle Appliance to Slack

      The Cycle Appliance provides a platform that facilitates continuous testing and continuous integration through cloud-based infrastructure running Jenkins in Azure. A key aspect of continuous testing and continuous integration is giving your ...