Test Driven Development by Example

Test-driven development (TDD) is a software development. First the developer writes an (initially failing) automated test case that defines a desired improvement or new function, then produces the minimum amount of code to pass that test,  process that relies on the repetition of a very short development cycle and finally refactors the new code to acceptable standards.


The following sequence of steps is generally followed:


  1. First, the developer writes some (initially failing) tests.
  2. The developer then runs those tests and they fail because none of those features are actually implemented.
  3. Next, the developer actually implements those features in the code.
  4. If the developer writes his code well, then the in next stage he will see his tests pass.
  5. The developer can then refactor his code, add comments, clean it up.
  6. The cycle can just continue as long as the developer has more features to add. A flowchart is given below of this cycle



Now we will write some test-methods for following test cases:

1.  0! should return 1
2.  1! should also be 1
3.  2! should return 2
4.  4! should return 24
5.  10! should return 3628800

import static org.junit.Assert.*;
import com.tdg.tdd.demo.*;
import org.junit.Test;

public class CalculateFactorialTest {

private FactorialCalculator factCalc=new FactorialCalculator();

@Test
public void shouldReturnOneWhenZeroIn(){
assertEquals(1, factCalc.getFactorial(0));
}

@Test
public void shouldReturnOneWhenOneIn(){
assertEquals(1, factCalc.getFactorial(1));
}

@Test
public void shouldReturnTwo() {
assertEquals(2, factCalc.getFactorial(2));
}

@Test
public void shouldReturnSix() {
assertEquals(6, factCalc.getFactorial(3));
}

@Test
public void shouldReturnTwentyFour() {
assertEquals(24, factCalc.getFactorial(4));
}

@Test
public void shouldFindCorrectFactorialFor10() {
assertEquals(3628800, factCalc.getFactorial(10));
}
}

I execute the test class now, and now I got following output




As we can see two cases are pass and four fail. Lets fix the failing test,

package com.tdg.tdd.demo;

public class FactorialCalculator {

    public long getFactorial(int i) {
if (i < 2) {
return 1;
}
return getFactorial(i - 1) * i;
}
}
I execute the test class again, and now all test cases are passed.



Lets clean up test-code.

import static org.junit.Assert.*;
import com.tdg.tdd.demo.*;
import org.junit.Test;

public class CalculateFactorialTest {

    private FactorialCalculator factCalc=new FactorialCalculator(); 
@Test
    public void shouldReturnCorrectFactorialValue() {
        int values[][] = {{0,1}, {1,1}, {2,2}, {3,6}, {4,24}, {10,3628800}};
        for(int[] value: values) {
            assertEquals(value[1], factCalc.getFactorial(value[0]));
        }
    }
}

Now we can repeat above steps by adding more test cases. Starting with another new test, the cycle is then repeated to push forward the functionality. The size of the steps should always be small, with as few as 1 to 10 edits between each test run. If new code does not rapidly satisfy a new test, or other tests fail unexpectedly.

Using TDD approach we can write an effective, organized and neat code. Also Encourage the writing of quality code.


Write a comment
Cancel Reply