An Introduction to Test-driven Development in Agile
If you’ve ever worked with Agile methodologies, you know that testing is a huge part of the software development process. It’s never a choice between testing or not testing, but whether to do it before or after.
Following a regular Agile lifecycle, testing usually happens at the end of each sprint, but with test-driven development, a failing test is what triggers the cycle to begin.
When code is complex and fragile, one single change can mess up a complete functionality. Agile test-driven development (TDD) is a way of guaranteeing code maintains the intention that it was built for and makes it cleaner to edit, and scale long-term.
In this guide, we’ll share all the basics around test-driven development: what it is, what it’s used for, and its pros and cons.
Table of contents
Ready to build your own custom software with a team that cares about you and your processes? We’re not code monkeys, we care about you.
What is test-driven development in Agile?
Test-driven development (TDD) is an Agile technical practice that’s configured at the beginning of the Agile software development lifecycle and begins with a test instead of writing lines of code. TDD is a test-first approach that guarantees the code developers write is valid.
TDD complements other techniques where the codebase is assessed for tidiness or efficiency. It allows development teams to express their intent in the form of unit tests (testing the smallest parts of software) to validate the functionality of the code.
Doing TDD on every single project may be a bit of an overkill, especially when you need to deliver software fast, when you do choose to incorporate it in your workflows, your efforts always pay off long-term.
How does TDD work?
The TDD cycle goes the following way:
Write a unit test for a specific functionality or intention
Run the test and expect it to fail because you haven’t written code for that function/intention (red)
Write only the needed code to meet the functionality, test it, and expect it to pass (green)
Refactor code to make it simpler and easier to maintain (refactoring)
Repeat until you finish all features or software functions.
Who should use TDD?
No one can deny the added value of doing test-driven development software but with time-pressing projects, it seems like there’s rarely enough time to do it. In fact, we believe that everyone should be using it for their software development, by applying different strategies to make the most out of it.
For a Prototype or Proof-of-Concept, you might avoid writing tests.
For MVPs that need to hit the market fast to validate product-market fit, you might focus on applying TDD in the critical and core components of your app.
If your app has achieved product-market fit and its scaling, you might want to consider increasing your unit-tests and start applying more TDD.
If you’re rebuilding an enterprise application from scratch, that would be a good scenario to target a good TDD coverage.
TDD vs behavior-driven development (BDD): What’s the difference?
Behavior-driven development uses TDD as a base but turns into a pretty similar, yet different approach to testing in software development.
From a technical perspective, the biggest difference between BDD and TDD is how developers write the test code. In BDD, programmers test the code to assert that the system behavior is in fact the experience the users expect when using the app. With TDD they test small pieces of code to see if the execution yields the correct result.
In test-driven development, the development cycle begins with testing. In behavior-driven development, it begins with a conversation about how this software is supposed to work and how people are going to use it.
The steps involved in behavior-driven development are:
Identify the intended behavior or business feature
List the scenarios for that feature or behavior
Define the steps for each of those scenarios
Run a test on that feature and expect it to fail
Write only the needed code to meet the expected behavior, test it, and expect it to pass
Refactor code to make it simpler and more scalable
Run a second test and expect it to pass
Create and save test reports.
Some key differences between TDD and BDD are:
What are the frameworks for test-driven development?
Every programming language has several unit testing frameworks which can be used to apply TDD. These are the most common ones to use when doing TDD:
Mocha, Jest and Ava for JavaScript
PyUnit and DocTest for Python
Junit and TestNG for Java
Rspec for Ruby
PHPUnit for PHP
csUnit and NUnit for .NET projects
Test-driven development: The pros and cons
TDD has some powerful advantages and disadvantages. While it’s a great way of ensuring code functionality, it may lack flexibility and may delay deliveries. Let’s review them in detail.
What are the benefits of TDD?
Code modularity. TDD makes the software modular by having developers concentrate on one feature at a time; they can’t continue until the unit test passes. This makes the code easier to scale, debug and reuse in different scenarios. Also, it increases the quality of the software architecture.
Refactor culture. Refactoring is one of the three main steps in test-driven development. It makes the code cleaner, focused on one clear goal, and optimized. Making TDD a regular practice can build a culture around refactoring which will inevitably lead to your team members constantly delivering high-quality and scalable code.
Better documentation. Each unit test acts as code documentation because it explains how the new code is supposed to work. That frees your development team from having to work on documenting each module.
Simplifies continuous integration. One of the benefits of Agile software development is that you can mix and match practices and frameworks together to meet a goal. TDD makes the continuous integration of code into the code repository easier.
Increases ROI. TDD might sound more expensive at the beginning because of the costs related to writing tests, but actually, testing makes the overall development and maintenance process more cost-efficient long term. Making the code cleaner and easier to maintain, helps development teams solve issues faster.
Fewer bugs. Constantly testing and ensuring the code is modular makes it easier to spot and fix bugs. The ones that appear later get fixed faster because tests are done timely and in small units, instead of testing at the end of the project where it’s harder to find the issue.
What are the challenges of TDD?
Test-driven development is a great Agile technical practice but it has some disadvantages:
Longer development process. While TDD makes it easier to work on code after it was developed and deployed, it takes time to write tests and refactor code. TDD might not be too appealing at first, especially for projects that need to hit the market fast.
Steep learning curve. Most of the people who discourage this practice do it because they’re not fully familiar with it, or they don’t know how to do it, so they find it difficult. A good way to begin is by doing some code katas to practice doing automated tests.
Tests can feel like blockers. Having to wait for the tests to be ready to code against can feel like a frustrating extra step since nothing else can happen until the test is green. Getting everyone involved and aware of the “why” behind TDD can help overcome this challenge.
TDD could be less adaptable. When codebases are poorly written or tests aren’t small enough, every change request can make the development process longer and more exhausting. If the client isn’t fully settled on a desired outcome, it’s even more difficult to adapt code. That’s when a BDD approach could be more appropriate.
Test-driven development at NaNLABS
At NaNLABS we’re huge TDD believers, but we don’t get to apply it all the time, especially when we work as an augmented team using legacy code. In those cases, it can be harder to apply TDD.
It’s difficult to start using TDD when a lot of code has already been written. In those cases it’s a good idea to identify one part of the codebase that needs testing first.
At NaNLABs, we’d usually start with the most critical parts: the functionalities that are mixed with other parts of the code. First, we separate them. Then, we use a specific test for each functionality and do the red/green/refactor cycle. It isn’t pure TDD but it’s a way to refactor the code following a similar mindset.
In some scenarios, we’re able to apply TDD as we like. In other cases, we opt for other test automation practices in order to have some code coverage that brings confidence to the entire team.
For example, when NaNLABS worked with HyreCar, the client wasn’t that familiar with TDD practice at first.We explained how their microservice architecture development would benefit from the practice, applied it to the development process, and delivered high-quality and modular code.
Ready to build your own custom software with a team that cares about you and your processes? We’re not code monkeys, we care about you.
Are your development practices passing the test?
Test-driven development can help you identify bugs early in the development lifecycle and foster work iteration by consistently performing unit tests, instead of doing it only at the end of an Agile sprint.
TDD makes your software easier to scale and maintain long-term. It also ensures that your code, however fragile or complex, is handled with care.
One of the biggest reasons people discourage TDD is because they don’t truly understand how to do it. At NaNLABS, we’re fully familiar with the practice, and our developers are aware of the value attained by it. We apply different strategies depending on your business context and the current situation of your codebase.
If you believe TDD is valuable but don’t necessarily know where to begin, book our consultation hours or augment your team with one of our Agile pods. You won’t only get a final working software solution as a product, but you’ll get to interact with and learn from a fully Agile team.
Ready to build your own custom software with a team that cares about you and your processes? We’re not code monkeys, we care about you.
Frequently asked questions about test-driven development
What is the goal of test-driven development?
The main goal of TDD is to consistently guarantee proper code execution over time. It helps make the code become more modular and robust, and therefore better quality.
What is Agile testing?
Agile testing is a software development practice that promotes testing features and deliverables as they happen to ensure proper functionality and that bugs are spotted easily.
How is TDD different from Agile?
All TDD is Agile, but not all Agile is TDD. Agile is a software development methodology that fosters continuous improvement and iterative development.
TDD is an Agile practice that consists of performing unit tests on each deliverable to ensure that the code is doing what it’s expected to do.
What is refactoring in test-driven development?
Refactoring is an Agile practice that aims to rewrite the code in a cleaner way. When you refactor the code, you leave only the necessary lines to ensure functionality. Refactoring makes the software more scalable.