AcceptanceTestsWithFitNesse.
TestingDatasets
< Gui Test with other Fixtures | Links and Books >

This is only the HTML version of the original WiKi-based tutorial.
You should download it from here to experience the real thing.

 Settings

The RowFixture

The ColumnFixture is good at testing functions; GUIs may be tested with ActionFixture. But sometimes the result of an operation is not a single piece of data but a dataset that must be tested against the expectations.

That's where the RowFixture comes into play. In a row RowFixture table one table row specifies an expected dataset. The RowFixture has the following properties:
Let's give it a try. We will use our time recording example again. Ok, it's not a database application; but at last our TimeRecording is nothing but a list of datasets. But at first we have to fill our TimeRecording with some values. How do we achieve that? Well, we just abuse our ColumnFixture for that and take care that the RowFixture starts working with the same TimeRecording instance.

Let's check it out by pressing Test:

At first we enter the datasets into the system using our TimeRecordingColumnFixture.
de.fitsample.timerecording.TimeRecordingColumnFixture
day from to
1 10:00 12:00
  12:45 17:00
2 08:00 12:00
  13:00 18:30
3 08:00 12:00
  13:00 19:30

After that, we test the expected datasets with a RowFixture. As you can see the order of the datasets is of no intereset:
de.fitsample.timerecording.TimeRecordingRowFixture
day? from? to?
3 08:00 12:00
1 10:00 12:00
2 08:00 12:00
1 12:45 17:00
3 13:00 19:30
2 13:00 18:30

That's the way it looks when datasets are missing or surplus:
de.fitsample.timerecording.TimeRecordingRowFixture
day? from? to?
1 12:45 17:00
2 08:00 12:00
2 13:00 18:30
3 13:00 19:30
3 08:00 12:00
4 08:30 16:00

So how is this implemented in detail? Let's have a look at our good old
first. The constructor of TimeRecordingColumnFixture creates an instance of TimeRecording and stores it in the TimeRecordingRepository:
    public TimeRecordingColumnFixture() {
timeRecording = new TimeRecording();
TimeRecordingRepository.getInstance().store(timeRecording);
}

Our RowFixture code is found in the classes
public class TimeRecordingRowFixture extends RowFixture {

private TimeRecording timeRecording;

public TimeRecordingRowFixture() {
timeRecording = TimeRecordingRepository.getInstance().retrieve();
}

public Object[] query() throws Exception {
Object[] result = new Object[timeRecording.size()];
for (int i = 0; i < result.length; i++) {
result[i] = new TimeRecordRowFixtureAdapter(timeRecording
.getRecord(i));
}
return result;
}

public Class getTargetClass() {
return TimeRecordRowFixtureAdapter.class;
}

public Object parse(String text, Class type) throws Exception {
if (type == Time.class) {
return Time.valueOf(text);
}
return super.parse(text, type);
}
}

So what's happening here? The constructor does not create any new instance of TimeRecording but retrieves it from the TimeRecordingRepository; and that's the instance we created and set up with data using our ColumnFixture.

The main methods of RowFixture are

Method query() returns the datasets under test, and getTargetClass() the type of a single dataset. Wait a minute, I would have expected getTargetClass() to return TimeRecord as the type of a dataset. What the heck do we need this TimeRecordRowFixtureAdapter for? Well, the RowFixture tries to map the row header names to fields, resp. methods of the dataset class. Our TimeRecord does contain a field named day, but none for from and to since they are encapsulated by a TimeFrame. In order to make these values accessible to the RowFixture we just wrap the TimeRecord with an adapter. This also provides a way to use names more convenient to the testing audience:
public class TimeRecordRowFixtureAdapter {

private TimeRecord timeRecord;

public TimeRecordRowFixtureAdapter(TimeRecord timeRecord) {
this.timeRecord = timeRecord;
}

public int day() {
return timeRecord.getDay();
}

public Time from() {
return timeRecord.getTimeFrame().getStartTime();
}

public Time to() {
return timeRecord.getTimeFrame().getEndTime();
}



< Gui Test with other Fixtures | Links and Books >


[.FrontPage] [.RecentChanges]