What is test driven development ?

Test Driven Development (acronym TDD) is a coding methodology that consists of starting the development of a feature by writing a unit test for it, and only in a second stage actually coding its implementation. This is the reverse of a more standard approach where unit tests are redacted once the development of the feature is considered completed. The goal of this approach is to obtain cleaner interfaces, simpler design patterns and therefore modularised, flexible and extensible code. In this approach you transform your features' specifications into output expectations and progressively add to your code to meet the requirements set by the test. Instead of thinking about your feature abstractly, you think about your features' specifications and how it will be used by the end user or consumed by other parts of your application. It’s a “test first” approach which forces developers to be more rigorous and correct their mistakes instantly and consequently raise the overall code quality.

Test Driven Development is built around a 3 step process

1. Write a test (not THE test, careful. It’s not the full test yet)

Ensure that the test is failing, because the functionality is not yet implemented

2. Write just the code necessary to make the test pass

Ensure that the test passes

3. Refactor

Repeat, adding new tests that complete the feature specification

You will iterate those 3 steps for any specification until your code is ready.

Tests are not the goal of TDD, but the means. The real objective is simpler and improved design patterns and high code quality.

What are the advantages?

This methodology forces you to plan your code in a very modularised way because tests for non-modular code are much harder to invent.

Every testable part of code needs to have a clear input, a clear output and a clear set of specifications of what it is supposed to do.

In other words, approaching one small chunk of code at a time means that you keep things simple even if your overall features' complexity is high. Simple means clearer interfaces and more robust code.

With TDD you have better code, not because of intense design thinking but because you handle your complex feature as the interaction of many small interconnected modules.

This test-ahead-of-code methodology leads to code quality through better design patterns. You will not miss on mistakes or edge cases issues very early on since all the possible scenarios will be taken into account in the test. We consistently observe better coverage and less time spent on debugging through this approach. This also ensures you don't skip testing any function. With TDD you stop “writing a function and checking if it passes the test” but instead you write the test and you know what kind of test your function is supposed to pass. For the lovers of a high coverage score, of course TDD is also a fantastic way to keep your coverage high.

Test Driven Development will help raise the overall quality of your code but it will also help your coding practice: working on one small chunk at a time will increase your capacity to focus and not miss out on anything. Developers can focus on making sure to meet each acceptance criteria and proceed towards focusing on refactoring. The refactoring will consequently be safer since you know test cases are already successful. You systematically get simpler code but well-tested code. The Test Driven Development approach also helps to have a comprehensive approach to bug fixing: instead of just trying to remove the bug you will have to understand the underlying reason for it.

On a higher level this methodology brings better code design and most of the time helps developers to be more thorough on building documentation. On the financial side, even though it’s more resource consuming, it arguably ultimately saves developers time by reducing the time they will spend fixing bugs.

 

Why develop using Test Driven Development?

the tdd lifecycle
The TDD lifecyclew

A goal-oriented approach

Sure, in “TDD”, the first letter stands for “Test”. However, when you create your test, you are writing the expected outcome of your code. You are essentially writing specs and the code is just a means to reach these specs. 

The goal is that your tests pass.

The test architecture is the action plan.

The mean is your code.

Yes, it is less “attractive” or “fun” than jumping straight in and starting to code, because it forces you to think before you act. But in the end, the cleanest way to reach a goal is to formalize it, write a plan and then implement it. This applies to code efficiency and TDD enables this discipline.

Good architecture

Good architecture is very often overlooked when coding, and this causes many unwanted side effects overtime:

  • Slow releases
  • Bugs
  • Poor quality VS innovation ratio
  • Technical debt
  • Developer frustration
  • Spaghetti code base

These are the very same problems that come with untested code bases. TDD forces you to think about your goals, and consequently, you have to think about the correct architecture to optimize your tests. Your brain will be in “design mode” and naturally prompt you to build strong architecture that enables clean tests that don’t involve lots of mock objects and other unattractive syntax.

Code quality

Of course, one consequence of TDD is that all of your code is tested. Thus, you have 100% code coverage and your code is protected from any potential regressions.

