Test-driven development 101

Please ensure you have a basic understanding of oriented object languages when looking for more information about this technique.

Once you have completed this article, your review of the software development will be changed.

What is test-driven development?

Test-driven development was developed by Kent Beck in the 1990s when he introduced extreme programming. This is a software development technique that favors a test-with-code approach, and it is based on a short feedback cycle: write a test–pass it–refactor the code.

As a developer, you most likely used to follow the traditional coding habit of writing code, so you write tests to see if your code is clean and strong.

Each developer that tried and used to follow the TDD approach found it very helpful to write cleaner and faster code than before. So they wouldn't write even one line of code without one line of test preceding it.

Additionally, it helps you to develop your requirements in a good way and to be sure that what you develop is what you really need, and in the end, you gain tests and the highest coverage code.

To resume, the main goal of TDD is to write as little code as possible while satisfying the expected functionality.

Steps to follow

The steps to follow to set up this method are three:

  • Write a failing test case before any business code, and you should not write more of a test case than is sufficient to fail ==> R (Red)
  • Write the minimum business code that is sufficient to make the test pass ==> G (Green)
  • Refactor the business code and ensure that the test case still succeeds ==> R (Refactor)

At each step of the iteration, we will write the minimum of code to satisfy the need.

Let’s describe a little bit the 3 steps:

R (Red): when we start to develop new functionality using TDD, we write firstly a test case for this requirement. At this stage, the production code to make this test pass is not yet written.

G (Green): when the test case was written, you can now write the minimum production code that makes the test pass. Sometimes the implementation is simple and you can return the hardcoded value. The idea is to avoid a complicated implementation and to minimize the development time.

R (Refactor): In this stage, you look for improving the code quality by dividing the code into methods, variable naming, or creating new classes.

Development cycle

The development cycle using Test Driven Development is made up of five stages, which are:

  1. Writing a first test case
  2. Run the test and it fails, because the code it tests has not yet been implemented
  3. Writing the minimum code to pass the test
  4. Execution of the tests in order to control that the tests pass and respect the functional rules of the unit tests
  5. Refactoring of code in order to improve its quality, while maintaining functional code
  6. Repeat from the beginning

Intro to test driven development

Don't forget that we are testing one thing at a time.

A lot of developers ignore the third step: Refactoring. It is the one that I personally considered so important. It helps you to make your code clean, strong, and easier to understand by you in a couple of months and by other developers. That is why I suggest you look for the book by Uncle Bob (Robert Cecil Martin), “Clean Code”.

Simple example

Let’s have the popular example that we found when we look for a learning unit test: the addition of two numbers.

First of all, you do a test class and one assert that fails:

<?php

namespace App\Test;

use PHPUnit\Framework\TestCase;

class AdditionTwoNumbersTest extends TestCase
{
public Calculator $calculator;
public function setUp()
{
$this->calculator = new Calculator();
}

public function should_return_4_when_added_2_and_2(): void
{
$this->assertEquals(4, $this->calculator->add(2, 2));
}
}

For a moment, you test the addition of the Calculator class feature that you haven't even created, so when you run the test, it will fail.

Let’s make it work:

<?php
namespace App\Domain;
class Calculator {
    public function add(int $a, int $b): int  {
       return 4;
    }
}

Now, you created your class Calculator with the add method. So if you run your test, it will pass because I return 4 which represents 2+2. Here I write the minimum code to make the test pass.

For now, there is nothing to refactor because it is simple and understandable.

Let’s add a new assert:

$this->assertEquals(5, $this->calculator->add(3, 2));

Run the test and you will see that the first assert passes and the second assert fails, which is so normal as we hard-coded our solution: remember you write the minimum code that makes your test pass.

Now, you should correct the second assertion for the second iteration. In the add** method, you should replace 4 by the addition return $a + $b; .

Now if you run the test, all asserts pass.

In this example, you will notice that you have quick feedback that drives you to quickly fix the wrong code.

This is a simple and little example. I suggest looking for the example of kata FizzBuzz that is used in the hiring process.

Advantages

  • By writing the tests, you first ensure that the tests will be written (because they are often postponed for lack of time or interest).
  • You can minimize the time needed to refactor the code.
  • You can maintain the old code and add new features without any trouble.
  • You can get feedback faster.
  • It is easier to refactor and maintain.
  • There is automatic verification by having a large number of tests that ensures the strength and warranty of the code.
  • You only write the minimum production code needed.
  • You gain the highest coverage code at the end.

Disadvantages

  • It is hard to apply this to a legacy code. Firstly the code should be refactored.
  • It cannot be easy for developers to learn at first, especially learning it alone on your own.
  • It is a very slow process when you are a beginner in TDD.

Conclusion

TDD stands for Test Driven Development and it is an approach in which test cases are written before the functionality code in order to validate that the code works well.

TDD is based on simple iteration in order to minimize the functionality, and it is the opposite of Test First which stands for creating all the tests for the functionality and then writing the business code.

The main advantage of TDD against Test First is the quick feedback that each small iteration gives you in return.

In this article, I give a short introduction to Test Driven Development and I encourage you to read more articles about it.


Written by Hicham Ben Kachoud, 27 years old developer from Morocco. He graduated from Mundiapolis University Casablanca as a Software Engineer in 2018 and now has 4 years of experience in web development.

He is a fullstack developer within a French Company and contributes to the development of a web application in the e-commerce domain.

His biggest interests are PHP languages using the Symfony framework. He is addicted to crafting concepts like Domain Driven Design, Test Driven Development, Clean Architecture, Design Principles (SOLID, KISS, YAGNI, DRY), and Design Patterns.

He used to share his knowledge through medium platforms, including LinkedIn and Facebook networks.

LinkedIn

Github

Medium

Find your next developer within days, not months

In a short 25-minute call, we would like to:

  • Understand your development needs
  • Explain our process to match you with qualified, vetted developers from our network
  • You are presented the right candidates 2 days in average after we talk

Not sure where to start? Let’s have a chat