The New Anti-TDD Movement

Alexandre PENOMBRE
4 min readJul 2, 2024

--

Many developers who have recently started using TypeScript have felt empowered by its real-time type-checking features directly in the IDE. Indeed, this development approach, as opposed to JavaScript, changes a lot and already reduces many potential errors before execution. I have nothing to say against it; I am totally convinced that there is a radical change between TS and JS with a significant improvement in the ability to anticipate bugs.

However, this movement goes very far, even to the point of renouncing TDD methods and deeming them unnecessary based solely on TS verifications. This movement has been reinforced by the acceleration of startup/POC type projects. The aim is to do quick and dirty work, to move fast and release something, prioritizing profitability over reliability. However, I believe there is a problem with this way of thinking. Reliability should never be opposed to profitability. The best applications, and those that last over time, have often succeeded in combining both: being reliable and profitable, thanks to a subtle balance between testing and feature delivery.

The ideal is to maintain maximum performance without compromising too much on reliability. Between us, at both extremes, we witness absurd viewpoints, between those who want 100% coverage and those who absolutely do not want to do tests. I can guarantee you that no one is right in these extremes. I have seen too many projects fail miserably due to problems arising from these viewpoints:

  • the 100% coverage that hardly releases any features,
  • the no TDD which is a bug sieve.

And to quote Clean Code again, there are too many companies that have neglected tests for a very long time until the day they started bug-fixing but lost tens of thousands of users per day due to bugs. In those moments, it is probably already too late to say: “Oh, but what if we made reliable code”. Congratulations, you have just managed to sink your company!

The Problem of Untested Projects

I can assure you that a project without any tests is hell on earth, and I have already experienced it firsthand. 🥵

When you work in a team, each commit is likely to break a behavior and create a bug, as developers often push their modifications without considering an initially intended or expected behavior but rather a spontaneous need.

The absence of tests does not allow intercepting regressions at this moment.

Similarly, on a large-scale project, the absence of tests provides no guideline on what is expected as a pathway to a feature. Developers will tend to create a lot of libraries and functions without knowing if they will actually use them. Hello, time wastage!

The risk is to maintain a debt so heavy that it would take weeks or even months to go back over it. Many projects have not overcome this ordeal because it is a stressful and financially demanding moment with a daily risk of client churn (churn: the client stops using your services).

Reminding you that all this could have been avoided with organization and rigor. Doing TDD is also showing responsibility towards the company and the clients.

Companies such as Knight Capital Group have gone bankrupt due to bugs that generated erroneous trades over a period of 45 minutes, resulting in a loss of 440 million dollars, an incident that cost 75% of the company’s capital. In 45 minutes!!! 🥵

Finding the Balance in Implementing TDD

To do TDD effectively, it is not enough to test everything and have 100% coverage and an inertia worthy of an ocean liner.

Testing also means imposing an expected operation for a component. For example, an additional and mandatory argument in a function that initially did not expect it is potentially a regression in other parts of the code.

Passing the tests before being able to push your code often means: ensuring that what you send does not break an intended behavior.

Similarly, TDD helps in development when building a complex feature that relies on a sequence of functions that are still non-existent. It will provide a guideline on the functions to be delivered and will anticipate the expected behavior of each function, materializing the specification of these functions.

If we remove this part, especially in medium to large-sized projects, it can be difficult to know where an implementation will lead because teams have no direction, TDD could have played a beacon role in this fog.

Knowing that the further you advance in your project, the clearer and more precise the objective becomes, you may have to go back over the tests to give them a new direction, but at least the direction exists, it is set, and the framework is given.

Conclusion after Several Years of TDD

My recommendations are as follows:

  • Implement TDD on the key features of your application.
  • Pay particular attention to the most critical paths: payment, manipulation of client data, document manipulation, exposure of confidential data…
  • Do not go too far by doing TDD on external libraries used (it is up to the libraries to test their code, and it is your responsibility to make an informed choice when selecting your dependencies); however, testing the combination of several libraries in TDD can be done if you think you reach a level of complexity requiring verification.

Since I have been working with TDD, I must admit that I am much more confident in what I deliver and I sleep soundly. This feeling is priceless as a developer, and I can only recommend this methodology. Unless you have absolutely no professional conscience, I don’t know how those who say they can do without it manage.

--

--

Alexandre PENOMBRE

Tech Enabler, Typescript Expert Freelance @TheFork By TripAdvisor #Typescript #React #WorkflowAutomation