Other benefits that I won’t dig into:

  • Less regression testing
  • Documentation
  • Scalability 

The limits of Test Driven Development

On paper, and also in many cases in practice, TDD seems to be one of the best available approaches to developing software. In particular, it enables you to shift left and reduce all costs associated with code quality.

However, the majority of the market does not match the requirements for ideal TDD conditions in most cases:

Legacy code: TDD does not apply to legacy code because the code was already written.

High initial cost: TDD needs a “no rush” environment. The pressure of quick time-to-market contradicts this condition. It is somewhat of a luxury and pretty rare to have the time available to think thoroughly about the test and architecture before beginning to code. While not ideal, this is the reality of TDD.

Unperfect code robustness: TDD certainly helps reduce bugs early in the development process, but unfortunately, there are always bugs that are missed by the developer. TDD does not guarantee perfect robustness.

Incomplete test cases: In any top down approach, some axes can be forgotten. This is the same for test cases, some values for happy paths can be forgotten by the developer, some edge cases might flight under their radar. TDD does not protect you from missing test scenarios

 

If it is so good why isn't everyone using it?

More and more developers are turning toward Test Driven Development. Some might argue that TDD has a fixed cost of spending time writing your tests ahead instead of actual coding. This time consumption could be fatal for developers with a limited amount of time on their hands such as startup developers who need to code prototypes fast and have an MVP ready before running out of resources.

Test Driven Development is also not chosen over a more classic approach because of the time pressure and lack of understanding of the advantages of TDD from managers or clients or just because it is not prominent in developers’ training curriculum.

On the other hand, bigger companies usually have those resources and since quality of code is of the utmost importance in their coding standards they turn towards TDD.

Test in the making at Ponicode

Is Test Driven Development a shift left friendly methodology? 

Test Driven Development fosters the creation of a high number of high quality unit tests, it consequently aligns itself perfectly with the logic behind shift left and provides all the benefits from shift left testing. By catching bugs and flaws very early on and reducing the feedback loop when new bugs aise you make sure to enhance the quality of the software development life cycle. Shift left testing and test driven development are not mutually exclusive, you can shift left without TDD but practicing TDD does make you a shift left practitioner. 

 

Are test generation tools in the way of TDD?

You can think at first that accelerating or automating test generation encourages a lazy approach towards unit testing by relieving a developer from the mental effort to design tests. But it does not have to be this way, accelerating your effort on unit test writing thanks to tools can enable you to refocus your energy on thinking about your test scenarios, on figuring out the most problematic outputs or spend more time to think of edge-case inputs to test your function with. These tools are usually there to help you ensure that tests are made and that coverage is high. 

What’s the DevEx team approach to TDD at CircleCI?

We have not yet been developing TDD centric tools and developers using the Test Driven Development methodology are not (yet) getting the full benefits of our technology. We try to remain agnostic of any methodology and design time saving tools for all coders no matter which coding methodology they choose thanks to quick automated unit test creation. Our target is increased confidence: we want to bring developers to get higher confidence in the robustness of their code and the exhaustivity of their tests than if they didn’t use any tools.

In our first extension (i.e Ponicode) we were providing some TDD friendly options such as building unit test tabs prior to function writing so you can manually enter your inputs and outputs before getting started with coding and check them later down the road (possible as long as the function prototype is defined). 

Today, we join our forces with TDD promoters in saying that unit tests are key to beautiful code and we want to push the unit test practice as absolutely unavoidable. We are unit tests lovers, we believe in how crucial of a step it is for developers and we want to make it easier for others to love unit tests too.

Do you want to get started with Test Driven Development? We spotted this resource, as well as this one, where you can get step by step examples to get familiar with it.

Do you want to get started with Ponicode? We won’t discourage you. You can get started here.

Also on the hub

Ready to write beautiful code?

Smart and simple unit testing assistant. Now available for free.

Try it now

Solutions for JS, TS, Java and Python

Lines Footer
Flexing Unicorn by Ponicode