JUnit best practices
Techniques for building resilient, relocatable, multithreaded JUnit tests
By and Andy Schneider, JavaWorld.com, 12/21/00
Page 4 of 5
Swing
When testing a Swing-based UI, you can write tests to ensure that:
- All the components reside in the correct panels
- You've configured the layout managers correctly
- Text widgets have the correct fonts
A more thorough treatment of this can be found in the worked example of testing a GUI, referenced in theResourcessection.
XML
When testing classes that process XML, it pays to write a routine that compares two XML DOMs for equality. You can then programmatically define the correct DOM in advance and compare it with the actual output from your processing methods.
Servlets
With servlets, a couple of approaches can work. You can write a dummy servlet framework and preconfigure it during a test. The framework must contain derivations of classes found in the normal servlet environment. These derivations should allow you to preconfigure their responses to method calls from the servlet.
For example:
HttpServletRequest
can be subclassed to allow the test class to specify the header, method, path info, and other dataHttpServletResponse
can be subclassed to return an output stream that stores the servlets' responses in a string for later checking
A simpler solution is to useHttpUnit
to test your servlets.HttpUnit
provides a DOM view of a request's results, which makes it relatively simple to compare actual data with expected results.
You can avoid visual inspection in many ways. However, sometimes it is more cost-effective to use visual inspection or a more specialized testing tool. For example, testing a UI's dynamic behavīor within JUnit is complicated, but possible. It may be a better idea to purchase one of the many UI record/playback testing tools available, or to perform some visual inspection as part of testing. However, that doesn't mean the general rule -- don't visually inspect -- should be ignored.
Keep tests small and fast
Executing every test for the entire system shouldn't take hours. Indeed, developers will more consistently run tests that execute quickly. Without regularly running the full set of tests, it will be difficult to validate the entire system when changes are made. Errors will start to creep back in, and the benefits of unit testing will be lost. This means stress tests and load tests for single classes or small frameworks of classes shouldn't be run as part of the unit test suite; they should be executed separately.
Use the reflection-driven JUnit API
AllowingTestSuite
to populate itself with test cases using reflection reduces maintenance time. Reflection ensures that you don't need to update thesuite()
implementation whenever a new test is added.
Build a test case for the entire system
It is important to build a test case for the entire system. If one test case exercises the whole system, then developers can test the impact their changes will have on every class in the system. This increases the chance of errors resulting from unanticipated side effects being caught earlier. Without a universal test case, developers tend to test only the class they have modified. Also, running all the tests for the system becomes a painstaking manual process. (Continued)