Many of you have read or heard me talk about NUnit, the open source testing tool from www.nunit.org. And, long-time readers of this column or my books will know that I have written about project templates in .NET before. In this two-part article, I would like to combine both technologies and demonstrate a practical application for project templates that incorporate a NUnit project with TraceListeners yielding a new project template, the Test Project.
If you have read any of the aforementioned articles, rest assured that you may both use those articles for cross-reference, and I have included some completely new material herein. If you are very comfortable with any one or more sections of either parts of this two-part article, feel free to skip that section.
In this part of the article, I will demonstrate how to create a prototype for our project template; copy a closely-related, existing project template; and convert our prototypical class into a template class. In Part 2, I will show you how to modify the custom JScript used by the .NET project Wizard (vsWizard.dll), define the wizard launch file, notify the wizard of the new template, and test the final product.
Creating an Example Project
I test everything I write. I used to refer to this testing as scaffolding. Scaffolding is literally where extra test code is added to my product code. The scaffold is comprised of methods that create objects and invoke behaviors, looking for a predetermined result. A few other authors used the term scaffolding before me but it never really caught on.
NUnit is like scaffolding. NUnit uses Reflection in .NET to load and create objects and methods attributed with custom attributes defined by the NUnit framework. NUnit then can load the class library and invoke operations on these attributed classes and methods. The methods themselves can be simple or complex and just about anything. An enhancement I like—and maybe one that should be added to NUnit, which is open source after all—is a custom TraceListener.
A custom TraceListener permits me to send debug statements—Trace.WriteLine—from my product-code to the NUnit console window. Consequently, I have the option of relying on the very simple Red-Green Fail-Pass color coding prescribed by NUnit or a more detailed examination of test results in NUnit's Console.Out window.
Listing 1 demonstrates a stubbed NUnit test project containing all of these elements. To recap: The listing is part of a Class Library that includes a reference to the NUnit.Framework.dll from NUnit version 2.1, a custom TraceListener, and some basic setup and teardown scaffolding. This prototype code will become our project template in Part 2.
Listing 1: An NUnit stub class library with a custom TraceListener.
Imports NUnit.Framework Imports System.Diagnostics Friend Class MyListener Inherits TraceListener Public Overloads Overrides Sub Write(ByVal message As String) Console.Write(message) End Sub Public Overloads Overrides Sub WriteLine(ByVal message As String) Console.WriteLine(message) End Sub End Class <TestFixture()> _ Public Class Test Private Shared listener As MyListener = New MyListener <SetUp()> _ Public Sub Init() If (Not Trace.Listeners.Contains(listener)) Then Trace.Listeners.Add(listener) End If End Sub <TearDown()> _ Public Sub Deinit() If (Trace.Listeners.Contains(listener)) Then Trace.Listeners.Remove(listener) End If End Sub <Test()> _ Public Sub Test1() Assertion.Assert("Add a boolean test here", False) End Sub <Test()> _ Public Sub Test2() Assertion.Fail("Intentionally fail if this code is run") End Sub <Ignore("Not ready yet!")> _ Public Sub Test3() ' Change the attribute from Ignore to Test ' when this test is finished End Sub End Class
After creating the Class Library, the next step was to add a reference to NUnit.Framework.dll. Of course, you will need to go to nunit.org and download the latest version of NUnit before you can reference that assembly. The next step is to add an Imports statement for the NUnit.Framework and System.Diagnostics namespaces. Next, I created an internal class called MyListener; MyListener implements the abstract base class TraceListener via inheritance. Finally, the test class is stubbed out.
You can add more than one test class, but for NUnit to find your test classes you need to attribute each with the TestFixtureAttribute, as demonstrated in the listing. Next, a shared instance of MyListener was added. Because the field, listener, is shared, we will only get (and we only need) one instance of the listener. The arbitrarily named Init and Deinit methods are run one time each, for each test. The SetUpAttribute indicates that Init should be run immediately before a test, and the TearDownAttribute indicates that the Deinit method should be run when a test has completed. These two methods add and remove the customer listener, respectively. To complete the class, I added some sample test methods, demonstrating some features of NUnit, such as the Test and Ignore attributes and NUnit's Assertion class. This pre-canned code will speed up writing test classes.
Make sure that you compile and test the prototype code. The results in NUnit should look something like those shown in Figure 1. (Keep in mind that the prototype intentionally fails or ignores, but green is the color we are shooting for in actual tests.)
Figure 1: Our prototype NUnit class works as coded.