« When To Use a Record-Playback Tool | Main | Abstractions in Test Code »

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 March 5, 2005 12:15 PM

Comments

I wish more people would get right to the point, instead of the usual endless blablabla. Nothing is refreshing like seeing an example and steps how to work something.

A high level JUnit question: Why would I use a frame work to have it call my testing function in some overglorified way, when instead I can simply have a public static void main that calls it instead?

Posted by: Mike at March 18, 2005 03:17 PM

An excellent question, Mike. Technically, you can do everything JUnit does in a public static main method. But you would have to implement the following functionality yourself: a) the assertion methods (automatically check for values and if they aren't as expected, throw an exception) b)
collecting test failures c) grouping of tests into test suites d) grouping of tests suites into a master test suite e) running tests with Ant's task f) generating HTML reports with Ant's task.

Also, you'd be grouping your test code right into your core application code which in my mind makes the application code harder to maintain. What you'll find as you develop your JUnit tests is that you'll need to have test helper classes and make use of design patterns just like you would in application code. All of this "test infrastructure" can be better maintained if using a separate tool/framework than mixing it in into the application code.

Posted by: Misha Rybalov at June 3, 2005 06:17 PM

thats what i was looking for on the internet!
Thanks

Posted by: Karthik at November 29, 2005 09:53 PM

Post a comment




Remember Me?