test-driven-development

What is test driven development? (+Examples)

“The original description of TDD was in an ancient book about programming. It said you take the input tape, manually type in the output tape you expect, then program until the actual output tape matches the expected output.” — Kent Beck, a software engineer who “rediscovered” the TDD technique in 2003. 

Case studies were conducted with three development teams at Microsoft and one at IBM that adopted test driven development. Results showed that the pre-release defects of the four products decreased between 40% and 90% relative to similar projects that did not use the TDD practice. Understanding test driven development and how it works is an important step in developing a software product.

That is why we created this text to walk you through all the details you need to know about test driven development. Let's begin.

We can help you drive TDD as a key initiative aligned to your business goals

Contact us

What is test driven development (TDD)?

Test-driven development (TDD) is a software development process that relies on repeating a very short development cycle. In TDD, the developer writes automated unit tests and uses those tests to drive the software's development. 
TDD involves creating automated unit tests that intentionally fail and writing code to pass them. This iterative process continues, refining code and adding tests until all desired functionality is implemented. This fosters early defect detection and enhances development efficiency, particularly in Agile environments.

Three phases of TDD (Test driven development cycle)

The three phases of the TDD cycle are commonly referred to as Red, Green, and Refactor. Here is a brief explanation of each phase:

  • Red: In this phase, the developer writes a failing test to represent a new feature or change in functionality. The test should be specific, automated, and written to fail.
  • Green: In this phase, the developer writes the code that makes the failing test pass. The primary goal is to write the minimum amount of code necessary to meet the test's requirements.
  • Refactor: In this phase, the developer reviews the code that was just written and looks for ways to improve its design, structure, and performance. The goal is to make the code more maintainable and easier to understand. Sometimes the Refactor phase is referred to as Blue because, after the Red and Green phases, the test suite should already be passing, or blue.

how-tdd-works

Here are some more explanations of each phase:

Red:

  • Write a test that defines the functionality you want to implement.
  • The test should be small and specific to make diagnosing failures easy.
  • The test should fail, indicating that the functionality has not been implemented yet.

Green:

  • Write the minimum amount of code required to make the test pass.
  • It's important not to write any additional code beyond what is required by the test.
  • The code should be written with quality and maintainability in mind.

Refactor:

  • Review the code that was written during the Green phase.
  • Make any necessary improvements to the code, such as simplifying logic, improving performance, or improving readability.
  • Refactor with confidence that the tests still pass.

Benefits of TDD

Here are 10 benefits of using TDD in software development:

  1. TDD ensures that software is thoroughly tested before it is released to production.
  2. It encourages modular design, resulting in simpler and more easily maintainable code.
  3. TDD provides a clear specification or contract for what the code should do, making it easier for developers to create software that meets the requirements.
  4. It can help reduce the time spent debugging and troubleshooting as defects are discovered early in development.
  5. TDD encourages developers to write better, more efficient code by forcing them to write tests that are easy to run repeatedly and confirm the expected behavior.
  6. It helps create software that is more resilient to change by ensuring that each change to the code doesn't break the code.
  7. TDD can help to improve overall development speed by allowing developers to catch issues earlier in the process.
  8. It helps to prioritize the development process and focus on what needs to be built rather than piling feature upon feature.
  9. TDD makes the code and software design much less daunting for new developers, particularly if they join a project after ongoing development.
  10. It fosters a collaborative development environment as tests become a common language for developers, testers, and stakeholders.

Pros & Cons of test driven development

TDD-pros-and-cons

Integrating TDD within Agile development

Test-driven development (TDD) is an important practice in Agile development because it enables developers to build and deliver high-quality software in an iterative, flexible, and collaborative manner. Here are some specific ways that TDD fits into Agile development:

  • Quality assurance: Adopting a method of writing tests before coding helps ensure software meets requirements and is free of bugs and defects.
  • Collaboration: When utilizing a practice like TDD, tests are written beforehand, and developers, testers, and stakeholders collaborate more effectively, as these tests serve as a shared platform for everyone involved in the project.
  • Continuous feedback: Preceding code with tests provides ongoing feedback on code quality, enabling continuous improvement throughout development. This allows for continuous improvements throughout the development cycle rather than waiting until the end.
  • Flexibility to change: Writing tests before code allows for confident refactoring, simplifying the accommodation of project changes. This approach allows for confident code refactoring without the risk of introducing new issues.
  • Incremental development: Test-driven methods align well with Agile's incremental approach, enabling the delivery of functional software in iterative increments. This enables developers to deliver functional software while enhancing its features over time.

TDD vs. BDD vs. ATDD

Here are the key differences between test driven development (TDD), behaviour driven development (BDD), and acceptance test driven development (ATDD).

tdd-vs-bdd-vs-atdd

Test driven development best practices

