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:

assertEquals(4, calculator.add(2,2));


assertEquals(0, mammals.getAnimalsByType("fish").size());

When converted to AssertJ assertions, these look like:




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:

public class LoginPage {
	private WebDriver driver;
	private WebElement txtFieldUsername;
	private WebElement txtFieldPassword;
	private WebElement btnLogin;
	public LoginPage(WebDriver driver) {
		this.driver = driver;
		if(!driver.getTitle().equals("Login Page")) {
		PageFactory.initElements(driver, this);
	public LoginPage setUsername(String username) {
		return this;
	public LoginPage setPassword(String password) {
		return this;
	public HomePage clickLoginButton() {;
		return new HomePage(driver);

Note that this Page Object also uses the PageFactory pattern, which improves Page Object code readability as well. This pattern is beyond the scope of this blog post, though.

Assuming we also have a HomePage object with a method that returns a boolean indicating we are indeed on the home page, we can write a simple login test that looks like this:

public void loginTest() {
	new LoginPage(driver)
	Assert.assertTrue(new HomePage(driver).isAt(), "Home page has been loaded successfully after login action");

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:

public void testMD5() {
		parameters("text", "test").
		body("original", equalTo("test"));

For other tools, you may need to apply this implicitly:

public void testCalculatorAddition() {
	Calculator calculator = new Calculator();
	assertEquals(calculator.getResult(), 2);		

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.

8 thoughts on “Three practices for creating readable test code

  1. Pingback: Java Web Weekly, Issue 116 | Baeldung

  2. Pingback: Weekly Links #6 | Useful Links For Developers

  3. Pingback: Some kick ass blog posts from last week #11 - Mr.Slavchev()

  4. Pingback: Java Testing Weekly 12 / 2016

  5. “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.

  6. Pingback: Java Web Weekly, Issue 117 | Baeldung

Leave a Reply

Your email address will not be published. Required fields are marked *