TDD in the real world: when to use it (and when not to)?

Rafael Buzzi de Andrade • November 28, 2024

Test-Driven Development (TDD) is one of the most well-known modern philosophies for achieving a high level of excellence in software development. Like any solid philosophy, however, TDD is sometimes misunderstood and misapplied, making it challenging to implement in certain environments.


The discussion about the importance of testing in systems development is nearly as old as programming itself. In the second chapter of The Mythical Man-Month, Frederick P. Brooks Jr. suggested, back in 1975, that half of the time spent on a task should be dedicated to testing. When the testing phase isn’t planned, developers often spend even more time on it unintentionally.


In the late 1990s, Kent Beck and others created the concept shown below:

This simple image is an effective tool that helps us better understand TDD. However, this simplicity can lead to overcomplications that make TDD impractical in day-to-day work, diverging from its original purpose. So many rules and behaviors are added to make it “true TDD” that it becomes unappealing to apply.


The very concept that your code should fail to compile before starting implementation doesn’t align with how some people think about problem-solving. Additionally, there are times when it’s simply not possible to write the test before the code. Both David Heinemeier Hansson (creator of Ruby on Rails) and Kent Beck (creator of TDD) share this perspective. Their thoughts can be found in this keynote.

If there are situations where TDD is impossible to use, when is it truly useful?


When to apply TDD?


Most TDD tutorials cover testing calculators, passwords, and other simple scenarios. Looking at software layers in modern applications, these TDD examples are often at the business layer and don’t account for more complex, real-world challenges.


Though not widely applicable in the usual workday, these simple cases can still provide clues about TDD. Their simplicity helps convey the main concept behind TDD quickly. That’s the goal of a tutorial. With a simple scenario, it’s easier to see all possible results of a piece of code. This lets us write test cases that cover all scenarios, including positive, negative, and edge cases.


And here lies our answer: to apply TDD, you only need to know how your code should behave.


In many cases, not all criteria are clear at the start. In fact, most projects are like this. Even in these situations, TDD can be implemented incrementally. The TDD approach itself allows for rewriting tests as many times as needed. Create the test based on what you know and update it as your understanding of the project evolves.


When TDD is not usable


If you’re receiving tasks with unclear acceptance criteria, it’s practically impossible to apply TDD.


Unlike community tutorials, a developer’s day-to-day involves delivering complete and complex services, not just business rules. If we only apply TDD at the business layer, the service has typically already gone through significant setup, with all its structures and protocols running. And what about tests for those parts? We need to think about tests before defining the layers of what we’re developing. It may feel more natural to implement TDD if we start even before opening the IDE (Integrated Development Environment).

David Farley, author of Continuous Delivery, once said: “It’s not about ‘Testing.’ It’s about ‘Specification.’ It’s not about ‘Testing Code.’ It’s about ‘Confirming Behavior.'”


When to use TDD: a practical example


It would be contradictory to discuss practical applications without giving at least one suggestion. So, consider using Postman (as we did for this client) or a similar tool as an MVP for TDD.


In the “Tests” tab, you can create acceptance criteria for your call to be considered successful. Set up the calls with the formats and fields you expect to receive. The test will fail because the project doesn’t even exist yet. Build your app and write a fixed object return. Your test passed. Now you can write your code, connect it to the database, make it return an actual object, and then write your unit tests. Or you could write the unit tests first, and then write the rest of the code and database integration—it depends on how you prefer to work.


If “real TDD” means writing tests before any code, we’ve just considered a scenario where we write tests even before opening the IDE. In cases where different people handle the backend and frontend, the frontend developer can write these tests and hand them over to the backend developer. This reduces a lot of rework that often occurs when the back-end and front-end meet.


Better still, with the right training, the product team could prepare the initial tests before the task even reaches the development team (whether back-end or front-end).



In any case, it’s important to understand that clear acceptance criteria are essential for well-applied TDD.


Rafael Buzzi de Andrade
Software Engineer


LET'S CONNECT

Ready to unlock your team's potential?

e-Core

We combine global expertise with emerging technologies to help companies like yours create innovative digital products, modernize technology platforms, and improve efficiency in digital operations.


You may also be interested in:

Por e-Core 22 de julho de 2025
A strategic approach to modernizing code At e-Core, we often partner with organizations whose software technically “works” in production, but just barely. Over time, shifting teams, competing priorities, and tight deadlines lead to codebases that are fragile, expensive to maintain, and risky to enhance. In this context, software refactoring becomes more than a technical task. It’s a business strategy that preserves continuity while unlocking future growth. Defining refactoring: Evolution without disruption Software refactoring is the disciplined restructuring of existing code, improving readability, modularity, and performance, without altering its external behavior. Unlike a full rewrite, refactoring delivers incremental value by: Accelerating feature delivery through cleaner, more modular code. Reducing operational risk by eliminating brittleness and regressions. Lowering total cost of ownership by making enhancements less labor-intensive. Why refactoring matters for business  Healthy codebases have a direct business impact: Faster Time-to-Market: Modular components support parallel development and faster releases. Greater resilience: Decoupled services isolate failures and simplify maintenance. Easier onboarding: Clear architecture and design patterns help new developers ramp up quickly. Sustainable cost savings: Less firefighting, fewer regressions, and lower maintenance overhead. What may look like a simple “cleanup” is often the first step toward digital reinvention. Refactoring techniques In enterprise environments built on Java, C#, or Python, we apply proven object-oriented refactoring techniques to increase cohesion and extensibility: Class decoupling: Split monolithic classes into focused, single-responsibility components. SOLID principles: Apply interface segregation and dependency inversion to stabilize architecture. Composition over inheritance: Build flexible, interchangeable structures. Testability enhancements : Isolate side effects and inject dependencies for better test coverage. These techniques form the foundation of our incremental software refactoring roadmaps. Beyond OO: Choosing the right tools for each paradigm Modern languages blend programming paradigms. We help clients apply the right tools to the right problems: Functional patterns in Python to create concise, side-effect-free data pipelines. Kotlin/Scala hybrids that combine OO structure with expressive functional constructs. C# LINQ and Async for declarative data queries and scalable concurrency. This multi-paradigm approach ensures that systems remain robust, flexible, and expressive. A refactoring story: From debt to differentiation Case Study: Regional logistics provider
Por e-Core 16 de julho de 2025
Background Ricksoft is known for its popular work and project management apps on the Atlassian Marketplace, including WBS Gantt-Chart for Jira and Excel-like Bulk Issue Editor for Jira. Originating in Japan, the company has grown to serve over 8,000 customers worldwide through nine apps. Their tools are trusted by some of the world’s most innovative companies to boost productivity and manage complex work. By 2019, Ricksoft was seeing growing demand from customers in the Americas and Europe, and needed to scale its support operation beyond Japan. To serve new markets effectively, they had to provide fast, high-quality service in English and across time zones, while maintaining the responsiveness and care that defined their brand. That’s when they turned to e-Core. Our approach We designed a support solution based on three key principles: timezone alignment, consistent high-quality service, and cultural alignment . To get things right from the start, our analysts flew to Japan for in-depth training. They didn’t just learn the products; they learned how Ricksoft works , communicates, and supports customers. Once training wrapped, we built the support operation around Ricksoft’s priorities: timely responses, consistency, and a thoughtful, human tone. We created detailed documentation and a clear process for hiring and onboarding, ensuring every new analyst could step into the role with confidence and alignment. We also introduced monthly updates to the knowledge base and took responsibility for keeping existing articles relevant. That work paid off: most tickets are now resolved in just two to three exchanges , and self-service performance has improved across the board. Today, Ricksoft holds a satisfaction rate of 89 percent and a CSAT of 4.63 out of 5 , well above industry averages. As new analysts joined over the years and support expanded to more products, the service quality remained consistent. “We place great confidence in e-Core’s hiring decisions,” says Alessandro Cristiano, Support Manager at Ricksoft. “They understand how we work, and their mission, values, and culture attract good talent. We had five different generations of agents in seven years, and the work was consistent all the time.” Building long-term value through support. To make support even more impactful, we set up a feedback loop between support and product. Recurring issues and feature requests are flagged and shared with product managers, turning support into a valuable channel to inform product strategy. Tone and empathy matter, too. Ricksoft’s brand is rooted in respect, clarity, and thoughtful communication. We greet returning customers by name, tailor our closings, and have consistently met their SLA targets—with 99% first-response compliance within 12 hours or less. “What is special about e-Core is that they listen first,” Cristiano says. “They don’t try to mold things just for efficiency if it doesn’t work for you. First, they absorb your culture, and then transform it.” To strengthen Ricksoft’s presence in the Atlassian Marketplace , we introduced a post-ticket review request process. That simple step led to more customer reviews, better app ratings, and increased visibility. “We’re now at the top search results, which helps increase our app installs, and ultimately our revenue,” says Cristiano. We also monitor Ricksoft-related activity in the Atlassian Community. When their apps are mentioned, our team responds quickly and accurately, helping Ricksoft remain visible, helpful, and credible in the ecosystem .
Por e-Core 16 de julho de 2025
A successful cloud migration doesn’t start with tools, it starts with the right plan . Download this guide to discover a structured, strategic approach to migrating and modernizing workloads on AWS . Whether you’re just starting your cloud journey or looking to optimize an existing environment, this whitepaper gives you the clarity and framework to do it right. What you’ll learn: A 3-phase cloud assessment and planning framework AWS tools that support discovery, migration, and modernization How to reduce cloud spend, improve security, and scale with confidence Real-world planning strategies, including containerization, serverless, and data modernization