Web UI tests reinforcement with webtau framework (Selenium based)

One of the biggest problem with Web UI tests is their brittleness. Moving a page element around or replacing an input box with a drop down can cause a ripple effect that breaks dozens of your tests.

In this article I will show you how to encapsulate your UI implementation details so your tests can focus on testing features.

I will be using the webtau framework that has primitives designed to help with tests brittleness.

First test attempt

Let’s test a search feature of an imaginary app.

Test:

  • open a search page
  • set a value to an input box that can be located by search-box id
  • simulate enter key and check that there are some results

I claim that there should be only one reason to change this test and that is if the actual functionality of your search experience changes (Single Responsibility Principle anyone?).

However there are four non functional reasons that can force our test to change:

  • search page url changes
  • the way we initiate the search changes: enter key vs mouse click
  • ids/classes/attributes associated with elements are changed
  • server response time becomes slower

Let’s address them one by one.

Extract elements definition

In webtau $(css) creates an instance of PageElement that you use to simulate user actions and query values.

Created instances are lazy and can be defined before the browser is even opened.

This is a step in a right direction, but we still have exposed page url and hardcoded Enter key press.

Extract user actions

Let’s create asubmit method to encapsulate the way users are supposed to initiate the search.

I think the changes we made make the test easier to reason about. But I still want to give it a final touch: move definitions out of a test file so they can be potentially used by other test scenarios.

Encapsulation

Let’s move the action and page elements definitions to a separate class. You may have heard of thePageObject concept before.

In webtau page objects are simple class instances. It is the lazy nature of PageElement that makes this simplicity possible.

It doesn’t matter when we create the instance of the class since searchBox and numberOfResults will be lazily initiated.

Let’s create thePages class with static page object instances to make it convenient to access them from different scenarios.

Our page object is one import away.

Dealing with asynchronous brittleness

Our test is now reinforced and can sustain UI non-functional changes. But there is one unprotected area left uncovered.

During local development our server is blazingly fast and search results are produced in under 5ms. Weeks later we will run the tests in QA environment and most likely we will be dealing with the failed assertion.

Let’s do a final test reinforcement.

We replaced shouldBe with waitToBe. As a result, instead of failing the assertion right away waitTo will re-query numberOfResults multiple times until it times out (driven by configuration).

Groovy, Java and beyond

I have been using Groovy for testing for the last decade and I think it is perfect for the job. But if you are not a Groovy fan, you can use Java or other JVM languages.

If you are interested in Java or other JVM examples, please hit me in the comments and I will be happy to help.

Links

GitHub

Introduction to REST API testing with webtau

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