This week I happen to be at one of our offices, and we had a ton of MSDN Magazines there. Flipping through one, they had an intro to F#, a functional language that runs on the CLR. I figured it would be fun to see how hard it would be to get it running with the FitNesse DotNet runner.
First, set up a FitNesse instance with the DotNet runner using C# to make sure everything is running well. Gojko’s site is a great place to start (since all of my tutorials weren’t updated for 2.0). Got it? Good. Let’s get F# going.
First things first. While FitNesse has been known to work with functional languages, I’m going to take advantage of the fact that we can define a class definition using F# which compiles to look like a .NET class. I’m using the latest drop of F# from the above site, which includes integration into Visual Studio.
After you’ve installed F#, open up Visual Studio and create a new F# project:
Name it whatever you’d like. I called my FSharpSpike. Next, right click on the project, and Add->New Item of an F# Source File. Name it fsfixtures.fs:
Delete any text that it puts in the file. What we are going to do is recreate the canonical Division FitNesse example. Once you’ve deleted the text, type the following:
type Division() = class
end
Now compile that. You should see in your project directory a new exe called FSharpSpike.exe. If you explore it with Reflector, you’ll see that it looks much like a regular class definition, with one caveat:
Division is an inner class of Fsfixtures. This is not a problem, but I simply don’t know enough about F# to know how to get around it. Our source is being compiled into a class named after the file name, which then contains our Division class. If you know how to get around this, please post in the comments.
Ok, so that out of the way, let’s set up our FitNesse test. Mine is called DemoDivision and looks like:
!define COMMAND_PATTERN {%m %p}
!define TEST_RUNNER {dotnet2\FitServer.exe}
!path C:\Projects\FSharpSpike\FSharpSpike\fsharpspike.exe
!|FsFixtures.Division|
|numerator|denominator|quotient?|
|10 |2 |5 |
|12.6 |3 |4.2 |
|100 |4 |25 |
|20 |2 |10 |
Notice that we are pointing our path to the generated exe, and that our fixture is using FsFixtures.Division. Save this, make sure the properties are set to Test, and then run it. You should see that we didn’t extend Fixture. Remember that to write fixture code we have to inherit from fit.Fixture. Luckily, F# gives us the ability. First, modify your F# code to:
type Division() = class
inherit fit.ColumnFixture() as base
end
compiling this will give you an error that fit does not exist. Notice that we don’t have a way to add references from the UI. We do have a way to add references from the project properties. So right-click on the FSharpSpike project, and choose properties. Notice the line “DLL References”? Modify that to point to fit.dll. Mine looks like:
Now recompile. You should succeed. Now rerun your FitNesse test, and you should see it go a little nutty:
But, this is a good thing! It means that FitNesse has found our fixture, and just can’t map anything. We are on the home stretch!
Now modify your fixture code to add in statements for the “properties” we need to retrieve:
type Division() = class
inherit fit.ColumnFixture() as base
let num = 0.0
let den = 0.0
let quo = num/den
member obj.denominator = den
member obj.numerator = num
member obj.quotient = quo
end
Now rerun, and you should see a similar look, except that it says that the setter property couldn’t be found. If we refresh Reflector, we can see what we’ve done:
We have getters for everything – including quotient. So let’s add some setters:
type Division() = class
inherit fit.ColumnFixture() as base
let num = 0.0
let den = 0.0
let quo = num/den
member obj.denominator = den
member obj.denominator(d:double) = den = d
member obj.numerator = num
member obj.numerator(n:double) = num = n
member obj.quotient = quo
end
Now compile and run, and….
WooHoo! We are extremely close. At this point, I’ve been brute forcing things, but I’m sure this is the wrong way. And indeed, I was close, but not quite there. The F# Wiki showed the way. So modify your fixture code to look like:
type Division() = class
inherit fit.ColumnFixture() as base
let mutable den = 0.0
let mutable num = 0.0
member obj.denominator with get() = den
and set d = den <- d
member obj.numerator with get() = num
and set n = num <- n
member obj.quotient() = num/den
end
Save and Build, run your FitNesse test and…
Bask in the glory! Now go out and have fun (and maybe I’ll figure out this whole functional thing yet…)
More information about the namespaces and how to set them can be found at http://research.microsoft.com/fsharp/manual/advanced.aspx. (Thanks to Matthew Podwysocki) for the link!