<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<article id="JUnit">
  <articleinfo>
    <title>JUnit Testing Utility Tutorial</title>
    <author>
      <firstname>Ashley</firstname>
      <othername>J.S</othername>
      <surname>Mills</surname>
      <affiliation>
 <address><email>ashley@ashleymills.com</email></address>
      </affiliation>
    </author>

    <copyright>
      <year>2005</year>
      <holder role="mailto:ashley@ashleymills.com">The University Of Birmingham</holder>
    </copyright>
  </articleinfo>

  <sect1 id="JUnit-Introduction"><title>Introduction</title>
    <para>
      JUnit is a framework for implementing testing in Java.  It provides a simple way to explicitly test specific areas of a Java program, it is extensible and can be employed to test a hierarchy of program code either singularly or as multiple units.
    </para>

    <para>
      Why use a testing framework? Using a testing framework is beneficial because it forces you to explicitly declare the expected results of specific program execution routes.  When debugging it is possible to write a test which expresses the result you are trying to achieve and then debug until the test comes out positive.  By having a set of tests that test all the core components of the project it is possible to modify specific areas of the project and immediately see the effect the modifications have on the other areas by the results of the test, hence, side-effects can be quickly realized.
    </para>

    <para>
      JUnit promotes the idea of first testing then coding, in that it is possible to setup test data for a unit which defines what the expected output is and then code until the tests pass.  It is believed by some that this practice of &quot;test a little, code a little, test a little, code a little...&quot; increases programmer productivity and stability of program code whilst reducing programmer stress and the time spent debugging.  It also integrates with Ant <ulink url="http://jakarta.apache.org/ant/">http://jakarta.apache.org/ant/</ulink>.
    </para>
  </sect1>

  <sect1 id="JUnit-Installation"><title>Installation</title> 
    <para>
      It is assumed that you know how to setup environment variables and install software on your operating system, for a comprehensive guide to doing so for Windows see <ulink url="../winenvars/winenvarshome.html"><citetitle>Configuring A Windows Working Environment</citetitle></ulink>, for Unix see <ulink url="../unixenvars/unixenvarshome.html"><citetitle>Configuring A Unix Working Environment</citetitle></ulink> Follow these instructions to install JUnit:
    </para>

    <orderedlist>
      <listitem>
        <para>
          Download the latest version of JUnit from 
          <ulink url="http://download.sourceforge.net/junit/">http://download.sourceforge.net/junit/</ulink>
        </para>
      </listitem>
      <listitem>
        <para>
          Uncompress the <filename>zip</filename> to a directory of your choice.
        </para>
      </listitem>
      <listitem>
        <para>
          Add <filename>/path/to/whereyouextractedjunit/junit/junit.jar</filename> to your Java <envar>CLASSPATH</envar>
          environment variable.
        </para>
      </listitem>
    </orderedlist>
  </sect1>

  <sect1 id="JUnit-Basics"><title>JUnit Basics</title>
    <para>
      This section will begin with a simple example which will illustrate the basic concepts involved in testing
      with JUnit.
    </para>

    <example id="JUnit-SimpleExample"><title>Simple Example</title>
      <programlisting>
import junit.framework.*; <co id="JUnit-SimpleExample-Import"/>
public class SimpleTest extends TestCase { <co id="JUnit-SimpleExample-Extends"/>
   public SimpleTest(String name) { <co id="JUnit-SimpleExample-Constructor"/>
      super(name);
   }

   public void testSimpleTest() {<co id="JUnit-SimpleExample-Test"/>
      int answer = 2;
      assertEquals((1+1), answer); <co id="JUnit-SimpleExample-Assert"/>
   }
}
      </programlisting>

      <calloutlist>
        <callout arearefs="JUnit-SimpleExample-Import">
          <para/>
          <programlisting>
import junit.framework.*;
          </programlisting>
          <para>
            Since we are using some constructs created by the makers of JUnit we must import any of the classes we desire to use, most of these reside in the framework subdirectory, hence the import statement.
          </para>
        </callout>

        <callout arearefs="JUnit-SimpleExample-Extends">
          <para/>
          <programlisting>
public class SimpleTest extends TestCase {
          </programlisting>
          <para>
            Our simple class needs to define its own test method(s) to actually be of any use so it extends TestCase which provides us with the ability to define our own test methods.
          </para>
        </callout>

