One of the biggest challenges for people using FitNesse in any scale is how to manage the pages. Since everything is a wiki, and mapped dynamically to adapter classes, it becomes very easy to break, very easy to make brittle, and pretty difficult to refactor. While there has been work on the interwebs to make things better (for example, Jeremy Miller’s StoryTeller), I kept thinking about ways we could make things better without having to rewrite things.
Last week at KaizenConf I was talking with Scott Bellware about FitNesse and the challenges. The way I see it, right now you’ve got 3 basic options:
- FitNesse
- DSLs
- RSpec
We’ve noted FitNesse’s issues already. DSLs are interesting in that they are in the context and domain of your users, but managing editing and creating them can be a pain. I really like RSpec, and have for a long time, but I really only like xSpec in Ruby – I haven’t particularly cared for it in other languages. It runs into a similar challenge of DSLs, and mixes in programming constructs as well.
When I really started thinking about it, most complaints I hear about FitNesse are around refactoring and management. You are writing things in a Wiki syntax that map back to code – but if you need to change that code, it becomes darn near impossible to know what you’ve broken. If we can solve that, then we might be able to make FitNesse a little more usable.
The inspiration point came out of the ALT.NET discussions around Fluent NHibernate – people had challenges writing all the XML configuration (or thinly veiled XML in the form of C# code) to hook up NHibernate, so they made some interfaces and abstracted code to make it much easier to work with. So why not do the same for FitNesse? Let’s look at a typical DoFixture:
!|MathFixtures.DivisionFixture|
|When The Numerator Is|3|And Divisor Is|1|Then Result Is|3|
|When The Numerator Is|7|And Divisor Is|2|Then Result Is|2.5|
|When The Numerator Is|4|And Divisor Is|2|Then Result Is|2|
Pretty straightforward. To run this, you’d have to create a mapping class. Using C#, that would look like:
public class DivisionFixture : fitlibrary.DoFixture
{
public bool WhenTheNumeratorIsAndDivisorIsThenResultIs(double num, double div, double result)
{
return (num / div) == result;
}
}
So we now begin to see the problem. What if we realize our tests should specify the behavior we want, so we want to change it from "Then Result Is" to "Then The Result Should Be"? We have to change both our FitNesse page and our C# class – and we won’t know until runtime that we missed something.
What if, instead, we could do the following?
FluentFitnesse.Fixture
new FluentFitnesse.Fixture
using (f.BoundTable)
{
f.Call.WhenNumeratorIs_AndDivisorIs_ThenResultIs(3.0, 1.0, 3.0);
f.Call.WhenNumeratorIs_AndDivisorIs_ThenResultIs(7.0, 2.0, 3.5);
f.Call.WhenNumeratorIs_AndDivisorIs_ThenResultIs(4.0, 2.0, 2.0);
}
return f.Output;
The output of which is our FitNesse table from above. Now what we have is a specification we can actually refactor. If we change the method name in our underlying classes, it becomes a compile-time issue – not something we discover way down the line. Even better, the call is using our Fixture object – so no concerns about it being out of sync.
The guts behind it is pretty simple, and requires just some minor modifications to your FitNesse fixture class. First, you have to use underscores where the parameter values should be inserted (as you can see from the above example). Second, your methods need to be virtual, as we are creating a DynamicProxy. Third, they need to return bool – something you are probably already doing with a DoFixture anyway.
With that out of the way, simply create a class for each wiki page you want which implements an IFitnessePage instance.
public class DemoDivision : FluentFitnesse.IFitnessePage
{
#region IFitnessePage Members
public string Header()
{
return @"!contents -R2 -g -p -f -h
!define COMMAND_PATTERN {%m %p}
!define TEST_RUNNER {dotnet2\FitServer.exe}
!path C:\Users\Cory\Documents\Visual Studio 2008\Projects\MathFixtures\bin\Debug\MathFixtures.dll";
}
public string Render()
{
FluentFitnesse.Fixture
new FluentFitnesse.Fixture
using (f.BoundTable)
{
f.Call.WhenNumeratorIs_AndDivisorIs_ThenQuotientShouldBe(3.0, 1.0, 3.0);
f.Call.WhenNumeratorIs_AndDivisorIs_ThenQuotientShouldBe(6.0, 2.0, 3.0);
}
f.Call.WhenNumeratorIs_AndDivisorIs_ThenQuotientShouldBe(7.0, 2.0, 3.5);
return f.Output;
}
#endregion
}
Running this will produce the output:
!|MathFixtures.DivisionFixture|
|When Numerator Is|3.0|And Divisor Is|1.0|Then Quotient Should Be|3.0|
|When Numerator Is|6.0|And Divisor Is|2.0|Then Quotient Should Be|3.0|
|When Numerator Is|7.0|And Divisor Is|2.0|Then Quotient Should Be|3.5|
Notice the extra space. That’s because if you are using a Flow-style fixture, you don’t want the rows right underneath the fixture name. What happens is that BoundTable returns an object that inserts an extra line when "disposed".
The entirety of the Fixture class looks like:
namespace FluentFitnesse
{
public class Fixture
{
private StringBuilder output;
private T fixtureObject;
public Fixture()
{
output = new StringBuilder();
fixtureObject = CreateWrapper();
}
 
; private T CreateWrapper()
{
Castle.DynamicProxy.ProxyGenerator proxyGen = new Castle.DynamicProxy.ProxyGenerator();
T instance = proxyGen.CreateClassProxy
return instance;
}
public IDisposable BoundTable
{
get
{
return new BoundTable(typeof(T), output);
}
}
public T Call
{
get
{
return fixtureObject;
}
}
public string Output
{
get { return output.ToString(); }
}
}
public class MethodInterceptor : Castle.Core.Interceptor.IInterceptor
{
private StringBuilder sb;
private string SplitCamelCase(string s)
{
Regex upperCaseRegex = new Regex(@"[A-Z]{1}[a-z]*");
MatchCollection matches = upperCaseRegex.Matches(s);
List
foreach (Match match in matches)
{
words.Add(match.Value);
}
return String.Join(" ", words.ToArray());
}
public MethodInterceptor(StringBuilder sb)
{
this.sb = sb;
}
#region IInterceptor Members
public void Intercept(Castle.Core.Interceptor.IInvocation invocation)
{
string methodName = invocation.Method.Name;
string[] parts = methodName.Split(‘_’);
if (parts.Length != invocation.Arguments.Length)
{
Console.WriteLine("WARNING! Number of arguments does not match the number of parts in the method name");
Console.ReadLine();
}
int argPos = 0;
sb.Append("|");
foreach (string part in parts)
{
sb.Append(SplitCamelCase(part) + "|" + invocation.Arguments[argPos] + "|");
argPos++;
}
sb.AppendLine();
invocation.ReturnValue = true;
}
#endregion
}
public class BoundTable : IDisposable
{
private StringBuilder output;
public BoundTable(Type t, StringBuilder sb)
{
this.output = sb;
output.AppendLine("!|" + t.FullName + "|");
}
#region IDisposable Members
public void Dispose()
{
output.AppendLine();
}
#endregion
}
}
Which, as you can see, uses the Castle DynamicProxy to wrap the Fixture code and intercept all calls to it. It’s all a bit hacky -I don’t like passing around StringBuilders, etc – but I wanted to get a baseline out there to see if people thought this would be useful.
The basic use case would be that you would gen out all of your FitNesse pages using a utility which took in a list of assemblies that contained your mappers. Ideally we could either reverse-gen C# code from the content pages, or otherwise have a way to tell when the pages are out of date (in case the users are changing them).
I’m really interested in feedback on this. I think this could really help out the "refactoring is hard in FitNesse" stigma. What do you all think?
Hi Cory
Just wondering if anything ever came of this?
I am implemting some fitnesse stuff at the moment and struggling with managing it all.
Tim