The Magic Behind Test-Driven Development and How to Do It Right

If you are familiar with agile, you might as well have heard of extreme programming that takes a bunch of great development practices to an extreme. This doesn’t mean anything scary – instead, extreme programming is about making the most out of proven and effective practices – and TDD is one of those.

Test-driven development, known as TDD, is considered a highly effective approach to software engineering. Yet, not all software companies use it since TDD requirements are not so easy to follow. So what is so extreme about TDD and why do some companies neglect it despite its obvious advantages? Let’s have a closer look.

The Magic Behind Test-Driven Development and How to Do It Right

What is TDD and why it’s not 100% about testing?

Test-driven development is a methodology that implies writing unit tests before writing production code. In other words, first, you write tests for a non-existing code, then you write the needed code, and then the test passes. How does this approach fit into XP (extreme programming) concept? Simple: let’s take code testing to an extreme and write tests before there is even any code written. A shoutout to Kent Beck here – the father of extreme programming and one of the 17 original signatories of the Agile Manifesto.

Now, the next question is how does TDD fit into the agile concept? The answer is actually quite simple. One of the main features of agile is the need for regular feedback since project requirements may change throughout the development process and developers need to adapt to the changes. Regular feedbacks help maintain transparency and quickly identify the source of an issue before the code goes anywhere further than the developer’s laptop.  And since test-driven development promotes constant testing, this approach provides developers with regular feedback on working and non-working parts of an application. In this way, the TDD approach prevents non-functioning parts of the code to go into production because failed tests block the deployment process. 

It is worth noting though that TDD may slow down the development process due to the need for constant testing. And if your project has many changing requirements, this will also contribute to a slower development process. 

How does TDD work? Uncle Bob’s rules

We’ve already spoken about the TDD principle of work for a bit – now let’s look at the way test-driven development is performed in more detail.

The TDD process starts with the API design of the future code and the three main phases in TDD are:

  • Create unit tests: a developer writes a test for a non-existent code for a new functionality. When the test is run, it will fail since there is no code yet. It is important to note that the unit test will be performed with other tests to ensure that all parts of the code function as intended.
  • Write code: a developer writes code for the non-existent functionality that the test is supposed to cover.
  • Refactor: the developer runs the test again (it must pass) and if needed, makes any adjustments to the code to improve its performance without affecting its external behavior (well-written green tests ensure that).

You can compare the process to the red/green testing where no code is written until there is a test that would fail (red). Hence, the TDD process can be described as Red, Green, Refactor. 

It’s not that simple though. Remember we said how TDD is known for its efficiency? A high level of it is supposed to be achieved by following the three TDD rules defined by Robert C. Martin in his book “The Clean Coder”:

  • A developer is not allowed to write any production code unless it is needed to make a failing test pass.
  • A developer is not allowed to write any more of a unit test than is enough to fail, and compilation errors are failures.
  • A developer is not allowed to write any more production code than is enough to pass the one failing test.

These rules are supposed to help developers avoid writing excessive and duplicate code and overall make the coding process easier. However, some professionals state that rule #2 could use a bit of improvement since the treatment of compilation errors as failures can mislead you in terms of understanding code quality. So if we rework Uncle Bob’s rules a bit, we’ll get:

  • Red: work on test code only. As well, only the test you work on should fail – others should be green.
  • Green: work only on the production code that will make the test pass. If the test fails after you wrote the code, have a look at your implementation. If other tests fail, you need to go back.
  • Refactor: refactor production code only and do not mess with the functional changes.

The benefits of test-driven development

Okay, so what are the biggest and most important advantages of implementing a test-driven development approach in your project? We’ve listed the main ones though there are actually many more!

You only write the needed code

Since TDD rules imply creating only the code needed to make a failing test pass without touching other parts of the code, you won’t write any production code when all tests pass. This helps eliminate duplicate code and contributes to keeping the code clean and simple since the simplest code will be enough to make a test pass.

Great test coverage from the start

Since there is a test for every feature, needless to say, TDD provides a pretty great test coverage. This, in turn, contributes to easier refactoring since the chances of a new feature breaking everything are pretty low.

Modular software design

The TDD approach promotes focusing on one feature at a time and developers do not move to the next feature until the first one works perfectly. This leads to code becoming modular and hence, contributes to easier bug discovery and easier code reuse. A clean modular code results in a better architecture and this impacts the overall app’s performance. 

Easy and smooth refactoring

Developers may fear refactoring because it might bring unexpected issues or break the existing code. But with TDD, refactoring is smooth and manageable since every feature is tested before being added. Hence, the chances of refactoring leading to an error become much lower than with a traditional development approach.

Other important benefits of TDD include:

  • Detailed specifications and well-documented code;
  • Clean interface and solid code;
  • Less time spent on debugging;
  • Increased productivity for developers;
  • The clarity in terms of understanding the code and issue sources;
  • Increased confidence for developers since refactoring is stress-free.

Most common TDD mistakes and considerations to keep in mind

As you can see, test-driven development promotes code clarity and efficiency of the development process – but this approach is also highly demanding. If developers lack certain skills, it will be easy to mess up with TDD and nobody wants that. So we will now have a look at the most common TDD mistakes and considerations to be aware of before deciding to go full TDD on your project.

Steep learning curve

Test-driven development requires developers to understand what they are doing and it also demands them to know how to create clean code and refactor it properly. When working by the TDD approach, developers really need to know the main development principles and design patterns – otherwise, they won’t be able to produce concise and clean code. The “hit or miss” coding just won’t work here.

Slow tests

When TDDing, you’ll want your test suits to be completed within several minutes (preferably, seconds). So one of the biggest mistakes that developers make is writing slow tests that take too much time. Another mistake here is using unit tests to do integration testing – since integration tests are slow by nature, you’ll need to put them in a separate test suite.

Infrequent testing and refactoring

Another big mistake that some developers tend to make is not testing frequently and not refactoring all the time. As a result, they do not receive early feedback (that is provided by frequent testing) and thus might let the code slip into looseness.

Summing up

Is test-driven development a good practice? Without a doubt. Is it a silver bullet that will instantly turn you into a programming demiurge? No, because you’ll need to know what you are doing.

TDD is amazing but on the condition that you have enough time and will to adopt this approach and follow it. And while TDD may not be for all, it’s definitely a practice worth paying attention to.

Want to stay updated on the latest tech news?

Sign up for our monthly blog newsletter in the form below.

Softteco Logo Footer