        <callout arearefs="JUnit-SimpleExample-Constructor">
          <para/>
          <programlisting>
public SimpleTest(String name) {
   super(name);
}  
          </programlisting>
          <para>
            Every test is given a name so that when viewing the output results of the overall test we can see which test an error was generated if the test fails.  The constructor provides this functionality by passing the parameter passed upon construction to the parent class.
          </para>
        </callout>

        <callout arearefs="JUnit-SimpleExample-Test">
          <para/>
          <programlisting>
public void testSimpleTest() {
   int answer = 2;
   assertEquals((1+1), answer);
}
          </programlisting>
          <para>
            This is one of the tests included within this TestCase, at the moment it is the only test but you are allowed to add as many as you like.  You can see that we can define variables and perform arithmetic like any other Java program.  
          </para>
        </callout>

        <callout arearefs="JUnit-SimpleExample-Assert">
          <para/>
          <programlisting>
public void testSimpleTest() {
   int answer = 2;
   assertEquals((1+1), answer);
}
          </programlisting>

          <para>
            This simple test tests whether 1+1 is equal to the value of <emphasis>answer</emphasis>. This is just an extremely simple example, more usually one may want to test the result of some function, perhaps a function that is supposed to strip all the 'a' characters from a string, you might test this like this: 
          </para>

          <programlisting>
public void testStringStripFunction() {
   String expected = &quot;bb&quot;
   StringStripper stripper = new StringStripper();
   assertEquals(expected, stripper.stringStrip(&quot;aabaaaba&quot;));
}
          </programlisting>

          <para>
            Which would cause assertEquals to fail if the <emphasis>stringStrip</emphasis> method did not perform as expected, one could then try to fix the code and run the test again until it passed.
          </para>
        </callout>
      </calloutlist>
    </example>

    <para>
      Copy the example into your favorite text editor and save it as <filename>SimpleTest.java</filename>.  Now we want to try this test out, there are three possible user interfaces for the JUnit TestRunner:
    </para>

    <itemizedlist>
      <listitem>
        <para>
          <emphasis>TextUI</emphasis>: Provides text-based output to stdout.
        </para>
      </listitem>   

      <listitem>
        <para>
          <emphasis>AwtUI</emphasis>: Provides <acronym>GUI</acronym>-based output using the <acronym>AWT</acronym>
          (Abstract Window Toolkit) from Java.
       </para>
      </listitem>   

      <listitem>
        <para>  
          <emphasis>SwingUI</emphasis>: Provides <acronym>GUI</acronym>-based output using the Swing graphical user
          interface component kit from Java.
        </para>
      </listitem>
    </itemizedlist>
          
    <para>To select an interface execute the following command sequence.</para> 

    <screen><userinput><command>java</command> junit.<replaceable>USERINTERFACE</replaceable>.TextRunner <replaceable>classfile</replaceable></userinput></screen>

    <para>
      For example if we wanted text based output for our TestCase we would issue the command sequence:
    </para>

    <screen><userinput><command>java</command> junit.textui.TestRunner <filename>SimpleTest</filename></userinput></screen>

    <para>
      Compile the file and then try this, you should see some output similar to this:
    </para>

    <screen>
.
Time: 0

OK (1 tests)
    </screen>

    <para>
      Indicating that our quite obviously correct test has been passed, well more correctly that no failures have occurred.  Change the value of <emphasis>answer</emphasis> in the example to something other than 2, recompile the file and run the test again, you should see output similar to this.
    </para>

    <screen>
.F
Time: 0.01
There was 1 failure:
1) testSimpleText(SimpleTest)junit.framework.AssertionFailedError: expected:&lt;2&gt; but was:&lt;3&gt;
        at SimpleTest.testSimpleTest(SimpleTest.java:9)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

FAILURES!!!
Tests run: 1, Failure: 1, Errors: 0
    </screen>

    <para>
      If this was a real program we would now go and try and fix the error and then recompile and retest and so on until we eventually fixed the error.  You should now begin to have an idea of how to go about setting up a simple test.  </para>
  </sect1>

  <sect1 id="JUnit-Intermediate"><title>Intermediate Example</title>
    <para>
      The last section was just a quick taster of and a gentle introduction to JUnit, this section will explore a more advanced example.
    </para>

    <programlisting>
// A Class that adds up a string based on the ASCII values of its
// characters and then returns the binary representation of the sum.
public class BinString {
  public  BinString() {}

   public String convert(String s) {
      return binarise(sum(s));
   }

