Sharpduino Library: Testing

Warning: This post is mostly about Unit testing and less about Sharpduino as a library.

It has been almost two months now that I have been developing the next version of the sharpduino library. I feel that the new implementation is far better in terms of understanding what each part of the code does, with as few byte constants as possible, so anyone who looks at the code can understand what is happening without having the page or (shameless plug) my blog open. I tried to make various parts of the library as loosely coupled as possible, so it could be extensible and easier to code against.

In the previous version the library was tested by a console application trying to make sure that everything worked for the end users by telling them what to do (connect LEDS, etc.) and then what to expect as the library was used (Led turns on/off, etc).

For this version much of the functionality was pre-tested with unit tests before even hooking up an arduino. This was done with the help of the NUnit and Moq libraries. I won’t be going into detail about the choice of Unit testing and Mocking frameworks. Let’s just say that the NUnit – Moq combination worked for me without much hustle. If you are interested in finding alternative frameworks, the following is a small list which I made while searching for my library. This is not an exhaustive list, but a few of the most prevalent frameworks that I could find.

Unit Testing Frameworks: NUnit,,MSTest, MbUnit
Moq Frameworks: NMock,RhinoMocks,Moq,NSubstitute

Until recently I had no idea what this Mocking stuff was really about. I had written unit tests but almost always I used business objects, or stubs. -There is a nice post about stubs and mocks from Martin Fowler –. So what is this thing with Mocking? Let’s see an example from the Sharpduino library.

This was the EasyFirmata class

I have omitted the irrelevant code. As you can see there is a close relationship with the com port. In order to check if the port is disposed when the EasyFirmata is disposed we cannot write any test other than believe that it will get called. There is also the problem of being dependent on a serial port being available for all the other tests. The solution to this problem is to abstract the base com port usage into an interface. Thus the ISerialProvider interface

Creating a ComPortProvider which implements ISerialProvider is very straightforward. The EasyFirmata class now becomes

Now it becomes much easier to test the proper disposal of the port. We only have to create a new class which implements ISerialProvider. For this test we just need to implement the Dispose method, so that it tracks if it has been called or not. The test then is easy to setup and execute

This was easy. But as we need to test more and more functionality, we have to write a lot more code for our Stub class. Mocks are used to spare us from this implementation and give an alternate way of doing such tests.

Instead of creating and keeping track of some state we just describe their behavior (how they respond to various stimuli -method calls,property changes,etc-) and then we verify how they reacted to the actual calls.

For example take this test:

Here we create a Mock object which implements our interface. Since we only need to check that a method was called we don’t have to setup any behaviors. We feed our object to the EasyFirmata constructor and wait for the disposal of the EasyFirmata object. We then proceed to verify if the Dispose method was called in our Mock object.

As you can see, even for our simplest example we wrote substantially less code by using a Mock framework. For more complex scenarios, this difference really makes the developer’s life easier. However, mock objects are not a panacea for all testing needs. There are scenarios where it will be much more difficult to describe a mock behavior than just creating a stub. It is the job of the developer to choose the best approach for each scenario.

BTW. Live Writer sucks. I wrote most of this post at least twice because of random crashes. And although there is an auto-recover functionality, it doesn’t always work (as I learnt the hard way). That said I will probably use it again for my next post..

Leave a Reply

Your email address will not be published. Required fields are marked *