Homepage of Ingo Klöckl
 Home
 Programmieren
 - Toolbox
 - Java
 - PostScript
 - Perl
 - Assembler
 - Links
 - Download
Ingo Klöckl
i.kloeckl@2k-software.de

Unit testing with JUnit

With JUnit, there is a powerful framework for manual and even automatic unit testing of Java programs. The usage of JUnit is so easy that there is no excuse for not using it. It can even be used in a test-driven development cycle. Here, I want to present a very short tutorial of using JUnit.

Using JUnit for testing of an existing module

I want to give a short introduction into JUnit by explaining how to test a pre-existing class. This scenario can easily be converted into a test-driven development cycle. In this case, you start with an empty class, write a test for a piece of funtionality, and add this method to the class. After testing and fixing this method, the next test for the next functionality and the next method is written ...

As explaing, we assume that we have written a Java class Mathe which provides some more or less important methods for calculate something (the code can be downloaded here):
public class Mathe {
  public int fak(int piN){
    int iValue = 0; // 0 is wrong, 1 would be correct!
    int iCnt = 0;
    while (iCnt++ < piN){
      iValue = iValue*iCnt;
    }
    return iValue;
  }

  public double MWSt(double pdAmount){
    return pdAmount*0.16;
  }
  
  public boolean isOdd(int piN){
    return (piN%2 == 1);
  }
}
To test this class with JUnit, do the following:

  • Write a class MatheTest, which extends TestCase:
    public class MatheTest extends junit.framework.TestCase {
      ...
    }
    
  • For each functionality to test, write a test method:
      public void testName(){
        <check something>
      }
    
    Note that these methods have names which starts with test. This allows JUnit to use inflection to find all your test methods.
    In the test methods, you can use the following methods to let JUnit check the results of your class:
    assertEquals(message, expected_value, actual_value)
    assertEquals(message, expected_value, actual_value, delta_of_value)
    assertTrue(message, actual_value)
    assertFalse(message, actual_value)
    
    (There are more of these assertion methods.)
  • If your test methods needs a common setup, you can build the required environment using the protected methods setUp() and tearDown() to set up the environment and to destroy it. These methods are called before and after the tests, respectively. Note that you will need some instance variables for the environment.
  • Finally, add code like this:
      public static Test suite(){
        return new TestSuite(MatheTest.class);
      }
    
  • If your code requires a certain order of the tests, you may modify the suite() method:
      public static Test suite(){
        TestSuite suite = new TestSuite();
        suite.addTest(new MatheTest("testOdd"));
        ...
        return suite;
      }
    
    (If you really have to arrange the order of tests, this is normally regarded as bad design, but may be required sometimes.)
Now you are ready to test the class. For our math module, the complete test class looks like this (download it from here):
/*
  MatheTest.java

  Setup:
$ javac -classpath %JUNIT_PATH%/junit.jar;. MatheTest.java
$ java -classpath %JUNIT_PATH%/junit.jar;. junit.textui.TestRunner MatheTest
  or
$ java -classpath %JUNIT_PATH%/junit.jar;. junit.swingui.TestRunner MatheTest

*/

import junit.framework.*;

public class MatheTest extends TestCase {
  Mathe m;

  public static Test suite(){
    TestSuite suite = new TestSuite(MatheTest.class);
    return suite;
  }

  protected void setUp(){
    m = new Mathe();
  }

  protected void tearDown(){
    // nothing to do here
  }
  
  public void testFakultaet(){
    assertEquals("0! should be 1!", 1, m.fak(0));
    assertEquals("1! should be 1!", 1, m.fak(1));
    assertEquals("2! should be 2!", 2, m.fak(2));
    assertEquals("3! should be 6!", 6, m.fak(3));
  }

  public void testMWSt(){
    assertEquals("MWSt of 100 should be 16!", 16.0, m.MWSt(100.), 0.001);
    assertEquals("MESt of 1 should be 0.16!", 0.16, m.MWSt(1.), 0.001);
  }
  
  public void testOdd(){
    assertFalse("0 should not be odd!", m.isOdd(0));
    assertTrue("1 should be odd!", m.isOdd(1));
    assertFalse("2 should not be odd!", m.isOdd(2));
  }
}

Starting JUnit

There are several ways to start JUnit:

  • Using the test runner delivered with JUnit:
    java -classpath .;$JUNIT_PATH/junit.jar junit.textui.TestRunner MatheTest
    
    The result looks like the one shown in this picture.
  • There is also a very nice graphical front-end for JUnit included. Start it by typing
    java -classpath .;$JUNIT_PATH/junit.jar junit.swingui.TestRunner MatheTest
    
    This front-end looks like the one shown here. If you click on the hierarchy tab, you get a detailed tree of all tests (shown here).
  • To start the test program from the command line, you have to include a main method which performs the JUnit startup. The method looks like this one:
    public static void main(String args[]){
      junit.textui.TestRunner.run(suite());
    }
    

Collecting tests in test suites

If you have written several test classes, you may want to collect them into a test suite for a complete source tree or sub-tree. You can do this by using the TestSuite class. To build a test suite for the math test class written above, we write the following program (downloadable from here):
/*
  MatheTestSuite.java

  Setup:
$ javac -classpath %JUNIT_PATH%/junit.jar;. MatheTestSuite.java
$ java -classpath %JUNIT_PATH%/junit.jar;. junit.textui.TestRunner MatheTestSuite
or
$ java -classpath %JUNIT_PATH%/junit.jar;. junit.swingui.TestRunner MatheTestSuite

*/

import junit.framework.*;

public class MatheTestSuite extends TestCase {
  public static Test suite(){
    TestSuite suite = new TestSuite();
    suite.addTest(MatheTest.suite());
    // more tests to be added here ...
    return suite;
  }
}

back to toolbox page