   public int sum(String s) {
      if(s==&quot;&quot;) return 0;
      if(s.length()==1) return ((int)(s.charAt(0)));
      return ((int)(s.charAt(0)))+sum(s.substring(1));
   }

   public String binarise(int x) {
      if(x==0) return &quot;&quot;;
      if(x%2==1) return &quot;1&quot;+binarise(x/2); 
      return &quot;0&quot;+binarise(x/2); 
   }
}        
    </programlisting>

    <para>
      Copy the above code into your favorite text editor and save as <filename>BinString.java</filename>, all this program does is convert an ASCII string to the sum of it's characters represented as a Binary string, the reason I chose those type of functions were arbitrary but I wanted to illustrate the testing of a program with auxiliary methods. Copy the test code below into your favorite editor and save as <filename>BinStringTest.java</filename>.
    </para>

    <programlisting>
import junit.framework.*;
public class BinStringTest extends TestCase {
   private BinString binString;

   public BinStringTest(String name) {
      super(name);
   }

   protected void setUp() { <co id="JUnit-Intermediate-SetUp"/>
      binString = new BinString();
   }

   public void testSumFunction() { <co id="JUnit-Intermediate-testSum"/>
      int expected = 0;
      assertEquals(expected, binString.sum(&quot;&quot;));
      expected = 100;
      assertEquals(expected, binString.sum(&quot;d&quot;));
      expected = 265;
      assertEquals(expected, binString.sum(&quot;Add&quot;));
   }

   public void testBinariseFunction() { <co id="JUnit-Intermediate-TestBin"/>
      String expected = &quot;101&quot;;
      assertEquals(expected, binString.binarise(5));
      expected = &quot;11111100&quot;;
      assertEquals(expected, binString.binarise(252));
   }

   public void testTotalConversion() { <co id="JUnit-Intermediate-TestAll"/>
     String expected = &quot;1000001&quot;;
     assertEquals(expected, binString.convert(&quot;A&quot;));
   }
}      
    </programlisting>

    <calloutlist>
      <callout arearefs="JUnit-Intermediate-SetUp">
        <para/>
        <programlisting>
protected void setUp() {
   binString = new BinString();
}
        </programlisting>
        <para>
          TestCase allows us to use the method <emphasis>setUp</emphasis> to set up any necessary variables or objects.  Note that <emphasis>binString</emphasis> was already declared at the top of the file like usual with <emphasis role="strong">private Binstring binstring;</emphasis>.  <emphasis>setUp</emphasis> is called before the evaluation of each test, <emphasis>setUp</emphasis> has a brother called <emphasis>tearDown</emphasis> which is called after the evaluation of each test and can be used to dereference variables or whatever so that each test may be performed without issuing side-effects that may affect the outcome of the other tests.
        </para>
      </callout>

      <callout arearefs="JUnit-Intermediate-testSum">
        <para/>
        <programlisting>
public void testSumFunction() {
   int expected = 0;
   assertEquals(expected, binString.sum(&quot;&quot;));
   expected = 100;
   assertEquals(expected, binString.sum(&quot;d&quot;));
   expected = 265;
   assertEquals(expected, binString.sum(&quot;Add&quot;));
}
        </programlisting>
        <para>
          Here we are testing the auxiliary function <emphasis>sum</emphasis> from our example file.
        </para>
      </callout>

      <callout arearefs="JUnit-Intermediate-TestBin">
        <para/>
        <programlisting>
public void testBinariseFunction() {
   String expected = &quot;101&quot;;
   assertEquals(expected, binString.binarise(5));
   expected = &quot;11111100&quot;;
   assertEquals(expected, binString.binarise(252));
}
        </programlisting>
        <para>
          Here we are testing the auxiliary function <emphasis>binarise</emphasis> which converts an 
          <emphasis>int</emphasis> to a binary String.
        </para>
      </callout>

      <callout arearefs="JUnit-Intermediate-TestAll">
        <para/>
        <programlisting>
public void testTotalConversion() {
  String expected = &quot;1000001&quot;;
  assertEquals(expected, binString.convert(&quot;A&quot;));
}
        </programlisting>
        <para>
          Here we are testing the <emphasis>convert</emphasis> function which calls the auxiliary methods to perform the conversion from String to integer to binary string.
        </para>
      </callout>
    </calloutlist>

    <para>Compile both these files and then run the tester on the TestCase by executing the following command sequence:</para>

    <screen><userinput><command>java</command> junit.textui.TestRunner <filename>BinStringTest</filename></userinput></screen>

    <para>This will produce the following errors:</para>

    <screen>
