The Granularity of Tests in TDD

Heaton Cai
4 min readAug 8, 2021

--

Wearing a testing hat when writing tests is one of the key practices in TDD. We should think like a tester that only cares about the behaviours of the system and the business rules without thinking about the implementation details. It is the basis for the third step of TDD (Refactoring). The code would be very hard to change if tests are coupled to the implementations.

However, I still see many developers writing tests from the implementation details such as CRUD with database or a controller with stubs. They explain it as a bottom-up approach, which is harmful to practising TDD. In this article, I’m going to explain where the bottom in TDD really is by some simple examples.

The example: Change passwords

The requirement is to allow users to change their passwords.

A Test Case

As a tester, I’ll expect a page with a form that includes 3 inputs (old password, new password, verify new password) and a submit button. After I type my old password and the new passwords then click the submit button, I’ll expect a confirmation page and to be able to login with the new password instead of the old one.

The application is implemented with a microservices style like this:

system diagram

As a tester, I can write tests in the following ways:

  • From UI level (end to end)

This normally refers to a top-down approach in TDD which the process starts from a failed test of the top level. This kind of test is normally called the acceptance test.

  • From Routes/API level (Integration)

This also refers to the top-down approach if you are in a backend team.

  • From the Domain Interface level inside identity service (Unit)

Notice that the new password consistency check is in the controller because it is about user experience, not part of the business rules.

If this is your first test, then it is a bottom-up approach.

Any level lower than above is considered as details

As a tester, I don’t care how the password is stored. So I won’t write a test like this:

Comparing the value in the database is considered as the implementation details and it is below the bottom line of the tests in TDD.

Non-functional Tests

Non-functional tests should be written separately from behaviour-oriented tests. For example, a test could be written for the encryption of the password like this:

Apply Test Pyramid

The test pyramid describes how the distribution of tests looks like with a good cost-benefit ratio. We should follow it if we want the tests to be maintainable, so we should write tests into the lower level as much as possible.

In the top-down approach:

  • A very simple end-to-end test drives the skeleton of the application (basic UI and a simple service)
  • An API test drives the skeleton of the backend service
  • Many unit tests drive the implementation of more domain rules

In the bottom-up approach:

  • Some unit tests to drive domain rules
  • An API test exposes the rules to a service API
  • A couple of frontend unit tests drive the user experience
  • An end-to-end test drives the integration of the existing components

TDD makes sure 100% business coverage (code coverage is also 100%, but it’s not important), the test pyramid minimises the cost of tests. Put them together, that’s the secret to keep our applications easy to be changed.

Summary

Writing tests as a tester is a very important skill to do TDD well. We need to make sure that there is no test below the bottom line, no test is against the implementation detail. Thus, we can enjoy the flexibility to improve the code by refactorings.

References:

Appendix

Another example for beginners.

Kata — Conway’s Game of Life

As a tester, there are only 2 proper levels to write tests with:

  • from UI (Console) which requires test doubles (end to end)

This is the top-level test that is based on the user interface.

  • From domain interface (Unit)

This is a bottom-level test.

Tests below the level above are too detailed

We should not write this test since it makes the code change become hard.

--

--

Heaton Cai

16 years in the IT industry, passionate to share what I have learnt. All thoughts and opinions are original and maybe new. Free to share with the original link.