Mathias Brandewinder on .NET, F#, VSTO and Excel development, and quantitative analysis / machine learning.
by Mathias 26. January 2013 19:08

Phil Trelford recently released Foq, a small F# mocking library (with a very daring name). If most of your code is in F#, this is probably not a big deal for you, because the technique of mocking isn’t very useful in F# (at least in my experience). On the other hand, if your goal is to unit test some C# code in F#, then Foq comes in very handy.

So why would you want to write your unit tests in F# in the first place?

Let’s start with some plain old C# code, like this:

namespace CodeBase
{
    using System;

    public class Translator
    {
        public const string ErrorMessage = "Translation failure";

        private readonly ILogger logger;
        private readonly IService service;

        public Translator(ILogger logger, IService service)
        {
            this.logger = logger;
            this.service = service;
        }

        public string Translate(string input)
        {
            try
            {
                return this.service.Translate(input);
            }
            catch (Exception exception)
            {
                this.logger.Log(exception);
                return ErrorMessage;
            }
        }
    }

    public interface ILogger
    {
        void Log(Exception exception);
    }

    public interface IService
    {
        string Translate(string input);
    }
}
We have a class, Translator, which takes 2 dependencies, a logger and a service. The main purpose of the class is to Translate a string, by calling the service. If the call succeeds, we return the translation, otherwise we log the exception and return an arbitrary error message.

This piece of code is very simplistic, but illustrates well the need for Mocking. If I want to unit test that class, there are 3 things I need to verify:

  • when the translation service succeeds, I should receive whatever the service says is right,
  • when the translation service fails, I should receive the error message,
  • when the translation service fails, the exception should be logged.

In standard C#, I would typically resort to a Mocking framework like Moq or NSubstitute to test this. What the framework buys me is the ability to create cheaply a fake implementation for the interfaces, setup their behavior to whatever my scenario is (“stubbing”), and in the case of the logger, where I can’t observe through state whether the exception has been logged, verify that the proper call has been made (“mocking”).

This is how my test suite would look:

namespace MoqTests
{
    using System;
    using CodeBase;
    using Moq;
    using NUnit.Framework;

    [TestFixture]
    public class TestsTranslator
    {
        [Test]
        public void Translate_Should_Return_Successful_Service_Response()
        {
            var input = "Hello";
            var output = "Kitty";

            var service = new Mock<IService>();
            service.Setup(s => s.Translate(input)).Returns(output);

            var logger = new Mock<ILogger>();

            var translator = new Translator(logger.Object, service.Object);

            var result = translator.Translate(input);

            Assert.That(result, Is.EqualTo(output));
        }

        [Test]
        public void When_Service_Fails_Translate_Should_Return_ErrorMessage()
        {
            var service = new Mock<IService>();
            service.Setup(s => s.Translate(It.IsAny<string>())).Throws<Exception>();

            var logger = new Mock<ILogger>();

            var translator = new Translator(logger.Object, service.Object);

            var result = translator.Translate("Hello");

            Assert.That(result, Is.EqualTo(Translator.ErrorMessage));
        }

        [Test]
        public void When_Service_Fails_Exception_Should_Be_Logged()
        {
            var error = new Exception();
            var service = new Mock<IService>();
            service.Setup(s => s.Translate(It.IsAny<string>())).Throws(error);

            var logger = new Mock<ILogger>();

            var translator = new Translator(logger.Object, service.Object);

            translator.Translate("Hello");

            logger.Verify(l => l.Log(error));
        }
    }
}

More...

by Mathias 1. December 2012 13:55

I have been obsessing about the following idea lately – what if I could run a FSI session from within Excel? The motivation behind this is double. First, one thing Excel is good at is creating and formatting charts. If I could use F# for data manipulation, and Excel for data visualization, I would be a happy camper. Then, I think F# via FSI could provide an interesting alternative for Excel automation. I’d much rather leverage existing .NET libraries to, say, grab data from the internet, than write some VBA to do that – and the ability to write live code in FSI would be less heavy handed that VSTO automation, and closer to what people typically do in Excel, that is, explore data. Having the ability to execute F# scripts would be, at least for me, very useful.

Seeing Tim Robinson’s awesome job with FsNotebook.net kicked me out of procrastination. Even though FsNotebook is still in early development, it provides a very nice user experience – on the web. If something that nice can be done on the web, it should be feasible on a local machine.

As an aside, Tim is looking for feedback and input on FsNotebook – go try it out, it’s really fun:

Anyways – this is the grand plan, now we need to start with baby steps. If I want to embed FSI in Excel (presumably via a VSTO add-in), I need a way to talk to FSI from .NET, so that I can create a Session and send arbitrary strings of code to be evaluated.

