Using NUnit with F# code
Switching to another programming language is difficult. Especially if you are switching from an imperative one to a functional one. There are a number of reasons why you would think that switching is bad, and when considering F# I dare say that none of those reasons are correct. The language compiles to IL (Intermediate Language) code that runs on Microsofts tried and tested .NET runtime (or Mono’s ditto). You have access to all the same classes in the .NET hierarchy that you have from any other .NET capable language. You can write web applications, WinForms applications or console applications in F#. You can connect to any kind of database that you can connect to from any other .NET language. You can use your existing C# og VB.NET code in your F# applications, or you can write F# code and use it in your existing applications. You have the opportunity to write more concise and maintainable code in a language that has much higher performance than any other functional language I know – with the possible exception of Clean, but that is still debatable, and you can mix functional programming with object oriented ditto at your leasure.
But what about testing? In these TDD (Test Driven Development) oriented days being able to properly test your code with automated unit- and integration tests is paramount. And if you have to use another (or perhaps write your) test framework than the one you are already using and familiar with, that might be an insuperable problem. Fortunately you can easily use NUnit with F# and I will show you how.
Testing your F# code from C#
The most obvious way to go about testing F# code for a new F# programmer is writing your tests in C# (if you are a C# programmer. Let’s just assume that). This is okay since you are used to writing tests in this language, and it is no different from writing tests in one project that tests classes written in C# in another project. Let us start by defining an easily testable class in F#:
#light namespace TestableLib type TestableClass() = member tc.DoubleNumber n = 2*n member tc.SquareNumber n = n*n
A typical test fixture written in C# for this class looks like the following piece of code. It is a bit overdesigned – using a test fixture setup in this test is a bit too much, but bear with me for a while.
using NUnit.Framework; using TestableLib; namespace TestApplication { [TestFixture] public class TestableClassTest { private TestableClass _testableClass = null; [TestFixtureSetUp] public void TestFixtureSetup() { _testableClass = new TestableClass(); } [Test] public void TestDoubleNumber() { Assert.AreEqual(2, _testableClass.DoubleNumber(1)); Assert.AreEqual(8, _testableClass.DoubleNumber(4)); Assert.AreEqual(512, _testableClass.DoubleNumber(256)); } [Test] public void TestSquareNumber() { Assert.AreEqual(1, _testableClass.SquareNumber(1)); Assert.AreEqual(16, _testableClass.SquareNumber(4)); Assert.AreEqual(10000, _testableClass.SquareNumber(100)); } } }
This obviously works for methods defined in modules instead of classes. This is F#-modules, not .NET modules. A module in F# is resolved as a class in C#, and all methods defined in the module file are static methods on this class.
#light module TestableModule let doubleNumber n = 2*n let squareNumber n = n*n
A couple of test methods could look like this:
[Test] public void TestModuleDoubleNumber() { Assert.AreEqual(2, TestableModule.doubleNumber(1)); Assert.AreEqual(8, TestableModule.doubleNumber(4)); Assert.AreEqual(512, TestableModule.doubleNumber(256)); } [Test] public void TestModuleSquareNumber() { Assert.AreEqual(1, TestableModule.squareNumber(1)); Assert.AreEqual(16, TestableModule.squareNumber(4)); Assert.AreEqual(10000, TestableModule.squareNumber(100)); }
Writing test fixtures in F#
Whether you are testing a class written in C#, VB.NET, F# or any other .NET language you can write the tests in F# too. This is because you can annotate type definitions and members with attributes as you can with any other language. You will of course have to reference the “nunit.framework.dll” file where the attributes we use are defined.
Test fixtures are classes too so we define a new type with a default constructor, and annotate the class and the methods with the attributes defined in the NUnit.Framework namespace:
#light namespace TestableLib open NUnit.Framework type TestableClass() = member tc.DoubleNumber n = 2*n member tc.SquareNumber n = n*n [<TestFixture>] type TestClass() = let mutable testableClass = TestableClass() /// This is not necessary since the mutable testableClass is already set /// but is just for showing how to define a test fixture setup method. [<TestFixtureSetUp>] member tc.TestFixtureSetUp() = testableClass <- TestableClass() [<Test>] member tc.TestDoubleNumber() = Assert.AreEqual(2, testableClass.DoubleNumber(1)) Assert.AreEqual(8, testableClass.DoubleNumber(4)) Assert.AreEqual(512, testableClass.DoubleNumber(256)) [<Test>] member tc.TestSquareNumber() = Assert.AreEqual(1, testableClass.SquareNumber(1)); Assert.AreEqual(16, testableClass.SquareNumber(4)); Assert.AreEqual(10000, testableClass.SquareNumber(100));
The output from the F# project can then be opened in the NUnit runner just like any other assembly with test fixtures defined.
Note to Visual Studio users
Since F# is still not part of the official .NET language stack (I am currently using version 1.9.4) there are a few minor(!) hurdles to overcome. If you normally use Visual Studio you are used to be able to add references to the projects in the IDE. This is not possible with F# project since the Visual Studio integration is not functioning optimally – or at least as good as other supported languages. But you can add a reference manually by selecting the property page of the project and adding a reference with the “-R” option. I have used ‘-R “c:\Program Files\NUnit 2.4.7\bin\nunit.framework.dll”’.