XP Programming: Part 2 Testing is Fundamental
Sunday, October 8th, 2006One of the cornerstones of the type of Extreme Programming (is it more Agile Modeling?) that I am interested in pursuing is unit testing. You start with your requirements and build use cases from them. You take your use cases and build unit tests that test the functionality displayed in the use case. I want everything to be documented and the documentation to flow all the way back to the requirements document. This way, you can pursue changed requirements through the use cases and unit tests down to the objects that support them.
To get started with unit testing, grab NUnit from http://www.nunit.org/ and take it for a spin. I have used NUnit in a project before, and loved the structure that it provided. Test-driven development is when you begin your process by writing tests that cover your requirements and then write code until they all pass. Start with a simple sample testing suite:
-
using System;
-
using NUnit.Framework;
-
namespace Reservation
-
{
-
[TestFixture]
-
public class PolyscopiaUnitTests
-
{
-
-
[SetUp]
-
public void Init()
-
{
-
}
-
-
[TearDown]
-
public void Destroy()
-
{
-
}
-
-
[Test]
-
public void MigrateObject()
-
{
-
Assert.Fail("This is a test failure");
-
}
-
}
-
}
and add tests that cover your requirements. Writing good unit tests is not as easy as it sounds, it takes time and effort. While you are creating your tests, you are also defining the solution set that your program will generate. As you develop your code, your goal should be to reduce the number of tests that fail.
So how do you integrate this into your NAnt build file? This is something I have never done before, but it turns out that you would simply add a section to compile your unit test dll and then change the test block as follows:
-
<target name="compileUnitTests">
-
<csc target="library" output="${basename}UnitTests.dll" debug="${debug}">
-
<sources>
-
<include name="${basename}UnitTests.cs"/>
-
</sources>
-
<references>
-
<include name="System.dll"/>
-
<include name="System.Data.dll"/>
-
<include name="c:\Program Files (x86)\NUnit-Net-2.0 2.2.8\bin\nunit.framework.dll"/>
-
<include name="c:\Program Files (x86)\NUnit-Net-2.0 2.2.8\bin\nunit.core.extensions.dll"/>
-
<include name="c:\Program Files (x86)\NUnit-Net-2.0 2.2.8\bin\nunit.util.dll"/>
-
<include name="c:\Program Files (x86)\NUnit-Net-2.0 2.2.8\bin\nunit.testutilities.dll"/>
-
</references>
-
</csc>
-
</target>
-
-
-
<target name="test" depends="compile,compileUnitTests">
-
<nunit2>
-
<formatter type="Plain" />
-
<test assemblyname="${basename}UnitTests.dll"/>
-
</nunit2>
-
</target>
Be sure and note the reference section and the nunit2 section.
Another topic that I would like to pursue is Spec#, an extension to the C# language to allow for provable code. See: http://research.microsoft.com/specsharp/ for more information on it. I will be trying to decide how to integrate it into my process.
It is also good to note and acknowledge that the mechanisms that work for a single individual may not scale to a group of 5 or, worse yet, a group of 500. I am going to attempt to keep to procedures that appear to be scalable enough to handle groups of up to 20 programmers. I will also try and identify those pieces that I feel will have trouble scaling beyond that.