How To TDD For Dummies

Posted on



What is Test Drive Development?

  • It’s the process of letting tests lead our development.
  • Write a test that fails and then write the production code that will make it pass.



How To Name a Test?

  • I like to follow the Given_When_Then format.
  • We specify three things
    -The conditions predefined for the test (Given)
    -The action that will be tested (When)
    -The result we wait for (Then)



TDD Rules ⚖️

According to Uncle Bob, TDD has three rules

You are not allowed to:

  1. Write any production code unless it is to make a failing test pass.
  2. Write any more production code than it is sufficient to pass the single failing test.
  3. Write any more unit test code than it is sufficient to fail.
    • Compilation failures are considered failures.



Confession

  • I don’t follow those rules 100% of the time.
  • Sometimes I write more production code than what makes the test pass, sometimes I write code without tests.
  • It’s human nature I think, we can’t follow the rules all the time



Code Example For a Calculator



Let’s look at the requirements

  • The method can take 0, 1 or 2 numbers as a string, and will return their sum (for an empty string it will return 0)

First of all, let’s write the code to handle the empty string case

    @Test
    public void givenEmptyString_Return0(){
        CalculatorService calculatorService = new CalculatorService();
        int result = calculatorService.getSum("");
        assertEquals(0, result);
    }
Enter fullscreen mode

Exit fullscreen mode

When you write this code, it will give you a compilation error because CalculatorService and its getSum method don’t exist.
So, we create the service and its method and write a simple logic to return 0 on empty strings

public class CalculatorService {
    public int getSum(String s) {
        if (s.isEmpty())
            return 0;
        else
            return 1;
    }
}
Enter fullscreen mode

Exit fullscreen mode

Note that the 1 in the else statement is an arbitrary value used to avoid compiler error since we have to return a value from the method.


Now, let’s write a test to handle strings with 1 number

    @Test
    public void givenAStringWith1Number_ReturnIt_WhenCalculateSum(){
        CalculatorService calculatorService = new CalculatorService();
        int result = calculatorService.getSum("5");
        assertEquals(5, result);
    }
Enter fullscreen mode

Exit fullscreen mode

When we first run this test, it will fail because the returned value is 1. So let’s make it work

    public int getSum(String s) {
        if (s.isEmpty())
            return 0;
        else if (s.length() == 1)
            return Integer.parseInt(s);
        else
            return 1;
    }
Enter fullscreen mode

Exit fullscreen mode


Next, let’s write a test to handle strings with 2 numbers

    @Test
    public void givenAStringWith2Numbers_WhenCalculateSum_ThenReturnSum(){
        CalculatorService calculatorService = new CalculatorService();
        int result = calculatorService.getSum("69");
        assertEquals(15, result);
    }
Enter fullscreen mode

Exit fullscreen mode

This test will fail because 1 doesn’t equal 15. duh!
Let’s make it work

    public int getSum(String s) {
        if (s.isEmpty())
            return 0;
        else if (s.length() == 1)
            return Integer.parseInt(s);
        else
            return getSumForMultipleNumbers(s);
    }

    private int getSumForMultipleNumbers(String s) {
        return Arrays.
                stream(s.split("")).
                mapToInt(Integer::parseInt).
                sum();
    }
Enter fullscreen mode

Exit fullscreen mode



Celebration



We’ve just applied TDD to program a really simple calculator.



Further Readings ‍

How To Unit Test Like a Pro

5 TDD Most Common Mistakes



Code On GitHub ‍

Leave a Reply

Your email address will not be published.