TestRunner for Visual Studio 2005 Manual

Test Driven Development

TestRunner has a pretty simple philosophy about Test Driven Development - it's a good idea. The basic assumption is that TDD is primarily a way of coding, and coding is primarily done in the editor. TestRunner is set up to let you stay in the editor while you code and test combining Visual Studio with NUnit. The tool windows, in-editor-markers, and output window content are there to argument the editing activity. The goal of TestRunner for TDD is to allow you to keep flow, by saving you the interruption of shelling out to an external tool for testing.

Recommended Setup

Watching folks use TestRunner, the favored setup is Visual Studio, maximized on one monitor to display the editor, with the TestRunner, Solution Explorer, and Output windows neatly arranged on a second monitor. This lets you see a lot of code, or use the editor split panel to look at your code and test simultaneously, with the text output and tool window metadata visible, but not in the way. If you don't have a second monitor, it all still works, you just dock the tool windows and output around your editor, and have a slightly smaller editor coding space as a consequence.

Getting Leverage

With your windows arranged, it's time to code. The benefit with TestRunner is that it lets you get leverage over Visual Studio and NUnit, making it take less of your effort to test. This is through hotkeys, context menus, and visualization tools wrapped into the coding experience.

Let's Go

Start a new class library project, and refer to NUnit. For TDD use, the TestRunner tool window is a completely optional matter of personal preference. You can drive all test cases directly from the editor.

We'll be building a really boring class that builds a string of counting numbers 1 2 3... Not exactly a mind bender, but it will serve multiple purposes of showing code coverage as well as performance tracking.

Create a new class that will be tested, put a method on it to declare it's 'interface' with no implementation. This gets us to a point of declaring our intentions and call signature to get Visual Studio code completion to work for us. Create a corresponding test class that will assert that our counting number generator can count to 10. We'll start off with the test failing, but that still be compiled by throwing a not implemented. Here is the code:

using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;

namespace ClassLibrary {
    public class CountingNumbers {
        public string Count(int to) {
            throw new NotImplementedException();
        }
    }

    [TestFixture]
    public class TestCounting {

        [Test]
        public void ToTen() {
            Assert.AreEqual(
                "1 2 3 4 5 6 7 8 9 10",
                new CountingNumbers().Count(10));
        }
    }
}        
        

Now, you can run your test directly from the editor with a chord hotkey Ctrl-R, T (run test) if your cursor it directly inside a test method, or a whole fixture if your cursor is in the containing class. Try that now, TestRunner will compile, load, and run your test case for you automatically, saving you steps. TestRunner is integrated with the editor and can tell when the project is dirty and in need of a rebuild before a test run.

You get instant and directive feedback from TestRunner when a test fails. Notice the large red dot on the failing test case, along with the 'fingers' marking the line that actually caused the failure in the gutter.

This is a really handy feature, and should be pointed out. Rather than wading through a stack trace, looking up a line number, finding the error... TestRunner does it for you, marking the source line that failed both in the test case assertion and at the root, in this case where an exception was thrown. You can see this directly in the editor, as well as from the context menu in the TestRunner tree where you can navigate to errors.

Now, if you hover your mouse inside the test case, generally near the marker 'dot', over the whitespace you'll see the stack trace for that test for you and display it in a tooltip. Rather than you finding a place in code based on the stack trace, TestRunner finds the stack trace based on your place in code. Again, you can keep right in the editor coding and NUnit brings data to you.

Get It Green

Now let's get the test passing by putting together a string append sequence to count. We'll tie off the last space with a trim. Here is the code, nothing fancy:

using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;

namespace ClassLibrary {
    public class CountingNumbers {
        public string Count(int to) {
            string ret = "";
            for (int i = 1; i <= to; i++) {
                ret += i;
                ret += " ";
            }
            return ret.Trim();
        }
    }

    [TestFixture]
    public class TestCounting {

        [Test]
        public void ToTen() {
            Assert.AreEqual(
                "1 2 3 4 5 6 7 8 9 10",
                new CountingNumbers().Count(10));
        }
    }
}        
        

And now TestRunner will mark the test passing. And, pointing out another way to run and debug tests. You can right click inside a test case and run from the context menu.

Debugging

TestRunner will automatically build, attach a debugger, run your test case, and stop on your breakpoints, handy when something isn't passing and you have no idea why. This is substantially streamlined compared to attaching a debugger to NUnit-Gui.

Recap

We went from red to green on a simple class, with not a lot to refactor yet. We have 100% coverage as noted by the line markers in the gutter. We know how to test and debug. There are a lot of options to run tests, from the editor, from the TestRunner tool window, and from Solution Explorer, covered under running tests.