Robot Pattern: Maintainable Angular UI Tests

John Crowson
ngconf
Published in
3 min readFeb 21, 2019

Motivation

Angular is a fast evolving framework. At a similar pace, there is a growing set of tools to improve our usage of it, including UI tests. Although Protractor is the Angular designated UI testing framework, there has been excitement about Cypress.

Most development teams who use one UI testing framework wouldn’t dare switch, because it would include a total rewrite of their suite.

What if we used a UI testing pattern that allowed us to swap frameworks in and out more easily?

In addition to changing testing frameworks, as a part of the development lifecycle, front-end application are subject to UI layout and functionality changes. One small change could break several different end-to-end tests.

How do we write UI tests that, for each UI change, only require an update in one place, instead of in every UI test that touches the change?

The Robot Testing Pattern

The Robot Testing Pattern is a UI testing architecture introduced by Jake Wharton. It promotes the creation of readable, reusable, and maintainable UI tests through abstracting what is being tested from how it’s being tested.

The Robot Testing Pattern abstracts what is being tested from how it’s being tested

Here’s what our example app functionality looks like:

Clicking “View Less” reduces the table to three rows

The Robot will provide abstracted methods to interact with the view, making the test definition simple:

it('should shrink to show 3 items when View Less is clicked', () => {
listPage.clickViewMoreItemsButton()
.verifyNumberOfItems(5)
.clickViewLessItemsButton()
.verifyNumberOfItems(3);
});

This is exceptionally readable. If we want to test the functionality of clicking “View More” instead, we can reuse the same robot methods.

it('should grow to show 5 items when View More is clicked', () => {
listPage.clickViewLessItemsButton()
.verifyNumberOfItems(3)
.clickViewMoreItemsButton()
.verifyNumberOfItems(5);
});

For each view in our application, we will create a Robot class. It looks like the Builder pattern:

If we refactored to use the Cypress UI testing framework, we would only reimplement the Robot methods.

If we refactored the table to grow and shrink on hover, for example, we would only reimplement the clickViewMoreItemsButton() and clickViewLessItemsButton() Robot methods (along with method renaming).

The test definitions would remain the same.

Resources:

EnterpriseNG is coming November 4th & 5th, 2021.

Come hear top community speakers, experts, leaders, and the Angular team present for 2 stacked days on everything you need to make the most of Angular in your enterprise applications.
Topics will be focused on the following four areas:
• Monorepos
• Micro frontends
• Performance & Scalability
• Maintainability & Quality
Learn more here >> https://enterprise.ng-conf.org/

--

--