One of the best and easiest ways to use F# in your projects is to use it for unit testing and the same can be said for your mobile applications with Xamarin.
While C# has FluentAssertions as well as Should (I prefer the syntax of FluentAssertions between the two) F# has FsUnit to give more readable test conditions. I would say even more readable than the C# equivalent.
With this post I’ll have a small demo Xamarin project using Xamarin Forms to build the UI. This will consist of a simple navigation and a small class to do some logic. We will use F# for our test project to test both the logic and use Xamarin UI Test to make sure our navigation and screens appear as we intend. These tests are also to make sure our workflows work as intended on several different devices.
Let’s quickly compare the two and see how they look. Within our demo Xamarin application, our PCL project that includes our XAML for Xamarin Forms will also have a class to do some logic for us. For demo purposes, this will just be an Add
class that takes in two integers and adds them together and returns the result. Here’s our small class:
public static class Add
{
public static int AddItems(int x, int y)
{
return x + y;
}
}
Pretty simple, right? Now we can unit test this method. Here’s a C# version of using FluentAssertions to check to check our result.
[TestFixture]
public class AddTests
{
[Test]
public void Add2And2()
{
var result = Add.AddItems(2, 2);
result.Should().Be(4);
}
}
And here is the equivalent of the above in F# using FsUnit.
[<TestFixture>]
type AddTests() =
[<Test>]
member x.``Adding 2 + 2 = 4``() =
let result = Add.AddItems(2, 2)
result |> should equal 4
From here, you may be able to tell that our F# version is more readable. It takes away the noise of the .
and ( )
. You may have also noticed that, in F#, we can add the double back-ticks to our function name which will allow us to use spaces. Now your test names are that much more readable as well! In Xamarin Studio we can easily read what each test either in the Test Results pad or in the easier to read Unit Tests pad.
Using F# for Unit Tests
Now that we’ve seen how using F# for unit tests can be to our advantage, how exactly do we make this happen?
Keep in mind that the F# templates for Xamarin Studio are still being worked on so some manual steps may need to be taken to get all of this working. Of course, the first step is to add an F# class library project to your solution.
Then just reference your PCL project as you usually would in a test project.
At this point, when trying to call the class or method to test against in the C# PCL library, you may need to add the
System.Runtime
DLL to the test project. On my Mac, this is located in the/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5/Facades/
folder.
Now, from here you are free to just call your tests like usual in an NUnit test project and use NUnit’s built-in Assert
class. To give us those fluent and easier to read tests we will import FsUnit, as well.
Another little quirk you may experience here is that, when running tests that use methods from FsUnit you may receive the error below when trying to run the tests.
For this issue, you would need to create an App.config
for your test project (if not already created) and add the below assembly binding redirect configuration.
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="FSharp.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.3.1.0" newVersion="4.3.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="nunit.framework" publicKeyToken="96d09a1eb7f44a77" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.6.4.14350" newVersion="2.6.4.14350" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
This is a bit weird and out of the way, but for now that’s what is needed.
Writing Tests With FsUnit
Of course, FsUnit has different methods that are included to make your testing much more readable. Below are a few other examples within our demo application.
[<Test>]
member x.``Adding 1 + 0 = 1``() =
let result = Add.AddItems(1, 0)
result |> should be (greaterThan 0)
[<Test>]
member x.``Adding 1 + 1 = 2``() =
let result = Add.AddItems(1, 1)
result |> should not' (equal 0)
Note that the
not'
function uses a single-quote. The FsUnit team explains that this is due to not overriding the built-in F# function.
There are plenty more over on the FsUnit site.
Hopefully you get a sense of how much helpful using F# with FsUnit can be with your unit testing experience. Even if you’re completely new to F# this is a great way to get started and a very easy way to incorporate F# into your projects, especially without having to mess with production code.
Also wonder what F# and Wintellect can do for you or your business, or just have more questions about F# in general? Feel free to reach out to us at any time with questions.
Need Xamarin Help?
Xamarin Consulting Xamarin Training