Improving Application Quality Using Test-Driven Development (TDD)

Getting Started

I will assume that you have created a new, blank, C# Windows Application, as shown in Figure 2.

Figure 2: Creating a new Windows Application using Visual Studio 2003

I mentioned earlier that TDD expects us to write test cases before we write any code. Therefore, instead of attempting to dive into the detail of developing a full-blown application, we will concentrate on developing a test case that will dictate how we might implement a small piece of functionality. This leads us to another TDD principle, borrowed from the eXtreme Programming world: do the simplest thing that could possibly work.

Writing a test case necessitates the use of the NUnit framework, so we must add a reference (using the menu Project, Add Reference) to the nunit.framework assembly as shown in Figure 3.

Figure 3: Adding a reference to the nunit.framework assembly

If you recall the first TDD principle that I mentioned, write tests first, that is our next step: we will create a new class that will act as a holder for one or more tests. The simple application that we will develop over the remainder of this article will be a simple magazine indexer. A magazine index comprises of zero or more magazines, a magazine comprises of zero or more articles.

In a production application, the architecture might end up being somewhat complex, possibly involving web access, multiple tiers, expensive databases and a lengthy development timeframe. Our example will be less complex and will be demonstrable in a very short space of time, albeit it will be bound by the fact that we are doing the simplest thing that could work.

So, the simplest thing that could work is a test case that assumes code has been written to handle our magazine indexing needs. Listing 1 presents us with the code required to create a new magazine index, add a magazine, and then check that the magazine index was created correctly. Of course, we have not written the class MagazineIndex yet, so you would be right to think that the compiler is going to complain!

Indeed, this is another TDD principle: let the compiler tell you when something is wrong. Compiler time is cheap; we can afford to let the compiler find our mistakes for us. For the sake of this demonstration, I have not worried about how an instance of MagazineIndex is actually created (there is a reason for this as we will see shortly).

namespace WinApp
{
    using System;
    using NUnit.Framework;

    [TestFixture]
    public class TestMagazine
    {
        [Test]
        public void CheckNew()
        {
            MagazineIndex cbtMagazineIndex;

            cbtMagazineIndex = null;
            Assert.IsNotNull(cbtMagazineIndex, "cbtMagazine is null!");
        }
    }
}

Listing 1: Writing Tests First, doing the simplest thing that could possibly work

Anatomy of Listing 1

Listing 1 demonstrates a number of the NUnit framework features: I have highlighted these in bold.

Firstly, we must add a reference to the NUnit Framework assembly: this gives us access to a number of attributes, such as [TestFixture] and [Test] as well as the Assert class. The Assert class is rather powerful and forms the basis of NUnit testing framework.

Secondly, we must use the NUnit attribute [TestFixture] to indicate that the following class, in this case TestMagazine, will contain test cases that NUnit should be aware of (there will be more about precisely how NUnit achieves this later in this article).

Thirdly, we must provide a method, the name of which does not matter, that is prefixed with the [Test] attribute. Methods such as these should perform a small test that uses the NUnit Assert class to indicate success or failure. The Assert class provides us with a number of methods that can be used to determine whether a test passes or fails. These are: AreEqual, AreSame, Fail, Ignore, IsFalse, IsNotNull, IsNull, IsTrue and ReferenceEquals. As you can see from Listing 1, I have used the IsNotNull method to confirm that the creation of cbtMagazineIndex took place without failure.

However, it is important to note that listing 1 does not actually compile. The first line of the CheckNew() method attempts to declare cbtMagazineIndex (cbt standing for class being tested) as an instance of the class MagazineIndex. Clearly, we have not mentioned MagazineIndex yet, hence the compiler will complain. Luckily, using the compiler helps us and it is one of TDD’s primary facets.

Use the compiler…

By examining the CheckNew() test from Listing 1, we can see that this [Test] requires a MagazineIndex class. What is the simplest thing we could do to get this line though the compiler? Well, we could simply declare an empty class, which would get us to the point where Listing 1 will compile.

namespace WinApp
{
    public class MagazineIndex
    {
    }
}

Listing 2: Empty classes can solve problems

Now that Listing 1 compiles, we know it does not do very much, what is next? Listing 1 contains a single NUnit [Test], we can use .NET’s reflection capabilities to examine assemblies (.exe or .dll) for [TestFixture] classes and [Test] methods within those classes. Indeed, NUnit is supplied with a tool that does just this; it is called NUnit-GUI.

Test Visualisation

TDD aficionados use the phrase "red/green/refactor" when practicing TDD. The colours relate to the success or failure of tests – a test that fails is considered red, and a test that passes is green. To help us manage our tests, most xUnit frameworks are supplied with a ‘test runner’ application. NUnit is no exception – if you look in C:\Program Files\NUnit 2.2\bin\ you should find nunit-gui.exe. NUnit GUI is a graphical front-end that takes a standard .NET PE format assembly, interrogates it, then allows us to run any tests contained in the assembly.

I’ll assume that you have double clicked on nunit-gui.exe and that it is running. Using Explorer (or your favourite file system navigation tool), locate the .exe that Visual Studio 2003 created (mine is in the Example\bin\Debug directory), then drag the .exe onto the NUnit-GUI window.

There is a ‘Run’ button – click on this button. Figure 4 should look familiar – this is what is known as the infamous ‘red bar’ whose partner and opposite in TDD world is the ‘green bar’.

Figure 4: NUnit’s GUI front-end

Taking a closer look at Figure 4 and we can see that the NUnit-GUI application has interrogated our WinApp.exe extracting the [TestFixture] TestMagazine and the [Test] CheckNew on the way. When the NUnit-GUI application then ran the tests, it was able to provide us with a list of Errors and Failures on the tab of the same name. Better than that, the failure message that we included in the test appears here to.

Getting the test to pass is the simple matter of creating an instance of MagazineIndex as shown in Listing 3.

[Test]
public void CheckNew()
{
    MagazineIndex cbtMagazineIndex;
    cbtMagazineIndex = new MagazineIndex();
    Assert.IsNotNull(cbtMagazineIndex, "cbtMagazine is null!");
}

Listing 3: Making the test pass

With Listing 3 in place, re-compiling and then re-running the tests through NUnit-GUI reveals Figure 5, the green bar.

Figure 5: Green bar, test OK

As we will see shortly, another TDD principle revolves around the fact that a test should fail the first time it is executed. Unfortunately, because of the blatant simplicity of this first example, the CheckNew() test actually passes!

You might also like...

Comments

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“XML is like violence - if it's not working for you, you're not using enough of it.”