Unit Testing: Avoid the Need for Debuggers

Problem

You don’t want to have to debug your code.

Solution

Use unit testing to validate each class as you develop it.

Discussion

Stopping to use a debugger is time-consuming. Better to test beforehand. The methodology of unit testing has been around for a long time, but has been overshadowed by newer methodologies. Unit testing is a tried and true means of getting your code tested in small pieces. Typically, in an OO language like Java, unit testing is applied to individual classes, in contrast to “black box” testing where the entire application is tested.

I have long been an advocate of this very basic testing methodology. Indeed, developers of the software methodology known as Extreme Programming (XP for short; see http://www.extremeprogramming.org) advocate writing the unit tests before you write the code, and also advocate running your tests almost every time you compile. This group of extremists has some very well-known leaders, including Gamma and Beck of Design Patterns fame. While I am not yet ready to unconditionally endorse all aspects of Extreme Programming, I certainly go along with their advocacy of unit testing.

Indeed, many of my classes come with a “built-in” unit test. Classes that are not main programs in their own right often include a main method that just tests out the functionality of the class. Here is an example:

/** A simple class used to demonstrate unit testing. */
public class Person {
    protected String fullName;
    protected String firstName, lastName;

    /** Construct a Person using his/her first+last names. */
    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    /** Get the person's full name */
    public String getFullName(  ) {
        if (fullName != null)
            return fullName;
        return firstName + " " + lastName;
    }

    /** Simple test program. */
    public static void main(String[] argv) {
        Person p = new Person("Ian", "Darwin");
        String f = p.getFullName(  );
        if (!f.equals("Ian Darwin"))
            throw new IllegalStateException("Name concatenation broken");
        System.out.println("Fullname " + f + " looks good");
    }
}

What surprised me is that, before encountering XP, I used to think I did this often, but an actual inspection of two projects indicated that only about a third of my classes had test cases, either inside or externally. Clearly what is needed is a uniform methodology. That is provided by JUnit.

JUnit is a Java-centric methodology for providing test cases. You can freely download JUnit from the obvious web site, http://www.junit.org. JUnit is a very simple but useful testing tool. It is easy to use; you just write a test class that has a series of methods whose names begin with test. JUnit uses introspection (see Chapter 25) to find all these methods, and runs them for you! There are extensions to JUnit for purposes as diverse as load testing and testing Enterprise JavaBeans (EJB); there are links to these on the JUnit web site.

How do you get started using JUnit? All that’s necessary is to write a test. Here I have excerpted the test from my Person class and placed it into a class PersonTest . Note the obvious naming pattern.

import junit.framework.*;

/** A simple test case for Person */
public class PersonTest extends TestCase {

    /** JUnit test classes require this constructor */
    public PersonTest(String name) {
        super(name);
    }

    public void testNameConcat(  ) {
        Person p = new Person("Ian", "Darwin");
        String f = p.getFullName(  );
        assertEquals(f, "Ian Darwin");
    }

}

To run it, I need only compile the test and invoke the test harness junit:

daroad.darwinsys.com$ jikes PersonTest.java
daroad.darwinsys.com$ java junit.textui.TestRunner PersonTest
.
Time: 0.188
 
OK (1 tests)
 
daroad.darwinsys.com$

The use of a full class name is a bit tedious, so I have a script named jtest that invokes this; I just say jtest Person and it runs the previous command for me.

#!/bin/sh

exec java junit.textui.TestRunner ${1}Test

See Also

If you prefer flashier GUI output, there are several JUnit variants (built using Swing and AWT; see Chapter 13) that will run the tests with a GUI.

JUnit offers classes for building comprehensive test suites and comes with considerable documentation of its own; download the program from the web site listed earlier.

Also, for testing graphical components, I have developed a simple component tester; it is described in Section 12.3.

Remember: Test early, test often!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.14.252.56