Junit - Getting started with an example Last update : 09/12/2002 back to HOME PAGE

Introduction

The goal of this article is getting started with Junit starting from a simple example.

Unit tests, integration tests and no regression tests take a large part in developer's life. Junit is an open source test framework which is using by java developer's community.

Contents :

  1. A simple example : description of class to test
  2. TestCase : description of unit test class
  3. Results of the test
  4. TestCase Generator : open source TestCase code generator and JBuilder 6 TestCase generator presentation
  5. Links
  6. Download source code
  7. Credits - about the author of this article and the license to respect if you want to use the code

Why using a test framework ?

This chapter contains some extracts from article Programmers Love Writing Tests.

Every programmer knows they should write tests for their code. Few do.

The universal response to "Why not?" is "I'm in too much of a hurry." This quickly becomes a vicious cycle- the more pressure you feel, the fewer tests you write. The fewer tests you write, the less productive you are and the less stable your code becomes. The less productive and accurate you are, the more pressure you feel.

Using a test framework is asking a remarkably small investment and will make you a faster, more productive, more predictable, and less stressed developer.

Here are a couple of the times that you will receive a reasonable return on your testing investment:

Then debug until the test succeeds. You will be able to refactor much more aggressively once you have the tests. You won't understand at first just how much you can do, though. Try to catch yourself saying, "Oh, I see, I should have designed this thus and so. I can't change it now. I don't want to break anything." When you say this, save a copy of your current code and give yourself a couple of hours to clean up. Make your changes, all the while running your tests.

You will be surprised at how much ground you can cover in a couple of hours if you aren't worrying every second about what you might be breaking.

Another very good article introducing Junit is here : Junit Primer by Dave Clark.

 


back to Top
1. A simple example

Here is a simple class with public methods we want to test using Junit :

public class Foo { 

 

	private int[] array; 

 

    public Foo(int size) { 

	    array= new int[size]; 

	} 

 

	public String getHelloWorld() { 

		return  "Hello World"; 

	} 

 

	public boolean getTruth() { 

	    return true; 

	} 

 

	public void setElement(int position, int value) throws ArrayIndexOutOfBoundsException { 

		array[position] = value; 

	} 

 

	public int getElement(int position) throws ArrayIndexOutOfBoundsException { 

	    return array[position]; 

	} 

}

How do you used to write testing code?

The simplest way is as an expression in a debugger. You can change debug expressions without recompiling, and you can wait to decide what to write until you have seen the running objects. You can also write test expressions as statements which print to the standard output stream. Both styles of tests are limited because they require human judgment to analyze their results. Also, they don't compose nicely- you can only execute one debug expression at a time and a program with too many print statements causes the dreaded "Scroll Blindness".

Using Junit, you won't "pollute" the source code because test code is separated from Business classes.

JUnit tests do not require human judgment to interpret, and it is easy to run many of them at the same time. When you need to test something, you create an instance of TestCase .

back to Top

2 TestCase




import junit.framework.*; 

import junit.textui.*; 

 

public class TestFoo extends TestCase { 

 

	// Foo instance used for tests 

	protected Foo Foo; 

	protected int testSize; 

 

	// standard constructor 

    public TestFoo(String name) { 

        super(name); 

	} 

 

   /** 

    * This method is called every time before particular test execution. 

    * It creates new instance of tested class and it can perform some more 

    * actions which are necessary for tests. 

    */ 

    protected void setUp(){ 

		testSize = 3; 

        Foo = new Foo(testSize); 

	} 

 

	/** 

	 * test original method getHelloWorld, example of Assert.assertEquals 

	 */ 

	public void testGetHelloWorld() { 

		System.out.println("testGetHelloWorld"); 

 

		/* This test code makes use of assertEquals - one of a number of 

		assertion methods provided by the JUnit interface Assert. 

		There are overloaded variants of assertEquals to deal with various types 

		of parameter, including the base types, containers, and Strings 

		- if the two parameters are equals then it simply returns, otherwise it 

		throws an unchecked exception used within the framework to report on the error. */ 

 

		// as the method returns "Hello World", the test should fail 

		String result = "Hello world"; 

        Assert.assertEquals(result, Foo.getHelloWorld()); 

    } 

 

	/** 

	 * test original method getTruth, example of Assert.assertTrue 

	 */ 

	public void testGetTruth() { 

        System.out.println("testGetTruth"); 

		/* assertTrue checks if its parameter equals true, otherwise it throws 

		an unchecked exception used within the framework to report on the error */ 

		Assert.assertTrue(Foo.getTruth()); 

    } 

 

	/** 

	 * test original method setElement, example of Assert.fail 

	 */ 

	public void testSetElement() { 

		/* This test consists in checking that an exception is throwed in method getException 

		trying to access element at position "size" of an 

     array should throw an ArrayIndexOutOfBoundsException. 

		*/ 

	    try { 

		     System.out.print("testSetElement, exception throwed :   -->  "); 

			 Foo.setElement(testSize, 0); 

 

		     /*	if exception is not catched, line Assert.fail is executed : test fails */ 

	          Assert.fail("setElement should raise an Exception"); 

        } catch (Exception e) { System.out.println(e.toString()); } 

 

		// test with valid parameter (no exception supposed to be throwed) 

	    try { 

		     System.out.println("testSetElement, OK "); 

			 int position = testSize - 1; 

		     int result = 10; 

			 Foo.setElement(position, result); 

			 Assert.assertEquals(result, Foo.getElement(position)); 

 

        } catch (Exception e) { System.out.println(e.toString()); } 

 

	} 

 

	/** 

	 * test original method getElement : to do ! 

	 */ 

