- Regression Tests
- Software Support for Regression Testing
- User Interface Testing
- Conclusion
Software Support for Regression Testing
It's imperative to automate as much of the regression testing process as you can. In theory, every changeno matter how smallrequires a complete repeat of every regression test you have, even for aspects of the system whose connection to the change doesn't seem relevant. I'd say that this is perhaps less critical in Java than in C or C++, where memory leaks in one unit can stomp on memory from absolutely any other unit, potentially causing errors in pieces of code far removed from the actual change. Even in Java, however, proper testing procedure requires that you rerun every test, no matter what change happens. Timing changes in threads and globally-shared objects and files can propagate effects from one unit to any other throughout the system.
TIP
Good programming habits can minimize the likelihood that rerunning the regression tests will actually find any errors, because good programming encourages errors to be detected locallybut bugs have a bad habit of not respecting good programming practice. If we were perfect programmers with perfect knowledge, we wouldn't have bugs in the first place, and regression tests would be unnecessary. Just because you're a great programmer, don't let the infrequency of errors lull you into believing that you can skip this step; the longer you wait, the harder the eventual error will hit you.
Regression testing can be incredibly tedious if you run tests by hand, but fortunately there are a variety of programs that help make regression testing nearly automatic. It's a lot easier to ensure that you actually run regression tests if they're easy to do.
The most important and well-known regression-testing support package for Java is JUnit. "Unit" refers to "unit testing," which allows each piece of software to be tested by itself (as opposed to system testing or testing at other scales). The great thing about JUnit is that it's freely available from SourceForge.
The basic element of JUnit is the junit.framework.TestCase. It uses Java reflection to run any methods beginning with the word test and reports any unexpected exceptions or failed assertions. Here's a trivial example:
import junit.framework.*; public class MyTest extends TestCase { /** There has to be a public constructor, and the class * must be public */ public MyTest() { } public void testDemo() { Assert.assertTrue(System.currentTimeMillis() > 0); } }
The Assert class contains a number of methods that look for some condition to holdsomething is true, something is false, two things are equal, etc. You run the class with a TestRunner (which comes in Swing, AWT, and plain text variants), like this:
java -classpath junit.jar;. junit.swingui.TestRunner MyTest
It constructs an instance of MyTest and then runs any methods beginning with test (with no arguments and void return). It pops up a status report like the one shown in Figure 1.
Figure 1 Status report.
A green bar is good; a red bar means that an assertion has failed or an exception was thrown from one of the test methods. The JUnit classes provide a lot of variants of TestCase and various support methods to make it easier to maintain the hundreds or thousands of test cases that a real project will have.
JUnit is very popular among Java programmerseven those not using the Extreme Programming methodology it's designed to support. JUnit requires you to use some of its classes, to which references remain even in production software. The TestCase classes usually exist in the same package as your regular code to be able to take advantage of non-public classes, fields, and methods, which need to be tested just as much as non-public ones do. That makes the TestCase classes hard to exclude from deliverable packages. You'll often see junit.jar delivered as part of the program even if you're a user, not a tester.