Login | Register   
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Apply Fit and FitNesse to Run Web-Based Acceptance Tests  : Page 4

Discover how to create a suite of automated acceptance tests that your entire development team can share and maintain at a very low cost.


advertisement
Using RowFixture Classes
Previously, a ColumnFixture table was used to define the expected output of an operation, given a set of input. This style of table works well for testing things like calculation and validation logic. However, there are other scenarios where a given operation might return more than one result. In these cases the RowFixture class can be extended to easily validate a list of data. The Table 2 example asserts that a given set of records is returned when generating the High Risk Rentals report.

Table 2. Risk Taking: Generating the report for this test case asserts that a given set of records is returned.
com.devx.fit.HighRiskReport
namerisk factor
MattExotic
AmyUnderage
JimUnderage
JoeExotic

The test table shown in Table 2 is fairly straightforward. Each row represents one record in the report. If there are missing or additional records, or if any of the records contain incorrect data, this test will fail.



Here is the Fixture code that is needed to execute the test table shown in Table 2:

package com.devx.fit; import java.util.ArrayList; import java.util.Collection; import com.devx.fit.app.RentalRecord; import com.devx.fit.app.ReportingService; import fit.RowFixture; public class HighRiskReport extends RowFixture { private ReportingService reportingService = new ReportingService(); @Override public Class getTargetClass() { return ReportEntry.class; } @Override public Object[] query()throws Exception { Collection report = reportingService.getHighRiskRentals(); ArrayList entries = new ArrayList(); for (RentalRecord record : report) { entries.add(new ReportEntry(record.getName(), record.getRiskFactor())); } return entries.toArray(); } public static class ReportEntry { public String name; public String riskFactor; public ReportEntry(String name, String riskFactor) { this.name = name; this.riskFactor = riskFactor; } } }

As you can see, a RowFxture simply defines a query() method that returns an array of objects and a getTargetClass() method that returns the type of the objects Fit can expect to find in that array. The type returned by getTargetClass() should contain public fields corresponding to each column of the test table that Fit will use to do its comparisons when the test is run.

By itself, the table shown in Table 2 doesn't really make much sense and won't execute successfully because we don't know where the data that backs this report come from. To give context to this test and prime the system with the necessary data we can use a third fixture type called a RowEntryFixture. A RowEntryFixture is a modified type of ColumnFixture where instead of asserting on the output of a given operation, the Fixture class simply implements a method that knows how to handle each row.

The test table shown in Table 3 and its supporting Fixture code is an example of a RowEntry-style table that could be used to set up the data needed to successfully run the previous high-risk report table (see Table 2).

Table 3. RowEntry Style: This test sets up the data to run the same high-risk rentals report as was run for the data in Table 2.
com.devx.fit.Rent
name age car type
John 34 Economy
Chris 53 Standard
Matt 42 Exotic
Amy 24 Economy
Jim 19 Standard
Joe 39 Exotic

package com.devx.fit; import com.devx.fit.app.RentalService; import fitnesse.fixtures.RowEntryFixture; public class Rent extends RowEntryFixture { public String name; public int age; public String carType; private RentalService rentalService = new RentalService(); @Override public void enterRow()throws Exception { rentalService.rent(name, age, carType); } }

Like a ColumnFixture, a RowEntryFixture processes each row by first binding all of the columns in the table to public instance fields. After the fields are bound, the fixture calls the enterRow() method to perform the desired operation. The only way for a RowEntry table to fail is if the enterRow() method throws an exception. In this case, the row or rows that threw exceptions during processing will be shown in red.

To use the Rent and HighRiskReport fixtures together, the two tables must appear on the same test page in the correct order. When FitNesse executes a test page it runs each test table found on the page in succession and uses a single classloader per page. The sample application is therefore able to use a singleton as a data store, and all the records entered by the Rent table will be available when the HighRiskReport table executes.

As you have seen, Fit and FitNesse can be used to easily create a suite of automated acceptance tests that can be shared and maintained by an entire team. While the fixtures and table styles discussed here are the ones most commonly used, combined they are just the tip of the iceberg. The libraries provided by Fit and FitNesse are very extensible and allow you to create fixtures that can execute any table as a test. By using these tools on your project you can reap all the benefits of acceptance testing at a very low cost.



Michael Deck is a consultant for Valtech Technologies Inc. Most recently he has worked with several projects to improve their continuous integration and test automation practices. He currently works out of Valtech's primary proximity center in College Station, Texas as a member of one of the many agile development teams based there.
Comment and Contribute

 

 

 

 

 


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

 

 

Sitemap