As usual, StackOverflow provided two good starting points (this answer, and this answer) – so I set out to look into the Process class, which I didn’t know much about, and attempted to spawn a FSI.EXE process, redirecting input and output. Turns out it’s not overly complicated – here are the 34 lines of code I ended up with so far (see it on GitHub):

namespace ClearLines.FsiRunner

open System.Diagnostics

type public FsiSession(fsiPath: string) =

    let info = new ProcessStartInfo()
    let fsiProcess = new Process()

    do
        info.RedirectStandardInput <- true
        info.RedirectStandardOutput <- true
        info.UseShellExecute <- false
        info.CreateNoWindow <- true
        info.FileName <- fsiPath

        fsiProcess.StartInfo <- info

    [<CLIEvent>]
    member this.OutputReceived = fsiProcess.OutputDataReceived

    [<CLIEvent>]
    member this.ErrorReceived = fsiProcess.ErrorDataReceived

    member this.Start() =
        fsiProcess.Start()
        fsiProcess.BeginOutputReadLine()

    member this.AddLine(line: string) =
        fsiProcess.StandardInput.WriteLine(line)

    member this.Evaluate() =
        this.AddLine(";;")
        fsiProcess.StandardInput.Flush()

This is a fairly straightforward class. The constructor expects the path to FSI.EXE, and sets up the process in the constructor (the do block) to run headless and redirect the stream of inputs and outputs. Start() simply starts the process, and begins reading asynchronously the output of FSI, AddLine(line) is used to add an arbitrary string of F# code, and Evaluate() sends all lines currently buffered to FSI for evaluation – and flushes the buffer. The 2 events OutputReceived and ErrorReceived are provided for the client to listen to the FSI results.

More...

by Mathias 18. December 2011 14:59

I spent some time this week putting together an example illustrating how to use Bumblebee from C# code. I figured it would be more exciting to have a graphical representation of the bee colony working on the traveling salesman problem, so I put together a small WPF application which creates a random set of cities, and displays the improvements live as they are found by the algorithm.

Here is a screen capture of the first 10 seconds of a 100-cities problem:

Bumblebee working on 100 cities

The source code for the example is available in the current head revision, under the TspDemo.CSharp project; I’ll push an “official” downloadable version as soon as I have time for some cleanup. Note that, besides a reference to Bumblebee, a reference to FSharp.Core 4.0 is required – the rest is all pure C#.

More...

by Mathias 4. December 2011 15:47

I am in the middle of “Working Effectively with Legacy Code”, and found it every bit as great as it was said to be. In the book, Feathers introduces the concept of Seams and Enabling Points:

a Seam is a place where you can alter behavior in your program without editing it in that place

every seam has an enabling point, a place where you can make the decision to use one behavior or another.

The idea - as I understand it - is that an enabling point is a hook for testability, a place where you can replace the behavior of a piece of code with your own controlled behavior, and validate that the results are as expected.

The reason I am bringing this up is that I have been writing lots of F# lately, and it made me realize that a functional style provides lots of enabling points, and can be much easier to test than object-oriented code.

Here is a simplified, but representative, example of the problem I was looking at: I needed to pick a random item in a list. In C#, a method along these lines would do the job:

public T PickFrom(IList<T> list)
{
   var random = new Random();
   return list[random.Next(list.Count())];
}

However, this code is utterly untestable; it’s also probably a terrible idea to instantiate a new Random every time this is called, so we modify it this way:

public T PickFrom(IList<T> list, Random random)
{
   return list[random.Next(list.Count())];
}

This is much better: now we have a decent Enabling Point, because the list of arguments of the method contains everything that is used inside the method. However, this is still untestable, but for a different reason: by definition, Random.Next() will return different values every time PickFrom is called, and expecting a repeatable result from PickFrom is a bit of a desperate enterprise.

More...

by Mathias 2. August 2011 16:06

When working with Excel, it is common to use small optimization tricks, like setting Excel.ScreenUpdating to false to avoid un-necessary screen refreshes, during lengthy operations – something along these lines:

public void DoJob(Worksheet  worksheet)
{
   var excel = worksheet.Application;

   var initialScreenUpdating = excel.ScreenUpdating;
   var initialCursor = excel.Cursor;

   excel.ScreenUpdating = false;
   excel.Cursor = XlMousePointer.xlWait;

   // do stuff

   excel.ScreenUpdating = initialScreenUpdating;
   excel.Cursor = initialCursor;
}

This is a good outline of what we would like to happen, but as is, this code has limitations. We would like to be certain that whenever we capture the state, the final two lines, which reset the state to what it was originally, are executed.

More...

Comments

Comment RSS