Implementing re-usable custom locators for RF SeleniumLibrary

I could have taken an screenshot of one of the XPath expressions, but as I am not a big fan of photos of code, here is a path in forest instead.

As a full stack developer, I am often involved in multiple different testing phases of an application. Recently, the front-end applications I have been working with have been implemented with React and unit-tested with Jest and react-testing-library. In addition to these unit-tests, the projects have usually had end-to-end tests run in a browser and implemented with Robot Framework and SeleniumLibrary.

These two testing tools, react-testing-libary and SeleniumLibrary, have very different approaches to locating HTML elements. react-testing-library, and all other testing libraries based on the dom-testing-library, provides methods for finding elements in a similar way that the end-user would use, such as findByLabelText(). SeleniumLibrarys locators are more developer focused and use, for example, elements id attribute or a XPath expression to locate the element. This difference in locating elements is one of the things that makes transitions between development and testing tasks more challenging for me.

In order to reduce the cost of context switches between development and testing task, I have often implemented some sort of hack to the end-to-end tests in order to produce XPath expressions to match the logic of the finder functions provided by the dom-testing-library. While these hacks have greatly helped to reduce the confusion when switching between these tools, they have not been very clean or re-usable solutions. For example:

*** Keywords ***
Title locator strategy
[Arguments] ${browser} ${locator} ${tag} ${constraints}
${element}= Get WebElements //*[@title='${locator}']
[Return] ${element}
Add custom locator strategies
FOR ${name} ${keyword} IN
... title Title locator strategy
# Other custom locators
Run Keyword And Ignore Error
... Add Location Strategy ${name} ${keyword}
END

After implementing a very similar hacky solution to many different projects, I decided to look into implementing these dom-testing-library inspired locators as custom locators that could be installed as a Python package. According to the most recent recommendations on how to extend SeleniumLibrary, it seemed like the way to go would be to implement the custom locators in a SeleniumLibrary plugin.

The plugin interface of the SeleniumLibrary provides an easy way to extend the default element finder. The element finder can be modified through the element_finder property of LibraryComponent, which is the base class that the plugin class must inherit. The default element finder can be created as an instance of ElementFinder by providing the constructor with the same context as the plugin class instance is initialized with. This created ElementFinder instance can then be used to register the custom locator strategies.

My solution replaces the default element finder with a new element finder that registers custom locators to implement the dom-testing-library style locators when the plugin is loaded. This allows easy re-usability and simplifies the setup process a lot. See import and usage example below.

*** Settings ***
Library SeleniumLibrary plugins=TestingLibrarySelectorsPlugin
*** Test cases ***
Click search bar
Click element placeholder:Search

The actual locator functions are mostly just wrappers for the xpath:… locator strategy of the SeleniumLibrary. At the moment, the only more complex locator is the find by label strategy, which will first find all the label elements with matching for or id attributes. This will allow locating input fields with matching id or aria-labelledby attributes. See the _plugin.py file in GitHub for the implementation.

At this point I had pretty much all of the features implemented that I have been usually using and could have been happy with what I had implemented. However, as the dom-testing-library supports also regexps and functions to match elements, I wanted to try something similar. Parsing the regexps from the locator criteria and passing it to matches() function in XPath expression seemed simple enough. And it was, but any of the browsers available didn’t seem to support this approach. Nevertheless, I still wanted to know if these XPath expressions are valid.

In order to test the XPath expression which uses the matches function, I decided to use the lxml Python library. While lxml also lacks the support for matches function out-of-the-box, it provides an option to implement custom functions to be used in the XPath expression. I implemented a custom matches() function that seems to find elements as expected. Could be possible that I made similar mistakes twice, but I would argue that there is no hurry to fix possible bugs before the matches() function, and XPath2 in general, is supported by any of the target browsers.

To summarize, I implemented a custom locator strategies for SeleniumLibrary as a plugin. My goal was to decrease the cost context switches when moving from development to testing tasks, and vice versa. The code is available in GitHub and as a python package.

Step-by-step getting started

In order to be able to use these locators in your Robot Framework Selenium library:

  • Install rf-se-dtl-selectors-plugin by running pip install rf-se-dtl-selectors-plugin.
  • Add TestingLibrarySelectorsPlugin to plugins parameter of SeleniumLibrary import:
*** Settings ***
Library SeleniumLibrary plugins=TestingLibrarySelectorsPlugin
  • Use provided custom locators, for example:
*** Test cases ***
Click search bar
Click element placeholder:Search

--

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

14 Things I Wish I Knew Before Becoming a Software Engineer

Tencent IM:Chat API For Real-Time In-App Communication

Kind, Keycloak and ArgoCD with SSO

An informal introduction to Python

Integrating TypeForm and Appbase.io using Zapier with Zero Lines of Code

Using Envoy Proxy to Improve Reliability, Security, and Observability of Microservices

Envoy Proxy logo

Balancer Grants Monthly Update #4

Image Classification App with Tensor Flow Lite on Android[Beginner]

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Toni Kangas

Toni Kangas

More from Medium

Which is the best, Selenium or Cypress?

Is Chrome Developer Tool a Future For Test Automation? — Devstringx

Selenium Webdriver Architecture

Advance Your API Testing Using JSON Schema on Your Test Framework