Here are 15 best practices for test driven development:

  1. Start with a clear goal: Begin each TDD cycle with a clear understanding of the functionality or behavior you aim to achieve.
  2. Write failing tests first: Before writing any production code, write a failing test defining the desired behavior or feature.
  3. Keep tests simple and focused: Each test should focus on a single aspect of the implemented behavior or feature.
  4. Utilize the RED-GREEN-REFACTOR cycle: Follow the cycle of writing a failing test (RED), making it pass by writing the minimum amount of code (GREEN), and then refactoring to improve code quality while keeping all tests passing (REFACTOR).
  5. Write minimal production code: Write only the code necessary to make the failing test pass, avoiding premature optimization or over-engineering.
  6. Follow the arrange-act-assert pattern: Organize each test into three sections: setup (Arrange), execution (Act), and validation (Assert).
  7. Keep tests independent: Ensure that each test is independent of other tests and can be run in any order without affecting the outcome.
  8. Refactor regularly: Refactor test and production code continuously to improve readability, maintainability, and design.
  9. Maintain readable test names: Use descriptive and meaningful names for tests that communicate the behavior being tested.
  10. Use test doubles for isolation: Employ test doubles such as mocks, stubs, and fakes to isolate the code under test from its dependencies.
  11. Implement just enough setup: Setup only the necessary preconditions for each test, avoiding unnecessary complexity or duplication.
  12. Prioritize tests: Write tests for critical or high-risk functionality first to ensure early detection of issues and maintain focus on delivering value.
  13. Keep tests fast: Ensure that tests run quickly to maintain developer productivity and encourage frequent execution during development.
  14. Test behavior, not implementation: Focus on testing the code's external behavior rather than its internal implementation details.
  15. Review and collaborate: Review tests regularly with team members to share insights, identify improvements, and ensure consistency in testing practices.

Examples

Example 1: Simple Calculator

  1. Objective: The goal is to create a basic calculator capable of performing addition.
  2. Write a failing test: Begin by crafting a test to verify whether the calculator's addition functionality returns the correct result for a given input. This test is composed before any actual implementation code.
  3. Write minimal production code: Implement the simplest possible code to fulfill the failing test's criteria. This involves creating a “Calculator” class with an “add” method that simply adds two numbers together.
  4. Run the test and make it pass: Execute the test suite, expecting it to fail initially as the calculator functionality hasn't been implemented yet. Then proceed to write the code for the “Calculator” class, ensuring it passes the test.
  5. Refactor: If necessary, refine the code for better readability or efficiency. However, in this straightforward scenario, additional refactoring might not be needed.

Example 2: Email Validator

  1. Objective: The aim is to develop a function capable of validating email addresses.
  2. Write a failing test: Initiate by composing tests to validate whether the email validation function accurately identifies valid and invalid email addresses.
  3. Write minimal production code: Develop the email validation function employing a simple regular expression to match the email format.
  4. Run the test and make it pass: Execute the tests, anticipating that they will fail initially due to the absence of the validation function. Then, proceed to implement the validation function to satisfy the tests.
  5. Refactor: If required, refine the regular expression or the validation function to handle edge cases or enhance readability.

Example 3: To-Do List

  1. Objective: The objective is to create a straightforward To-Do list application.
  2. Write a failing test: Begin by writing a test to confirm the ability to add tasks to the To-Do list.
  3. Write minimal production code: Develop a “TodoList” class featuring an “add_task” method to insert tasks into the list.
  4. Run the test and make it pass: Execute the test suite, expecting initial failure due to the absence of the “TodoList” functionality. Then proceed to implement the “TodoList” class to fulfill the test requirements.
  5. Refactor: If necessary, refine the “add_task” method to accommodate additional features or improve efficiency.

How can Global App Testing assist?

Global App Testing offers an elastic and fast tester supply that you can instantly expand when you need human expertise for tests that cannot be automated. Our Elastic QA approach merges technology with human expertise, delivering swift and valuable software testing. 
We integrate third-party QA resources to cater to your team's dynamic testing requirements and release cycles, creating tailored solutions when needed.

With a network of 90,000 testers across 190 countries, we blend automation with a 'human in the loop', empowering you to tap into and out of resources per your specific needs. 
As an additional resource, Global App Testing partners with your existing QA team to give you access to our global tester network. Here are some additional benefits of using our services:

Easy-to-use platform:

  • Our intuitive platform seamlessly integrates with your development workflow, enhancing overall efficiency.
  • Access a centralized dashboard to effortlessly manage testing projects, monitor progress, and engage with testers, promoting collaboration.
  • Benefit from detailed bug context and visual evidence to better understand identified issues.

Fast and reliable services:

  • With our 24/7 service, you can expect prompt delivery of test results within 6 to 48 hours. We cater to urgent testing needs and support overnight launches.

Quality assurance:

Extra benefits:

  • Explore a wealth of guides, webinars, and articles to adopt and understand best practices in performance testing.

Ready to learn more? Sign up now to schedule a quick call today!

We can help you drive TDD as a key initiative aligned to your business goals

Contact us

Keep learning

Testing in Agile - What are the benefits?
What is Automation Testing? - Everything You Need To Know
A guide to outsourced software testing