Main menu

Three practices for creating readable test code

You’ve probably read before that writing code that is readable and easy to understand is considered good practice for any software developer. Readable code takes less time to understand, to hand over to your colleagues or clients and to update if needs be. Since writing automated checks is essentially just another form of software development (this was true in 2005 and it sure hasn’t changed since then), it makes sense to apply the ‘write readable code’ practice there as well. But how do you go about doing that? In this post, I would like to introduce three practices that are guaranteed to have a positive impact on the readability of your test code.

Practice: Use fluent assertions libraries
Some other fans of readable code with far better development skills than yours truly have created some useful libraries that allow you to write assertions in a style that is almost equal to natural languauge, so-called fluent assertions. Two examples of these fluent assertion libraries for Java are AssertJ and Truth.

Let’s take AssertJ as an example. Consider the following TestNG assertions:

The exact same checks are being executed, but the AssertJ assertions are the better readable ones in my opinion, since you can read them from the left to the right without having to jump back in order to understand what the assertion does. AssertJ has many more features for improving the readability of your test code, so be sure to check it out. The library also comes with a script that automatically converts your TestNG assertions to AssertJ assertions for you.

Practice: Have Page Object methods return Page Objects
This practice applies mostly to Selenium WebDriver code, although I can imagine there are other uses for it as well. When you use the Page Object model in your code, you can easily improve the readability of your tests by assigning Page Object return types to all methods in your Page Object. Each method represents a specific user action that is to be performed on the page, and the type of Page Object that is returned depends on the page where the user will end up after that specific action is performed. For example, a simple LoginPage object could look like this:

You can instantly see what this test does, due to the fact that all of our Page Object methods return a specific type of Page Object. This enables us to chain methods from either the same or different Page Objects (as long as their return types match up) and create this type of readable tests.

Practice: Employ a Given/When/Then structure for your tests wherever possible
Another way to improve the readability of your test code is to structure your tests following the Given/When/Then format that is often used in Behaviour Driven Development (BDD). This applies even when you’re not doing BDD, by the way. Just think of it like this:

Given: set up test data and other preconditions

When: perform a specific action

Then: check the results

Some test tools support this format explicitly, for example REST Assured:

An additional benefit of writing your tests in this way is that it makes it much easier to discuss them with people without any substantial programming background. Most people will recognize what a test does if you break them down in this way, even when they lack programming knowledge.

I hope there’s at least something that you can take away from this post and apply it to your existing test suite in order to make it more readable. You’ll be doing yourself, your clients and your fellow team members a huge favour.

“Readable” is very subjective term. For example – I don’t need the practices you mention in order to read the code. Probably the term “closer to natural English” would suit better for the problem you are trying to solve.

But my question is – how often non-technical persons read auto test code? I have yet to meet a business person who wants to read auto test code:) If what you really need your tests to be described in close to natural English, then why not write test comments in plain natural English and then generate some kind of auto test documentation in HTML or other form? Code should be well written, but it does not need to be “readable” as in “close to natural English”.

Some other problems your suggestions create:
1. Fluent assertions can be more difficult to debug.
2. With too much test method chaining you don’t know in which page you are (if you use it across different pages).
3. Given/When/Then is not very suitable for longer test flows (which is often the case in end-to-end UI automation).

Yes, readable is a subjective term, but isn’t there a significant overlap between ‘readable’ and ‘closer to natural English’? I am sure that there are a lot of situations where people might benefit from code that expresses its purpose in a way that is closer to natural language (and therefore better readable). I get that not everybody ‘needs’ these practices. But I have encountered several situations (my current project being one) where explaining the test code to new project members (often less experienced) has been made significantly easier exactly because I have applied the principles I have explained in this blog post. Sure, business people don’t read the code, but those aren’t the only stakeholders/users.

I am a firm believer in code speaking for itself rather than having to rely on comments and auto-generated HTML documentation, because there’s no guarantee that that documentation will be up to date and can be relied on. Readable test code is, because that’s the exact same bits and bytes that will be executed.

As for the other ‘problems’ you mention:
1. Is that true? The output generated by AssertJ (see here, especially when you’re using as()) and Truth (see here) seem easier to debug rather than harder to me. But I’m to examples of the opposite.
2. A very good point, and one I failed to mention in the original post. I never use it across pages for that exact same reason.
3. That depends on how your tests are structured, I think. In my current project we have some pretty long test scenarios, but they’re all written using Given/When/Then (with the use of SpecFlow, but you could do the same thing without). It can be tricky, I admit that. It’s one of the reasons I’m not really a fan of end-to-end UI test automation (anymore).

Finally, thanks a lot for your remarks and taking the time to comment in depth, it really helps me rethink and reevaluate what I’m writing about.

About me

Hi there! I'm Bas, a test automation trainer and consultant always looking for more intelligent ways to use tools to support testing. I'm sharing my experiences and thoughts here, so you can benefit from them too!

Agenda

I will be facilitating a full day workshop titled ‘Investigating the context – How to design an effective automation strategy’. More information about the event can be found here.

Test Automation Days
June 19-20, 2019 (Utrecht, NL)

I will be facilitating a half day workshop titled ‘Patterns and principles over tools and tricks:
applying the pillars of object oriented programming to your test automation code’. More information about the event can be found here.

I’ll deliver this course in public in collaboration with Black Koi Consulting. See here for more information and registration.

Agile & Automation Days
October 28-29, 2019 (Gdańsk, PL)

I have the honour of delivering a keynote titled ‘Test automation: Put on the brakes so you can go fast’ at this conference. Next to that, I will also be delivering a full day tutorial on API test automation and service virtualization.