Test Driven Development Walkthrough

This is a short walkthrough of doing software development with the Test Driven Development process.  I'm still learning TDD myself, so this example may not be approved by the TDD-purists, but I think it's consistent with the main principles discussed here.

Here's the design of a Java class.  Importantly, it fully specifies the method signature:
class Calculator
{
    /** Find the sum of a list of integers, represented as a string.
     * Example: 6  = add("1 3,2");
     * @param numbers a string representing 0 or more integers to be summed.
     * @result int sum of the integers. The sum of an empty string is zero.
     *        An integer > MAX_INT is ignored.
     * @pre Integers are separated by a comma, a blank, or a newline character.  
     */
    public static int add(String numbers)
    {
    }
}

Now let's build it incrementally, using the TDD process.

Application code

Test code


public class CalculateTest extends junit.framework.TestCase
{
    public void testEmptyString()   
    {
        assertEquals(0, Calculator.add(""));
    }
}

Create a test that won't compile.
class Calculator
{
    public static int add(String numbers)
    {
        return -1;
    }
}
Write code that compiles, but tests fail.

class Calculator
{
    public static int add(String numbers)
    {
        return 0;
    }
}
Make the code pass the test.



    public void testOneNumber()
    {
        assertEquals(1, Calculator.add("1"));
        assertEquals(2, Calculator.add("2"));
        assertEquals(999, Calculator.add("999"));
    }

adding a test that fails.
    public static int add(String numbers)
    {
        int result = 0;
        if (numbers.length() > 0)
        {
            result = Integer.parseInt(numbers);
        }
        return result;
    }
Add code needed to make the tests pass.



    public void testLargeNumber()
    {
        assertEquals(Integer.MAX_VALUE, Calculator.add("2147483647"));
        assertEquals(0, Calculator.add("2147483648"));
    }
adding a test that causes NumberFormatException
    public static int add(String numbers)
    {
        int result = 0;
        if (numbers.length() > 0)
        {
            try
            {
                result = Integer.parseInt(numbers);
            }
            catch (java.lang.NumberFormatException nfe)
            {
                result = 0;
            }
        }
        return result;
    }

add code needed to make the tests pass.


    public void testMultipleNumbers()
    {
        assertEquals(5, Calculator.add("2 3"));
        assertEquals(12, Calculator.add("2 3 2 5"));
    }
adding a test that fails.
    public static int add(String numbers)
    {
        int result = 0;
        if (numbers.length() > 0)
        {
            String[] values = numbers.split(" ");
            for (String item : values)
            {
                result = result + getInt(item);
            }
        }
        return result;
    }
    private int getInt(String number)
    {
        int result = 0;
        try
        {
            result = Integer.parseInt(number);
        }
        catch (java.lang.NumberFormatException nfe)
        {
            result = 0;
        }       
        return result;
    }

Refactor and add code needed to make the tests pass.


    public void testDelimiters()
    {
        assertEquals(5, Calculator.add("2,3"));
        assertEquals(12, Calculator.add("2 3,2\n5"));
    }
adding a test that fails.
    public static int add(String numbers)
    {
        int result = 0;
        if (numbers.length() > 0)
        {
            StringTokenizer st = new StringTokenizer(numbers, " ,\n");
            while(st.hasMoreTokens())
            {
                String item = st.nextToken();
                result = result + getInt(item);
            }                       
        }
        return result;
    }
Refactor and add code needed to make the tests pass.

Are we done?