Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Efficient Test-Driven Design with Unitils

Unitils is an open source testing framework for Java that dramatically reduces boilerplate test code. Test-driven design is a test-first methodology that uses programmatic tests as design tools. Find out how to realize the benefits of test-driven design using Unitils.

ver feel uncertain about exactly what the class you're implementing needs to do? Of course you probably have some idea of what it's responsible for, enabling you to:
  • Sketch out some message flows in UML, and derive an interface for the class
  • Comment the interface with descriptions of what the individual methods will do
  • Use inline documentation like Javadoc to describe the preconditions, parameters, return values, and post conditions for each method

While these are good starting points for a class design, they're more like vague promises than a real contract. Enter test-driven design (TDD).

TDD is the practice of using programmatic tests as design tools in addition to their traditional roles of providing regression coverage and defect containment. It's a test-first methodology, which means that you write test code before implementation code instead of after. By writing your production code against a test, your ability to refactor and isolate bugs is better than with the traditional test-after approach, because tests act as an executable specification rather than just an ad-hoc verification of certain behavior.

This article shows you how to bring clarity to your class designs using Unitils, an efficient open source testing framework for Java. Unitils dramatically reduces boilerplate test code through its integration of packages such as JUnit, EasyMock, and DBUnit, which happen to be especially useful for test-driven design. It also provides some tools of its own, which this article also introduces.

The Application Example
As a demonstration of Unitils, the example in this section builds part of an HR application that manages employee salaries for a client who, being aware of the occasional bump in the baseline salaries for certain professions, wants to remain a competitive employer. So one of the use cases is "Raise Salaries to Baseline," in which an HR representative picks a job title and enters a new baseline salary.

The remainder of this section walks through the development process for the HR application and highlights interesting portions of the code. To get started, download the accompanying project example (in Eclipse), which contains data and domain layers for the application. Be sure to follow along in the example project code, because the discussion omits many of its details for brevity. (See Figure 1 for a diagram of where you'll find the sample project files discussed.)

Click to enlarge

Figure 1. Project Example Directory Structure

You can use Maven to generate an identical Eclipse project for this example if you choose.

To complete the use case you need only one entity bean: Employee, a simple data object class. The application needs a way to persist Employee instances, which is a good starting point for the design. This example uses the standard Data Access Object pattern. The use case requires the ability to retrieve employees by job title and then save them after adjusting salaries. You can express those requirements with the following interface (only partially reproduced):

public interface IEmployeeDao { public List<Employee> findEmployeesByTitle(String title) throws DataAccessException; public void saveEmployees(List<Employee> employees) throws DataAccessException;

This interface is a good start, but you should specify exactly what you expect its implementers to do. You want findEmployeesByTitle to return a list of employees with a given title from the database, so create a sample dataset from which to select (if this seems an overly verbose approach, see Sidebar 1). Here's an example from EmployeeDaoTest.findsForTitleOnly.xml:

<dataset> <employees id="100" title="Software Engineer"/> <employees title="Account Executive"/> <employees title="Sales Manager"/> <employees id="103” title="Software Engineer"/> <employees title="Chief Executive Officer"/> </dataset>

Notice how the dataset includes values only for columns relevant to the behavior you want to test, in this case job titles. It also includes IDs only for the records you want to verify were retrieved. Unitils enables this function by helpfully stripping NOT NULL constraints from the test database before loading datasets. This approach makes your test code resilient to future changes in the database schema that aren't relevant to the behavior you're specifying.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.