25 July 2008

Shared code development and easy unit testing with Compact Framework

Microsoft made developing for the Compact Framework relatively easy. Everyone with experience in .NET development can easily take the plunge into mobile development by downloading the Windows Mobile SDK 6.x and go on as if you are just working in the full framework. You will notice some restrictions, not everything you might want to use is available, programs running on mobile device face some very specific challenges, but then again, the development experience is quite seamless.

Some things remain a bit cumbersome. Unit testing can be a real PITA, and you cannot binary reuse code, so if your shop (like mine) uses some utilities that are distributed as binary components, they will have to be recompiled specifically for the Compact Framework and someone has to keep the CF and Full version in sync.

Fortunately Visual Studio sports an almost hidden feature that can make life a lot easier for Mobile developers. The following procedure assumes that you have Visual Studio 2008 professional edition and the Windows mobile 6 SDK installed. For unit testing I use NUnit and Testdriven.NET to launch it from Visual Studio, but you can of course use anything you like

1. Make a new empty solution
Let's call it "SharedCode"

2. Add a new Smart Device application
Select Add/new project/Smart Device
Use "MyMobileApp" as name
Select Smart Device, Windows Mobile 6.0 professional SDK, and Compact Framework 3.5 although for this sample only the first option is really important.

3. Add another Smart Device application
Select Add/new project/Smart Device
Use "MyMobileLib" as name
Select Class Library, Windows Mobile 6.0 professional SDK, and Compact Framework 3.5

4. Add two Windows Class library projects
These must be full framework projects, not mobile projects.
Call the first one "MyLib" and the second one "MyLib.Test". Select .NET framework 3.5 as target framework

5. Add a new class to the MyMobileLib assembly
For this example, we will use a trivial calculator class:
namespace MyMobileLib
{
public class Calculator
{
private int Num1;
private int Num2;

public Calculator(int num1, int num2)
{
Num1 = num1;
Num2 = num2;
}

public int Add()
{
return Num1 + Num2;
}

public int Subtract()
{
return Num1 - Num2;
}
}
}

6. Add as link to the MyLib library
Go to the MyLib library and remove the default generated "Class1.cs" file.
Then right-click the project and select "Add/Existing Item".
And now for the piece the resistance:
Browse one directory up, then down into the MyMobileLib directory, and select the Calculator.cs file.
Now look carefully to the "Add" button down right. It will sport a hard-to-spot small arrow pointing downwards:
If you click that, you will get two options: Add and Add as link. That is what I mean by "an almost hidden feature". Select "Add as link" and you will see that "Calculator.cs" is added to the MyLib project, but that the document icon has a shortcut arrow overlay:







7. Add references
Right-click the MyMobileApp project
Select "Add Reference", click Tab "projects" and select the "MyMobileLib" project

Right-click the MyLib.Test project
Select "Add Reference", click Tab "projects" and select the "MyLib" project

8. Define unit test in de MyLib.Test project
Rename the default Class.cs file in MyLib.Test to "TestCalculator.cs".
Since I use NUnit, I have to make a reference to the nunit.framework.dll which sits somewhere on my system. Then I can create the world shocking ;-) test
using MyMobileLib;
using NUnit.Framework;

namespace MyLib.Test
{
[TestFixture]
public class TestCalculator
{
[Test]
public void TestCalc1()
{
Calculator c = new Calculator(3,2);
Assert.AreEqual(5, c.Add());
Assert.AreEqual(1, c.Subtract());
}
}
}
which will undoubtly work. But my point is: you can simply run units tests out of the Windows Mobile scope, inside Visual Studio

9. Test the library on the mobile device
For the sake of brevity: drag a label onto the form.
Open the Form1.cs, and add to the code on the form:
using System.Windows.Forms;
using MyMobileLib;

namespace MyMobileApp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Calculator c = new Calculator(3, 2);
label1.Text = "3 + 2 = " + c.Add()
;
}
}
}
If you run this, open pops the Windows Mobile emulator and the form will show the 'surprising' message "3 + 2 = 5".

Conclusion
While the sample was trivial, it showed two things:
  • For general purpose classes, you can develop code and generate binaries for both Compact and full framework using a single code file

  • Unit testing of general purposes classes can be done outside a Windows Mobile emulator and becomes a lot easier this way



Complete code downloadable here.