..F.
Time: 0.01
There was 1 failure:
1) testBinariseFunction(BinStringTest)junit.framework.AssertionFailedError: expected:&lt;11111100&gt; but was:&lt;00111111&gt;
 at BinStringTest.testBinariseFunction(BinStringTest.java:26)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

FAILURES!!!
Tests run: 3,  Failures: 1,  Errors: 0
    </screen>

    <para>
      This tells us that there was an error in the Binarise function and it even tells us the actual result compared to the expected result, a quick glance shows that the binary string has been output in reverse so we fix this by changing the <emphasis>binarise</emphasis> method in the file <filename>BinString.java</filename> to:
    </para>

    <programlisting>
public String binarise(int x) {
   if(x==0) return &quot;&quot;;
   if(x%2==1) return binarise(x/2)+&quot;1&quot;; 
   return binarise(x/2)+&quot;0&quot;; 
}
    </programlisting>

    <para>Recompile this and execute the test again and you will see:</para>

    <screen>
...
Time: 0.01

OK (3 tests)
    </screen> 

    <para>
      Which indicates that everything went fine.  Try this, comment out this line in the <filename>BinString.java</filename> file:
    </para>

    <programlisting>
if(s.length()==1) return ((int)(s.charAt(0)));
    </programlisting>

    <para>Recompile the file and execute the test again, you will see:</para>

    <screen>
.E..E
Time: 0.01
There were 2 errors:
1) testSumFunction(BinStringTest)
java.lang.StringIndexOutOfBoundsException: String index out of range: 0
 at java.lang.String.charAt(String.java:455)
 at BinString.sum(BinString.java:13)
 at BinString.sum(BinString.java:13)
 at BinStringTest.testSumFunction(BinStringTest.java:17)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
2) testTotalConversion(BinStringTest)
java.lang.StringIndexOutOfBoundsException: String index out of range: 0
 at java.lang.String.charAt(String.java:455)
 at BinString.sum(BinString.java:13)
 at BinString.sum(BinString.java:13)
 at BinString.convert(BinString.java:7)
 at BinStringTest.testTotalConversion(BinStringTest.java:31)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

FAILURES!!!
Tests run: 3,  Failures: 0,  Errors: 2
    </screen>

    <para>
      Notice that there were no failures but the test still failed, this is because there was errors, errors are caused by completely unexpected occurrences, such as exceptions as indicated by the error messages displayed.  Whenever an assertion such as an <emphasis>assertEquals</emphasis> fails it will throw a AssertionFailedError which is caught by the JUnit framework.  Sometimes you may need to test that a certain input produces an exception, for example, we may have a String manipulation method which should throw some defined exception if passed an empty string.  We could use the following to test that it does so:
    </para>


    <programlisting>
try {
   stringmanipulationmethod(&quot;&quot;);
   fail(&quot;Should raise a someDefinedException exception here&quot;);
} catch(somedefinedException e) {
   // successful test
}
    </programlisting>

    <para>
      If the string manipulation method did not throw the exception then program control would be directed to the fail statement and we would get an informative message upon executing the test unit.
    </para>
  </sect1>

  <sect1 id="References"><title>References</title>
    <itemizedlist>
      <listitem>
        <para><ulink url="http://members.pingnet.ch/gamma/junit.htm">http://members.pingnet.ch/gamma/junit.htm</ulink></para>

        <para>
	         <literallayout>
Test Infected:  
Programmers Love Writing Tests     

Kent Beck, CSLife 
Erich Gamma, OTI Zurich 
          </literallayout>
	       </para>
      </listitem>

      <listitem>
        <para><ulink url="http://junit.sourceforge.net/doc/cookbook/cookbook.htm">http://junit.sourceforge.net/doc/cookbook/cookbook.htm</ulink></para>

        <para>
	         <literallayout>
JUnit Cookbook
Kent Beck, Erich Gamma
          </literallayout>
	       </para>
      </listitem>

      <listitem>
        <para><ulink url="http://junit.sourceforge.net/doc/cookstour/cookstour.htm">http://junit.sourceforge.net/doc/cookstour/cookstour.htm</ulink></para>

        <para>
	         <literallayout>
JUnit A Cook's Tour
Erich Gamma, Kent Beck
          </literallayout>
	       </para>
      </listitem>
    </itemizedlist>
  </sect1>
</article>

