Thursday, September 23, 2004 - Posts

NUnit, MbUnit & Test Driven Development

Ok, I've laid the foundation for my development environment, I'm now ready to begin writing some code. As you may remember, I came up with a set of User Stories that I will begin to start writing test cases for, because I plan on using a Test Driven Development methodology.

Before I do that though, I'll download and install NUnit & MbUnit just to compare/contrast those two software packages.

Installing MbUnit

I retrieved the latest version of MbUnit from Peli's blog entry. It was a bit confusing at first, but in all actuality quite simple. Run these programs from the cmdline.

msiexec /qb- /L install.log /x {8073D8BC-7651-4ADF-9219-F67DB3C49103}
msiexec /qb! /L uninstall.log /i http://www.testdriven.net/downloads/TestDriven.NET-0.9.651d.msi

This runs the install program, however since I'm not running as Administrator, I had to use the RunAs /user:Administrator command. The install worked ok, however it appears that the .msi file only installs for the user running it (Just Me vs. Everyone). So it didn't work for me. Instead I had to use the MakeMeAdmin.cmd from Aaron Margosis' blog, and then rerun the install.

Installing NUnit

I downloaded version 2.2 of NUnit and ran the install. No problems here using the RunAs command as the install program asks me who I want to install it for. (Everyone!).

Test Driven Development

So I begin by creating a new C# Class Library in the D:\VirtualCellar folder called Lorengo.VirtualCellar.Business.Tests. This will contain all of my test fixtures for the Lorengo.VirtualCellar.Business classes. I've decided to start with this project because my first User Story says

Wine Maintenance, we should be able to add, remove, update and view individual wines currently in our cellar.

So I create a CellarFixture class that does the following

using System;

using MbUnit.Core.Framework;
using MbUnit.Framework;
//using NUnit.Framework;

using Lorengo.VirtualCellar.Business;

namespace Lorengo.VirtualCellar.Business.Tests
{
	/// 
	/// This text fixture is used for testing the functionality of the 
	/// cellar class
	/// 
	[TestFixture("Test Fixture for testing the Cellar Class")]
	public class CellarFixture
	{
		[Test]		
		public void AddWineToCellar()
		{
			Cellar cellar = new Cellar();
			Assert.AreEqual( 0, cellar.Items.Count );
			
			Wine w = new Wine( "Hightower Cellars", 2000, "Cabernet Sauvignon" );
			cellar.Add( w );

			Assert.AreEqual( 1, cellar.Items.Count );
		}
	}
}

Basically I have an AddWineToCellar() test case that creates a new instance of a Cellar class, verifies that the number of items in the cellar are 0, creates a new Wine instances and adds it to the cellar. Finally I check to make sure that the count of items in the cellar is 1.

When I compile this, I get all sort's of errors because

  1. Lorengo.VirtualCellar.Business does not exist
  2. Class Cellar and all of it methods do not exist
  3. Class Wine does not exist.

