The .NET Micro Framework enables devices to be developed using the same managed C# language and Visual Studio tools we use for all our other projects. More details about the .NET Micro Framework can be found on the Microsoft site.
At Dot Net Solutions, we have a strong belief in Agile development and XP programming. So when we started to develop for the .NET Micro Framework, we immediately looked for its support for unit testing. However, we discovered that there was no support available. Not to be deterred from our ethos, we undertook to create our own.
The .NET Micro Framework supports reflection, thereby, giving the ability to execute “Test” methods. However, the .NET Micro Framework does not provide support for custom attributes, therefore, the following is not possible:
[TestMethod] //no custom attributes
public void TestStartsWith()
{
...
}
Instead, we used a convention based approach, requiring the word “Test” to be prefixing to all test methods names. We can then use reflection to call all public instance methods starting with “Test”.
Type[] types = assembly.GetTypes();
foreach (var type in types)
{
MethodInfo[] methods =
type.GetMethods(BindingFlags.Public
|BindingFlags.Instance);
foreach (var method in methods)
{
if (method.Name.Length >= 4 &&
method.Name.Substring(0, 4) == "Test")
{
...omitted
try
{
method.Invoke(null, null);
}
catch (Exception ex)
{
result.Status = ResultType.Fail;
result.Exception = ex;
}
OnDisplayTestResult(new TestResultEventArgs
{ TestResult = result });
}
}
}
Using this naming convention for test methods and reflection to execute those methods provides part of the solution. The next challenge was to provide a host that would enable this approach to be used. Here the .NET Micro Framework does provide a solution. Our approach was to create a test harness project that would iterate all test methods in all test assemblies and execute them. The results are displayed in a custom emulator, which is set as the Deployment device for the test harness project.
This emulator provides a simple user interface, allowing the number of successful test to be seen and information on any failing tests.

There is one critical part missing and that is the ability to “Assert” the expected outcome of a test and to manage the case where this assertion fails. A simple Assert class can be created for this with a number of static methods, such as IsTrue. This enables this common unit testing syntax, e.g. Assert.IsTrue, to be used in tests:
public void TestStartsWith()
{
string _testString = "freakyKey";
Assert.IsTrue(!_testString.StartsWith("gav")
, "The string freakyKey does not start with 'gav'");
Assert.IsTrue(_testString.StartsWith("freak")
, "The string freakyKey does start with 'freak'");
}
The implementation of Assert.IsTrue is shown below:
/// <summary>
/// Assert whether the specified condition is true.
/// </summary>
/// <param name="condition">The condition to test.</param>
/// <param name="message">The message.</param>
public static void IsTrue(bool condition, string message)
{
if (!condition)
{
throw new AssertException(message);
}
}
We could have stopped there but how do we know that our framework does what we expect? We unit test it of course! We actually used our unit test framework... to test our unit test framework. Cool!
The unit test for the Assert.IsTrue method looks like this:
public void TestIsTrueAssertTrue()
{
try
{
Assert.IsTrue(true
, "This should not throw an exception");
}
catch (AssertException)
{
throw new AssertException(
"Assert.IsTrue should not throw an exception for true");
}
}
While the .NET Micro Framework does not provide support for unit testing out of the box, this should not deter you. The creation of a unit testing framework (and even testing that framework) can be achieved with a little effort.
Author: Marcus Tillett
@drmarcustillett
Tweet