Yesterday, I read an article about how to unleash the power of Test-driven Development*. I liked most of it so much that I would like to share and discuss some of its main thoughts. What I liked most about it were the concepts of how tests can be written in a way that is easy to read and understand. To assure long-term quality of tests it’s important to comply with some conventions regarding partitioning, naming and structure. I totally agree with the authors that the Cucumber project with the Gherkin language and all its tools is a good reference for easy-to-understand test design. Especially the natural language of the test cases facilitates comprehension for the readers who can then dive into step definitions and the actual test code. Even if you’re not willing to use Cucumber / Gherkin in your test solution you can benefit from its concepts. If you make use of its three phases Given / When / Then in existing test cases, even unit tests get a better structure and readability. Additionally, the authors point out the following requirements for clarity in tests:

  1. Tests should be short. Each section should only contain few lines of test code.
  2. Each test should only check one scenario of a feature.
  3. Tests should be concise, only showing the relevant aspects and hiding insignificant details.

Especially to reach the goal of the third point the authors recommend to use builder classes and helper methods from a small test DSL. All these recommendations are finally used in the following example of a readable test case:

public class OrderTest extends TestBase {
    @Test
    @TestedFeature(OrderPlacement)
    public void test_order_single_product_in_stock() {
        // Given:
        User user = database().persist(a($User()));
        Product product = database().persist(a($Product));
        database().persist(a($StockItem()
                .withProduct(product)
                .withAmount(1)
        ));
        // When:
        httpClient().authenticate(user).post(an($Order()
                .withProduct(product)
                .withAmount(1)
        ));
        // Then:
        assertThat(database().find(Order.class)).hasSize(1);
    }
}

Having good readability like in this example results in faster understanding of what is actually tested and better maintainability. More tests should be like this one!

* original article: “Interne Prüfung. Wie Test-driven Development seine Stärken entfaltet.” by Michael Karneim and Oliver Kraeft in magazine “iX”, Vol. 9 / 2016, pages 84-88.