« February 2005 | Main | June 2005 »

March 05, 2005

JUnit "Quick and Dirty" Tutorial

For those that want to get started with JUnit quickly and prefer a "just the facts" type of tutorial, I've create the following JUnit Quick and Dirty Tutorial. This tutorial assumes you are already familiar with Java programming, so the junit.jar should be in your classpath and you should have a development environment all setup for compiling and running Java code.

Preparing a JUnit test class

1. create a blank Java file (e.g. FooTest.java)

2. import the following classes:
junit.framework.Test
junit.framework.TestCase
junit.framework.TestSuite

3. create a class that extends from TestCase (e.g. public class FooTest extends TestCase)

4. create a public constructor that takes a string argument called name

e.g. public FooTest(String name) { super(name); }

5. create a public static suite() method that tells JUnit which test cases to run. The easy way to do this is to pass the class instance of your class and let JUnit dynamically figure out which tests to run. It does this by reflecting on your test class (FooTest.class) and looking for all public methods that return void and start with "test".

e.g. public static Test suite() { return new TestSuite(FooTest.class); }

This is all that's required to setup your class for JUnit tests. Now you're ready to actually write some tests.

Writing a JUnit test

1. For every test you'd like to run, create a public method that returns void, takes no arguments and starts with "test"
e.g. public void testBar() { ... }

2. Instantiate the object you'd like to test inside the test method from the previous step.

Foo foo = new Foo();

3. Invoke the method(s) you'd like to test and assign the return values to local variables.

e.g. int actualValue = foo.bar(1, 2, 3);

4. Check the method's return value by using one of JUnit's assert methods. You'll be using methods inside junit.framework.TestCase since you inherited from it. You can get a list of all the assert methods from the JUnit JavaDocs.

e.g. assertEquals(4, actualValue);

Initializing and De-initializing Tests

Often, you'll need to initialize or de-initialize a group of tests in the same way. For example if all your tests had to start with the same object creation, you can place that common initialization code into a special JUnit method called setUp(). Similarly, if all your tests had to do the same de-initializing steps, that code can be placed into a tearDown() method.

Your test methods would then not have to perform those common steps anymore and could start with the "meat" of their testing.

These methods are protected and take no arguments, so if you don't have any use for them, don't include them and by default they will do nothing.

e.g.
//foo variable should be declared as an instance of the test class
protected void setUp() { foo = new Foo(); }
protected void tearDown() { foo.cleanUp(); }

Rules of Thumb

These are general guidelines to keep in mind as you're creating more tests with JUnit.

1. Create a single test class for each application class you have.

2. Name each test class the same name as the application class its testing but with "Test" appended to the end. So if you have an application class called "ShoppingCart.java" the test class would be called "ShoppingCartTest.java"

3. Give meaningful names to each test method. I usually name the test method the same name as the method that its testing with some additional info appended to the name. For instance if I'm testing a method called "add" in my ShoppingCart class, I'll create a few test methods to test different ways of adding to a shopping cart:

4. The scope of how much checking to do in a single test case (test method) is a judgement call. I usually stick to a single method call with a single set of arguments, but you can stuff a single test case with multiple method calls and assertion checks. In the example above, that would mean creating a single testAdd() method and testing adding a single product, multiple products, invalid product and null all in one test method.

Posted by Misha Rybalov at 12:15 PM | Comments (3)