Welcome!

Java Authors: Jason Dolinger, Miko Matsumura, Walter H. Pinson, III, Liz McMillan, Maureen O'Gara

Related Topics: Java

Java: Article

Generating JUnit Tests for Legacy Java Applications

How to maintain apps you didn't write

An excellent way to explore an unfamiliar application is to create unit tests. Tests not only alert us when something is wrong; tests demonstrate how the code actually works. Of course, creating unit tests for existing code isn't trivial, especially when it comes to code we didn't write.

A case in point is the Spring JPetStore. JPetStore is a production-quality rendition of Sun's infamous PetStore application, originally created by Clinton Begin to showcase using iBATIS with Struts. The Spring rendition added a Spring MVC implementation and refactored the business layer for Spring. Surprisingly, the Spring JPetStore doesn't include a suite of unit tests against the business logic. The Spring JPetStore welcome page is shown in Figure 1.

We'd like to bring the Spring JPetstore up-to-date with the latest version of iBATIS and add a Struts 2 implementation. But before starting on that, we'd like to add a set of unit tests for the back-end. With a good set of tests on board, we can make changes and not worry that something will break without notice. Kent Beck, widely recognized as the father of eXtreme Programming and JUnit, tells us that we should "test until fear turns to boredom." Good advice, but being lazy, we'd rather not create all the tests by hand.

Avoid Drudgery with Generated JUnit Tests
JUnit Factory (www.junitfactory.com, shown in Figure 2) is a free test generation service offered by Agitar Software that can generate tests by analyzing source code. JUnit Factory is powered by the same technology that's behind AgitarOne, Agitar's comprehensive, server-based unit testing solution for Java.

We can submit code to the JUnit Factory service with either a Web browser or an Eclipse plug-in. JUnit Factory analyzes the code and generates unit tests based on how the code behaves.

In this article, we'll use JUnit Factory to create a suite of standard JUnit tests for the Spring JPetstore business layer, so that we can refactor or extend the business logic with confidence. As we change the JPetStore code, we'll run the tests to see whether we have broken any of the code's existing behavior. As we go along, we can update the tests by hand, generate new tests, or both.

Say Hello To Generated JUnit Tests
Before we study the JUnit tests for JPetStore, let's take a look at the JUnit tests generated for two simple examples. Of course, the first example is "Hello World!" shown in Listing 1.

A reasonable unit test for HelloWorld, as generated by JUnit Factory, is show in Listing 2.

Nothing fancy, but it shows us exactly what the application does: it says Hello World!

From now on, whenever we change the HelloWorld class, we can run testSayHello() to see if anything breaks. If a test does fail, it's a signal that a method doesn't work the same way anymore. Sometimes, a failing test means that our change had unexpected consequences and by fixing one bug we've accidentally created another. (So, it's back to the drawing board!)

Other times, a failing test means that we've changed our expectations of how the code should behave, and the failing test is now obsolete. With conventional JUnit tests, an API change means we have to update any outdated tests. With a tool like JUnit Factory, instead of rewriting obsolete characterization tests, we can regenerate those tests instead, and create a new baseline.

What about something a little more challenging like the calculation of a leap year shown in Listing 3?

Given a method with various output possibilities, JUnit Factory will generate a set of unit tests such as those shown in Listing 4.

To do unit testing right we need a lot of tests - more tests than most of us would like to write. Along with the main "success" path, we should also check boundary and edge conditions: what happens if the year is zero, or if the year is divisible by 4, or if the year is exactly 4, and so on.

In Listing 4, we can see that JUnit Factory was able to generate a decent array of tests for the LeapYear class - again far more unit tests than most of us would have the patience to devise and code, especially for code we didn't write ourselves.

Agitar calls the tests it generates "characterization tests" to emphasize that these JUnit tests reflect what the code actually does.

The generated tests always work if you run them against the original code under test. When run as regression tests, characterization tests serve as API change detectors: if we change an application and find that one or more characterization tests fail then we should consider the change "on notice." We might need to rework the change, or we may have to regenerate the tests. But, either way, characterization tests red-flag changes in public behavior.

Generate JUnit Tests for JPetStore
The JUnit Factory site is fun, but it only works with classes that have no dependencies. To generate tests for an entire application such as JPetStore, we need to use the JUnit Factory Eclipse plug-in, which is also free.

JPetStore is a shopping cart application. Visitors can browse our inventory, add items to a virtual shopping cart, and place an order for the items when ready.

To generate tests for JPetStore, we should first isolate which classes we'd like to test. Unit testing is best suited to plain Java objects that handle business logic. Other objects, including data access objects, can be tested too, but that requires more setup.

Like many applications, the core of JPetStore is represented as a set of business objects that represent entities in the problem domain. In our case, the business entities are client accounts, inventory products, product categories, inventory items, shopping carts, sale orders, and sale items. The JPetStore business objects are conveniently gathered into a package named domain.

Let's say that we've installed the JUnit Factory plug-in and created a Java project. To generate characterization tests, all we have to do is right-click in Eclipse's Package Explorer view then select Agitar/Generate Tests. The plug-in submits the classes to the JUnit Factory Web site and within a few minutes the JUnit Factory will generate and return over 100 tests, organized in separate test suites for each of the eight classes.


About Ted Husted

Ted Husted (http://husted.com/ted/) is a software engineer and an active member of several open source projects hosted by the Apache Software Foundation, including Struts and iBATIS. His books include JUnit in Action, Struts in Action, and Professional JSP Site Design. Ted is also a consultant for Agitar Software, Inc.

Comments (1) View Comments

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


Most Recent Comments
Alexander Klimuk 01/14/08 06:37:02 PM EST

This article resembles the video of Alberto Savoia from Agitar, which is available as of Sep 2007 at 'theserverside.com':
http://www.theserverside.com/news/thread.tss?thread_id=46931#239986

Well, a bit different wording, and that's all.

Why haven't you just placed a link to that video and discussion on TSS site?

Regards,
Alexander Klimuk