Running NUnit in the Windows Azure Emulator
If there is an easier way to do what I am about to describe, someone please me. I am guessing there is some clever way to use cspack and csrun to allow me to run NUnit in the Azure emulator, but for the life of me I can’t get it to work. Therefore, I am using this admittedly goofy approach.
Disclaimer: The approach is tailored to a web role. The sample code is really a proof of concept.
Basic Approach
My basic approach is to copy the output from my test project into a subdirectory beneath the bin folder of my main web role (bin/test). Instead of using a test runner – in my case TestDriven .NET – I run my web role. There is a page on my site that will run NUnit and output the test results to the browser. If I need to, I can put break points in my tests and the debugger will let me step into the code.
Initial Setup
1. In the bin directory of your web role, create a sub-directory called test. In my case this is /TestSiteWebRole/bin/test.
2. Add a post-build event to your test project (replacing TestSiteWebRole with your project):
copy “$(TargetDir)*.*” “$(SolutionDir)TestSiteWebRole\bin\test”
3. In your web role add references to nunit.core.dll and nunit.core.interfaces.dll.
Adding a Test Runner Page (or Running NUnit from Code)
4. Add a page to your web role. In the example code, this is NUnit.aspx. There are several horrors to behold here. One, my example code is using WebForms. Two, there are a bunch of hardcoded references in it. I’m leaving it up to you to take this code beyond a POC.
public partial class NUnit : Page
{
protected void Page_Load(object sender, EventArgs e)
{
RunTests();
}
private void RunTests()
{
CoreExtensions.Host.InitializeService();
string testPath = Server.MapPath("bin/test");
string testAssemblyPath = Path.Combine(testPath, "TestSite.Tests.dll");
var package = new TestPackage(testAssemblyPath);
var builder = new TestSuiteBuilder();
var suite = builder.Build(package);
var result = suite.Run(new MyListener(Response), TestFilter.Empty);
}
5. The NUnit page uses another class called MyListener. This is just a class that implements NUnit.Core.EventListener (which is an interface). My implementation is about as simple as you can get. I am sure you can do much better.
public class MyListener : EventListener
{
private readonly HttpResponse _response;
public MyListener(HttpResponse response)
{
_response = response;
}
public void RunStarted(string name, int testCount)
{
_response.Write(name);
}
public void RunFinished(TestResult result)
{
}
public void RunFinished(Exception exception)
{
}
public void TestStarted(TestName testName)
{
Print("<p/>");
Print("{0}", testName.Name);
}
public void TestFinished(TestResult result)
{
if (result.ResultState == ResultState.Failure)
{
Print("FAILED");
Print(result.StackTrace);
}
else if (result.ResultState == ResultState.Success)
{
Print("SUCCESS");
}
else
{
// do something phenomenal here
}
Print(result.Message);
}
public void SuiteStarted(TestName testName)
{
}
public void SuiteFinished(TestResult result)
{
}
public void UnhandledException(Exception exception)
{
}
public void TestOutput(TestOutput testOutput)
{
}
private void Print(string msg)
{
_response.Write(msg);
_response.Write("<br />");
}
private void Print(string msg, params string[] args)
{
_response.Write(string.Format(msg, args));
_response.Write("<br />");
}
}
The test project contains one test:
[Test]
public void role_environment_is_available()
{
Assert.IsTrue(RoleEnvironment.IsAvailable);
}
If everything is set up correctly. You should get the following output when you run the NUnit page:
role_environment_is_available
SUCCESS
