Sunday 10 March 2019

Pop Goes the Tests



Behaviour Driven Development (BDD) is about so much more than automated tests but the reason these things are so frequently conflated is because an effective implementation of BDD principles presents the opportunity to write tests that proves your systems behaviour.

A frequent mistake when implementing these automated tests is to concentrate too much on the presented User Interface (UI) over the actual behaviour of the software. The purpose of these tests first and foremost should be to validate that things work, that isn't to say that defects in the UI aren't important but they are likely to be less impactful than broken functionality.

Alongside this a frequent criticism you will hear from teams that implemented automated tests is that they are flaky or can't be relied upon, if when tests fail the issue can be with the tests themselves then there becomes little point in running them. The source of this fragility again is often an overemphasis on the UI when implementing the tests.

UI is often an area of frequent change and tests that are too closely tied to a particular implementation of look and feel can become brittle. The Page Object Pattern (POP) is a technique for implementing automated tests that can address this fragility by encapsulating UI details into a single place whilst leaving the rest of the elements that make up the tests to concentrate on function using a business domain language.

Feature Files

Although not expressly part of POP the approach can be undermined when feature files contain too many UI related details. The language used in feature files should reflect the operations users want to complete using concise phrases that both business stakeholders and users would likely use to describe what they are doing.

As an example two different ways of describing a login process might be:

"I'm entering my username into the first text box, I'm entering my password into the second text box, I'm clicking the terms and conditions checkbox, I'm clicking the login button" 

"I'm logging into the site"

The first describes in great detail the interaction with the various UI components on the screen as well as the details of what is happening under the hood, the second is a much more concise explanation of the process the user is trying to complete. The first would need to be changed should the implementation of the login process change, the second would be unlikely to change unless there is a significant change in the flow of the site.

Those that are familiar with the site have an implicit understanding of how the second description is realised and it therefore isn't necessary to go beyond this level of detail.

Page Object Models

Keeping the feature file language simple and concise allows for the code that will underpin the process (usually called step definitions) to be written in such a way as to avoid the need for frequent refactoring when the UI of the experience may change. Obviously since the interactions with the UI need to be automated within the tests this detail does need to be dealt with somewhere, this is where Page Object Models become part of the mix.

Page Object Models provide an encapsulation of the implementation detail of a page and present a business focussed implementation. To return to our previous example the Page Object Model for out login page would define a login method that internally automates the detailed steps listed in the first description, this leaves the test themselves to use the simplified language of the second description.

Should the details of the login process change the the implementation of the Page Object Model would need to be updated but the tests themselves can remain unchanged. This isolation of change promotes stability in the tests allowing them to concentrate on describing and testing function over form.

SOLID Tests

POP and the use of Page Object Models is an example of applying the same engineering discipline to writing tests as to writing the software they are testing. This frequently isn't the case, tests are often the most untidy part of a code base where they are simply churned out rather than thought through and executed with the same care and attention.

Whilst tests may not represent code that is deployed into production they are the mechanism, or at least should be, that gives the confidence to action deployments. Can this confidence be forthcoming if they are sloppily implemented or can't be relied upon to adequately and reliably verify the operation of the system?

Sometimes the reluctance of developers to implement tests is also driven by the fact that the code in this area is difficult to work with and time consuming to change. Putting the implementation of the tests under proper engineering scrutiny can remove this barrier.

If code is worth writing, whether it be implementation of functionality of tests to verify it, then it's worth writing well.

No comments:

Post a Comment