I think there were a few more, but I've since created the code so I've lost track. (I've left out a couple of steps here, but it would take me longer to type them all than it did to code the tests and classes.

So my first round of testing (did it compile) failed, now I have to fix that.

Create The Non-Existent Classes

So I go to my Lorengo.VirtualCellar.Business project and create the following code...

Cellar.cs
using System;
using System.Collections;

namespace Lorengo.VirtualCellar.Business
{
	/// 
	/// The Cellar class mimics a cellar that a person may choose
	/// to store wine in
	/// 
	public class Cellar
	{
		/// 
		/// Constructs a Cellar object
		/// 
		public Cellar()
		{
			// Create the implementation of the items as an ArrayList
			_items = new ArrayList();
		}

		/// 
		/// The collection of items in the cellar
		/// 
		public IList Items
		{
			get { return _items; }
		}

		/// 
		/// Adds a wine to the collection of items in the cellar
		/// 
		/// 
		public void Add( Wine w )
		{
			_items.Add( w );
		}

		// Keep the private implementation as generic as possible
		private IList _items;
	}
}
And Wine.cs

 

using System;

namespace Lorengo.VirtualCellar.Business
{
	/// 
	/// The wine class represents a bottle of wine
	/// 
	public class Wine
	{
		public Wine( string name, int year, string varietal )
		{
		}
	}
}

Again, creating the minimum needed to get the code to compile. You see I do nothing with the parameters passed in the Wine constructor. At this point I compile the solution including the tests and domain classes and everything works!

Now to run my tests, with the NUnit Addin, I simply right-click on my project and say Run Test(s). Here's the output

Info: Test Execution
Info: Exploring Lorengo.VirtualCellar.Business.Tests, Version=1.0.1727.30703, Culture=neutral, PublicKeyToken=null
mbunit: Found 1 tests
mbunit: [critical-failure]
System.NullReferenceException: Object reference not set to an instance of an object.
   at MbUnit.Core.Reports.ReportBase.GetFileName(ReportResult result, String outputPath, String nameFormat, String extension) in C:\cvshome\mbunit\src\MbUnit.Core\Reports\ReportBase.cs:line 27
   at MbUnit.Core.Reports.ReportBase.Render(ReportResult result, String outputPath, String nameFormat, String extension) in C:\cvshome\mbunit\src\MbUnit.Core\Reports\ReportBase.cs:line 72
   at MbUnit.Core.Reports.ReportBase.Render(ReportResult result, String outputPath, String nameFormat) in C:\cvshome\mbunit\src\MbUnit.Core\Reports\ReportBase.cs:line 89
   at MbUnit.Core.Reports.HtmlReport.RenderToHtml(ReportResult result, String outputPath, String nameFormat) in C:\cvshome\mbunit\src\MbUnit.Core\Reports\HtmlReport.cs:line 39
   at MbUnit.AddIn.MbUnitTestRunner.GenerateReports(ITestListener testListener, Assembly assembly, AutoRunner runner)
   at MbUnit.AddIn.MbUnitTestRunner.Run(ITestListener testListener, Assembly assembly, FixtureFilter filter, RunPipeFilterBase runPipeFilter, TypeFilterBase typeFilter)
TestCase 'M:Lorengo.VirtualCellar.Business.Tests.CellarFixture.AddWineToCellar' failed: Test execution failed

Uh oh, what happened? Looks like MbUnit didn't like something, I'll have to investigate that...

Let's switch over and see what NUnit does, I'll comment out the MBUnit usings and uncomment the NUnit usings... It also turns out that NUnit doesn't support the idea of a comment for the TestFixture attribute so I'll remove the comment and just put [TestFixture]. Now, recompile, open the NUnit GUI and run the tests...

WooHoo! My test worked in NUnit. That's about all for this post

In Conclusion

I need to troubleshoot why MbUnit is failing. It could be a permission problem, it could be something else, I'll have to step through the process again.

With regard to Test Driven development, this was a simple example, I can tell right now, that I'll need to rethink my business model a little bit. More on that tomorrow.

with 0 Comments

Installing Nant

As part of preparing to write some code for the Virtual Cellar, I've installed a source code provider (SubVersion), VS2003, and now I will be installing Nant.

I've chosen to download version 0.84 and unzipped it to the d:\nant-0.84 folder. I'll want to setup a NANT_HOME environment variable that points to this folder, and then modify my path to contain the %NANT_HOME%\bin folder so that I can run Nant from any directory.

Specifying a NANT_HOME environment variable will allow me have multiple versions of Nant on my machine without having to change my scripts.

After doing the above I can test my Nant Installation by typing:

d:>nant
NAnt 0.84 (Build 0.84.1455.0; net-1.0.win32; release; 12/26/2003)
Copyright (C) 2001-2003 Gerry Shaw
http://nant.sourceforge.net

BUILD FAILED

Could not find a '*.build' file in 'D:\'

For more information regarding the cause of the build failure, enable log4net us
ing the instructions in NAnt.exe.config and run the build again.

Try 'nant -help' for more information

It all looks good. The next step will be to create a new VS2003 solution for the VirtualCellar system. I'll go ahead an create the following projects and folder structure.

d:\VirtualCellar\Lorengo.VirtualCellar.Business
This will contain all of the domain model classes for the application

d:\VirtualCellar\Lorengo.VirtualCellar.UI.Console
This will contain all of the UI code for the console version of the application.

Of course all this code will then be added to the Subversion repository

Tomorrow, I'll go ahead and install NUnit (and maybe MbUnit) and begin writing tests for my first User Story.

with 2 Comments