Over the past few months, we’ve had the chance to explore getting up and running with Fitnesse and .NET and the chance to check out how to implement ActionFixture
s. While both Column and Action fixtures are great ways to express requirements, there is another fixture which is extremely powerful, and allows your customer to write incredibly expressive fixtures. These are called DoFixture
s. In this 2 part article, we’ll explore the basics of the DoFixture, and then move into some more advanced features.
The concept behind a DoFixture
is to write your tests as user-readable sentences. For example, if a requirement for a chat application was that a user was supposed to enter his username, enter a room name, and click the “Create” button, we’d have a table that looked like:
|User enters username of|John|
|User enters room name of|baseball|
|User presses|Create|
So right away we can see the expressiveness of the DoFixture
. The three rows above would be mapped to the methods:
public void userEntersUsernameOf(string username);
public void userEntersRoomNameOf(string roomName);
public void userPresses(string buttonName);
In addition, you can have multiple parameters. For example, we could have written the above as:
|User|John|enters room name of|baseball|
which would map to the method:
public void userEntersRoomNameOf(string username, string roomName);
Finally, you can mix other fixture types into your DoFixture
s, even having your methods return Fixture
types.
But, before we get too far, let’s get an example working. We assume that you have already been through the Fitnesse tutorial for .NET, so you have a working Fitnesse server and have been able to get it to talk to your .NET classes.
Make sure your Fitnesse server is running, and fire up a browser. Create a page called DoFixtureExample, and type in the following:
!define COMMAND_PATTERN {%m %p}
!define TEST_RUNNER {dotnet\FitServer.exe}
!define PATH_SEPARATOR {;}
!path C:\fitnesse\fitlibrary.dll
|User enters username of|John|
|User enters room name of|baseball|
|User presses|Create|
|User|John|is in room|baseball|
As you can see, we have a user named John who wants to create a new chat room called baseball. Once he presses create, we should be able to tell that he is in the room baseball. Once you have the code in there, save it, change the properties of the page to be a Test, and then run it. You should get something like:
So let’s get these to pass. Fire up Visual Studio, and create a new project called DoFixtureExample
, and create it in location c:\
. (I created mine as a Class Library). Next, add fit.dll and fitlibrary.dll to your references (FIT Library can be downloaded from the SourceForge). Now, create a class called ChatRoom.cs
, and have it extend fit.DoFixture
. Finally, compile your project.
Now that we have our project shell built, let’s get it added to our Fitnesse fixture. Go back to your DoFixtureExample test, and add a path reference to your new project’s DLL:
!path C:\DoFixtureExample\bin\Debug\DoFixtureExample.dll
We also need to tell our test what is going on. Before, we would preface the tables with the name of our Fixture class. But since DoFixtures are a series of steps that apply to the same group of objects, we need to tell Fitnesse what to use. We do that by “Starting” our application. So, edit your Fitnesse test and add the following after your path and other declarations, but before your first test:
|!-DoFixtureExample.ChatRoom-!|
So, your fixture should now look like:
and running it gives us errors like:
fit.exception.FitFailureException: Unknown method: userentersusernameof with 1 argument(s).
at fit.Method.FindFirst(Object[] theTargets, String theMethodName, Int32 theParameterCount)
at fit.FlowFixtureBase.FindMethod(CellRange theCells)
at fit.FlowFixtureBase.FindRowMethod(Parse theRow)
at fit.FlowFixtureBase.DoRows(Parse theRows)
So, now we know that our Fixture is talking to our code, but not finding the methods. So, let’s create methods for each fixture. In your ChatRoom.cs, add the following methods:
public void userEntersUsernameOf(string username)
{
}
public void userEntersRoomNameOf(string roomName)
{
}
public void userPresses(string button)
{
}
public void userIsInRoom(string user, string room)
{
}
Now, compile and run your test. All of your tables should stay gray. For now, that means success! Your fixture is talking to all of your methods – they just aren’t doing anything. So let’s make them do something. For our contrived example, let’s have the username go into a hashtable with the room name as the key. When we find out if a user is in that room, we’ll simply look up the username with the room name.
To do this, we’ll add a Hashtable, getting a new instance in the constructor, and modify our methods to use this. Your code should look like:
using System;
using System.Collections;
namespace DoFixtureExample
{
///
///
public class ChatRoom : fit.DoFixture
{
private Hashtable roomList;
private string user;
private string room;
public ChatRoom()
{
roomList = new Hashtable();
}
public void userEntersUsernameOf(string username)
{
user = username;
}
public void userEntersRoomNameOf(string roomName)
{
room = roomName;
}
public void userPresses(string button)
{
if(button.Equals("Create"))
{
roomList.Add(room, user);
}
}
public void userIsInRoom(string user, string room)
{
if(theUserIsInTheRoom(user, room))
{
}
}
private bool theUserIsInTheRoom(string user, string room)
{
if(roomList.ContainsKey(room))
{
string roomsUser = (string)roomList[room];
return roomsUser.Equals(user);
}
return false;
}
}
}
We now have a problem. if the user is in the room, we want to turn the table green. If they aren’t, we want to make it red. Normally we’d do that through using this.Right()
and this.Wrong()
, but both of those need access to the Parse, which we don’t seem to have. Luckily, getting the Parse is pretty straightforward – we just need to override a method so we have access to it. So we’ll add the following to our ChatRoom.cs:
using fit;
private fit.Parse currentParse;
protected override System.Collections.IEnumerable MethodCells(CellRange theCells)
{
currentParse = theCells.Cells;
return base.MethodCells(theCells);
}
Next, we’ll modify our userIsInRoom
method to look like:
public void userIsInRoom(string user, string room)
{
if(theUserIsInTheRoom(user, room))
{
this.Right(currentParse);
return;
}
this.Wrong(currentParse, "User was not found in the room");
}
Compile and run your test. It’s Green! Congratulations!
In our next segment, we’ll go over a different way to test the users in a room by embedding fixtures inside our code, and go into some more advanced features of the DoFixture. Enjoy!
Hi,
Are you still planning on doing a part 2.
I have looked around your blog but can’t find it :(
“””Now, create a class called ChatRoom.cs,”””
This is a typo. The class should be called Chatroom
“|!-DoFixtureExample.ChatRoom-!|”
Compiling using SharpDevelop I found that I should instead use
“|!-ChatRoom-!|”
In order to get the boxes to remain gray I must use:
|!-ChatRoom-!|
|ChatRoom|
|User enters username of|John|
|User enters room name of|baseball|
|User presses|Create|
“””public class ChatRoom : fit.DoFixture”””
DoFixture is in fitlibrary so it should read
public class ChatRoom : fitlibrary.DoFixture
Contrary to what is shown above in IE there should be no empty lines in betwen the following:
|User enters username of|John|
|User enters room name of|baseball|
|User presses|Create|
|User|John|is in room|baseball|
If you place an empty line after the |Create| then you will get an error.
The example finally ran properly with all of the changes noted above. Hooray!
Proposing something called “PhraseFixture†— a better DoFixture() for use with FIT and FitNesse Acceptance Testing Framework.
The powerful DoFixture() in FitLibrary simulates English like specification. The PhraseFixture proposal takes this to the next level.
Please see article here:
http://codeproject.com/KB/library/PhraseFixture.aspx
I’d like to get some feedback.