	public void testGetElement() { 

	} 

 

	/** 

    * Once you have several tests, use a Suite to organize them.

	* this method returns all tests which should be performed for testing class. 

    * By default it returns only name of testing class. Instance of this 

    * is then created with its constructor. 

    */ 

	public static Test suite() { 

		/* Junit uses reflexion to add automatically all the methods of TestFoo 

		whose name begins by "test" 

		*/ 

		return new TestSuite(TestFoo.class); 

    } 

 

	/** 

    * This main method is used for run tests for this class only 

    * from command line. 

    */ 

	public static void main(String[] args) { 

 

        /* to use command line interface  */ 

		junit.textui.TestRunner.run(suite()); 

 

		// to use GUI interface (no Suite paramater permitted) 

		//junit.swingui.TestRunner.run(TestFoo.class); 

 

    } // end of main(Stringp[] args) 

}
back to Top
3 Test results
Command line Interface Result :


 .testGetHelloWorld



F.testGetTruth



.testSetElement, exception throwed :   -->  java.lang.ArrayIndexOutOfBoundsException



testSetElement, OK 



.



Time: 0,015



There was 1 failure:



1) testGetHelloWorld(TestFoo)

junit.framework.AssertionFailedError: expected:<Hello world> but was:<Hello World>



	at TestFoo.testGetHelloWorld(TestFoo.java:42)



	at TestFoo.main(TestFoo.java:107)





FAILURES!!!



Tests run: 4,  Failures: 1,  Errors: 0



 

GUI Inteface Result :

back to Top

4 TestCase generator : unittestsgen by Artur Hefczyc

unittestsgen is a Test class code generator developed by Artur Hefczyc. It implements a task which allows use the generator from ANT and control test classes generating from build.xml file. You can download it at this url : http://sourceforge.net/projects/wttools/

How to use unittestgen

In MS Windows, the command line looks like this : D:\projects\yourproject> java -jar unittestsgen.jar -cp "yourjarfile.jar;junit.jar"

If you work with a war, you can download batches here.

Extract of FooTestcase generated by unittestgen :



/**

 * File FooTestCase.java is automaticaly generated by

 * 'unittestsgen' application. Code generator is created for java

 * sources and for 'junit' package by "Artur Hefczyc"

 * kobit@users.sourceforge.net
*/ public
class FooTestCase extends TestCase { /** * Instance of tested class. */ protected Foo varFoo; /** * Public constructor for creating testing class. */ public FooTestCase(String name) { super(name); } // end of FooTestCase(String name) /** * This main method is used for run tests for this class only * from command line. */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } // end of main(Stringp[] args) /** * This method is called every time before particular test execution. * It creates new instance of tested class and it can perform some more * actions which are necessary for performs tests. */ protected void setUp() { // Initialize your variable(s) here // for example: // varFoo = new Foo(...); // But note that there is no default constructor in Foo } // end of setUp() /** * Returns all tests which should be performed for testing class. * By default it returns only name of testing class. Instance of this * is then created with its constructor. */ public static Test suite() { return new TestSuite(FooTestCase.class); } // end of suite() /** * for classes which doesn't contain any methods here is one additional * method for performing test on such classes. */ public void testNoMethods() { } /** * Method for testing how works original method: * int getElement(int) * from tested class */ public void testGetElement104431() { /* No default constructor, code commented out... // Hint: in get/set pair 'get' method should _not_ have any parameters // and should return int as a value. // Warning in get/set methods pair 'set' method should have only one // parameter. The same type which is returned by corresponding get method. */ } // end of testGetElement104431(int) } // end of FooTestCase Using ant with unittestgen, build.xml script <project name="UnitTestsGen" default="dist" basedir=".">
<taskdef name="unitgen" classname="testsgen.taskant.UnitTestsGen"/>
<property name="src" value="src"/>
<property name="test-src" value="test-src"/>
<property name="build" value="build"/>

<target name="compile" description="Compile sources in ${tmpsrc} directory">
<mkdir dir="${build}"/>
<javac srcdir="${src};${test-src}" destdir="${build}"
debug="on" deprecation="off">
<classpath>
<pathelement location="${libs}/junit.jar"/>
</classpath>
</javac>
</target>
<target name="jar" depends="compile">
<jar jarfile="jar/${jarfile}.jar" manifest="MANIFEST.MF" basedir="${build}">
<exclude name="** /*TestCase*.*"/>
<exclude name="TestAll.*"/>
</jar>
<unitgen update="true" classpath="${build};${libs}/junit.jar"
imput="${src}" output="${test-src}"/>
</target>
</project>
back to Top
5 Links

Junit Home site, billions of links : http://www.junit.org/

Download the TestCase generator tool at http://sourceforge.net/projects/wttools/

Junit discussion group : http://groups.yahoo.com/group/junit/

Another article introducing Junit : Junit Primer

Jbuilder6 integrates Junit, an Javaworld article about what's new in JBuilder6 :
http://www.javaworld.com/javaworld/jw-01-2002/jw-0118-iw-jbuilder_p.html

IBM presents its Application Quality Assurance :

http://www7b.boulder.ibm.com/wsdd/library/presents/junit.html (contains pdf)

back to Top

6 Download

Download the examples and some batch files (for windows) to use unitestgen with a war.

back to Top

Credits

Author

I am an European software engineer who lives and works in London. For any comments / suggestions : send an e-mail to g a r n i e r j m @ y a h o o.f r (remove the spaces to get my e-mail, I have done that bc the sobig virus has filled my mailbox!)

Copyrights

The source is free to use and is available under the GNU GENERAL PUBLIC LICENSE.

back to Top