Skip to content

Test-Driven Development (TDD)

Overview

Test-Driven Development (TDD) is a software development methodology in which tests are written before the actual implementation of code. It follows a short iterative cycle of writing a failing test, implementing the minimum amount of code to pass the test, and then refactoring the code.

TDD Cycle

TDD follows the Red-Green-Refactor cycle:

  1. Red – Write a failing test that defines a function or improvement.
  2. Green – Write the minimal code required to pass the test.
  3. Refactor – Improve the code while ensuring that all tests continue to pass.

Example: TDD in C#

Let's demonstrate TDD with a simple example: a calculator with an Add method.

Step 1: Write a Failing Test (Red)

using NUnit.Framework;

[TestFixture]
public class CalculatorTests
{
    [Test]
    public void Add_TwoNumbers_ReturnsSum()
    {
        // Arrange
        var calculator = new Calculator();

        // Act
        int result = calculator.Add(2, 3);

        // Assert
        Assert.AreEqual(5, result);
    }
}

At this point, the test fails because Calculator and Add method do not exist yet.

Step 2: Implement the Minimal Code (Green)

public class Calculator
{
    public int Add(int a, int b)
    {
        return a + b;
    }
}

Now the test passes successfully.

Step 3: Refactor (Refactor)

Since the implementation is already optimal, no further refactoring is needed in this case. However, in real-world scenarios, you may improve structure, remove duplication, or optimize performance.

Benefits of TDD

  • Higher Code Quality – TDD Encourages modular, testable, and reliable code.
  • Better Design – Forces developers to think through requirements before implementation.
  • Fewer Bugs – Catch issues early, reducing costly fixes later.
  • Better Documentation – Tests serve as living documentation for expected behaviors.

Alternative Approaches

While TDD is a powerful methodology, alternative testing and development approaches exist:

1. Behaviour-Driven Development (BDD)

Focus: Tests written in a human-readable format (e.g., using Gherkin syntax). For example:

    Feature: Calculator
      Scenario: Add two numbers
        Given I have a calculator
        When I add 2 and 3
        Then the result should be 5

Common Tools: SpecFlow, Cucumber

2. Traditional Testing (After Development)

Write tests after implementation. This is less strict but allows more flexibility.

This approach however may result in lower test coverage and harder-to-test code.

3. Exploratory Testing

Testers manually explore and verify application behaviour.

This approach is useful for UX, edge cases, and security testing. It is not automated but valuable for uncovering unexpected issues.

Conclusion

TDD is an effective methodology that improves code reliability, design, and maintainability. However, alternative approaches like BDD, traditional testing, and exploratory testing can complement TDD depending on the project needs.

A well-balanced software development strategy often combines multiple testing methodologies to achieve optimal results.