Test-Driven Development - A Win!

I’ve been working on a set of Java classes to parse meteorological reports. I also decided to use the Eclipse Java Development environment for the first time to write these classes, and I can say that I’m very pleased with the integration of smart features such as:
  • “Quick Fix” which suggests code amendments on request – such as adding class imports, declaring new classes, and the like.
  • “Refactor” which lets me rename a class and automatically rename the class file as well, since Java wants it that way. Lots more capabilities in refactoring – will be looking at that soon!
  • Java debugging with breakpoints in Eclipse – I came from the “old school” way of gdb and text based debugging. Printf statements anyone? I still use printf’s to output tracing statements even when there’s debugging capabilities in XCode or Visual Studio.
But the most important feature I’ve realised is that of Test-Driven Development. In the old days, we’d write test cases to exercise our code. This was quite cumbersome as developers had to write code to do the test, including comparisons to make sure that the result of the test was correct. This took lots of time and you tend to spend just as much time writing the test code and test support functions as the actual code itself.

With the advent of Test-Driven Development and the plethora of tools supporting that methodology, testing becomes easy, almost fun! Key mantra:

Make something easy to use, it becomes an enabler



In my case, I used the built-in JUnit integration which Eclipse provides. I can right click on a class file, ask for a JUnit test to be created, and designate which Java package the resulting JUnit test class file is to be added to. What you do to write a test case is to simply write a Java function to exercise the function being tested.

I started using JUnit 3 and finally settled on JUnit 4 which uses annotations – part of Java 5.0 – to designate which test case functions are to be run by JUnit.

Say you have a Java class called Temperature:

public class Temperature
{
  // class member data
  double _temperature; // this value is in Celsius

  public Temperature
  {
    _temperature = 0.0;
  }

  public Temperature( double temperature )
  {
    _temperature = temperature;
  }

  public getTemperature()
  {
    return _temperature;
  }

  public asCelsius()
  {
    return _temperature;
  }

  public asFahrenheit()
  {
    return _temperature * (9.0 / 5.0) - 32.0; // ERROR!
  }
}


Here’s what a JUnit test class would look like:

package test;

import static org.junit.Assert.*;

import org.junit.Test;

public class TemperatureTest
{
  @Test
  public void Check_Fahrenheit()
  {
   Temperature temp = new Temperature( 18.33 ); // in Celsius
  
   assertEquals( 65.0, temp, 0.1 );
  }
}


Running the JUnit test framework would result in an assert failure for the assertEquals, since the asFahrenheit function uses an incorrect formula. We would now go back to the asFahrenheit function and modify the code until the test passes.

Test-Driven Development proposes the following sequence of actions when adding a new feature to the project:

  1. Add a test
  2. Run all tests and see if the new one fails
  3. Write some code
  4. Run the automated tests and see them succeed
  5. Refactor code
  6. Repeat

I’m a little reserved in the potential for applying this methodology in a safety-critical software development, but I do think that making testing effortless and easy will help developers quite a bit, be they in enterprise applications or safety-critical embedded software.