February 29, 2020
Hot Topics:

Writing a Simple Automated Test in FitNesse

  • By Jeff Langr
  • Send Email »
  • More Articles »

Each column header in the fixture must map to a public method in BookRules. FitNesse concatenates words in the column header name, appropriately adjusting capitalization to meet Java camel case naming conventions. For example, the column header "daily fine" maps to the query method dailyFine().

The one line of code within dailyFine() interacts with code in the library system. Here, you're testing Java classes directly, but fixture code might also access a system through an interface layer such as a web service.

Now, try out the test. You click the Test button located in the left-hand margin. The results are shown in Figure 1. (If you see yellow, something is configured improperly. Double-check your path statements. Refer to the FitNesse online user's guide. Send me an email. Or post a message to the FitNesse Yahoo! group.)

Click here for a larger image.

Figure 1. FitNesse execution.

The green cells indicate that an expected cell value matched what the fixture code actually returned. The red cell beneath the column header checkout period? indicates an error—the test expected 20, but the system returned 21. You know the system is right in this case, so you edit the FitNesse page and change 20 to 21. You rerun the test by clicking the Test button. You see all green, and a summary showing "Assertions: 3 right, 0 wrong, 0 ignored, 0 exceptions."

Take a quick look at an additional fixture, one that can verify the late fine calculations. You'll create a test table to use a new fixture named fixtures.CheckinBook, You edit the test page, updating its contents to look like Listing 4.

Listing 4. An additional fixture.

!path c:Fitnessefitnesse.jar
!path C:Documents and SettingsjlangrMy Documentsworkspace
!path C:Documents and SettingsjlangrMy Documentsworkspace

|daily fine?|grace period?|checkout period?|

|checkout date|due date?|checkin date|daysLate?|fine?|

The new table verifies the due date, days late, and fine amount for a book, given its checkout date and return date. Note that two of the column headers, checkout date and checkin date don't end with a ?. They're not queries; they instead represent input data elements. FitNesse uses data in these "setter" columns to initialize a public field in the fixture.

The fixtures.CheckinBook table in listing 4 contains five data rows that cover a number of data scenarios. When you click the Test button, FitNesse calls out to the fixture five times, once for each row in the table. For each row, FitNesse first initializes public fields in the corresponding fixture using each of the setter columns. For example, FitNesse sets the public field checkoutDate to the value 12/1/2006 for each row in the table. Once all setters execute, FitNesse executes each of the query methods.

The corresponding fixture code appears in Listing 5.

Listing 5. fixtures.CheckinBook.

package fixtures;

import java.util.*;

import com.langrsoft.app.*;

import fit.*;

public class CheckinBook extends ColumnFixture {
   public Date checkoutDate;
   public Date checkinDate;

   public Date dueDate() {
      Checkout checkout = new Checkout(new Book(), checkoutDate);
      return checkout.getDueDate();

   public int daysLate() {
      Checkout checkout = new Checkout(new Book(), checkoutDate);
      return checkout.daysLate();

   public int fine() {
      Checkout checkout = new Checkout(new Book(), checkoutDate);
      return checkout.amountToFine();

For each query method that executes, remember that FitNesse has already populated the public fields checkoutDate and checkinDate.

You run the test page to ensure everything passes.

As a programmer, you might balk at the design of the fixture. The fixture code creates a checkout object and calls its returnOn method three separate times, once for each of the three query methods. That's not very efficient!

The important point is that the test tables are an expression of the requirements of the system. They might not represent how you think users should interact with the system. Yet, that's how the customer who designed the test tables wants to think about things.

The test tables are your focal point for future negotiation. You can center debate and discussion around these tables. You might get the customer to agree to split the fixtures.CheckinBook table into two. Or, you might realize that you need to redesign the APIs into the system. Even better, going forward, you can consider that the FitNesse tests can help drive the development of the system.

You've just scratched the surface in terms of FitNesse capabilities. There are numerous fixture types, including a RowFixture type that allows you to verify collections of data. FitNesse also provides many ways to help make your tests more expressive. Read through the online users' guide and experiment with the FitNesse capabilities that it explains. You might also check out the book, Fit For Developing Software, by Rick Mugridge.

Download the Code

You can download the code that accompanies this article here.

About the Author

Jeff Langr is a veteran software developer with a score and more years of experience. He's authored two books and dozens of published articles on software development, including Agile Java: Crafting Code With Test-Driven Development (Prentice Hall) in 2005. You can find out more about Jeff at his site, http://langrsoft.com, or you can contact him directly at jeff@langrsoft.com.

Page 2 of 2

This article was originally published on December 15, 2006

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date