Getting Started with TDD using MbUnit and C# and VB.NET

There is a lot being written about Test Driven Development in the .NET world.  So much so that it can seem overwhelming to absorb, and you always feel like you’re entering in the middle of the conversation.  Yep, me too, even four years ago when I first dipped my toe into the TDD pool.

After a couple years in SSRS/BI-land, it’s back to regular development, and back into the TDD pool.  The pool has matured–there are new tools, stronger opinions, and much more conversation.  Essentially, I’m starting over, but with a little experience.  In this post, I’ll show you what I’m setting up, and how to get started with a simple project.

What to use?

There are a number of applications available, each with its own adherents and detractors.  Some are free, some you buy.  If you have Visual Studio 2008 Professional or better, you have a testing tool built in.

I tried a couple tools getting started, including NUnit and MbUnit.  I preferred MbUnit, so I downloaded the latest version, part of the Gallio Automation platform.  Gallio/MbUnit is one of the more popular TDD applications.  It’s well supported and well documented, which helps greatly.

So what is Gallio and MbUnit?  Simply understated, MbUnit v3 is a set of classes for unit testing, and Gallio is what actually runs the tests and displays the results.  Gallio can run more tests than just MbUnit, and integrates with build tools.

Installation was a snap–I downloaded the installer and let it run.  Gallio integrated with VS 2005 and VS 2008 automatically, but had an issue loading a language pack when I started VS 2008.

Planning what you’re coding

Before you start hacking away on the keyboard, you need to figure out what you’re writing.  You can use whatever project management methodology you want.  Here’s a user story for something I encountered recently:

For our space utilization analysis, I need to be able to easily take an order date, and figure out the date the week ends on, so I can accumulate inventory changes to the same base date.  I need to be able to specify the end date, since calendar and fiscal weeks may have different end days.  Dates should be calculated back from the given date.  If the the weekday of the given date, and the week end day are the same, then the given date should be used.

Test first!

One of the tenants of TDD is writing your tests first, called the “red, green, refactor” cycle of development.  Red refers to a test which fails, green refers to a test which passes, and refactor refers to reworking the code you wrote to make the test pass to make it leaner.  This takes some realignment of your thought process, but gets easier as you do it.

Open Visual Studio, and create a new project.  I’m calling mine DateLibrary, since I’m actually creating a library of date functions useful to me.  Delete the automatically created Class1.

We need to separate the tests from the code we’ll use in our applications, so our tests don’t end up as part of the application.  Add a second class to the solution, called DateLibraryTests to contain the tests.  Again, delete Class1, and add one named WeekEndTest.  Add references to your class library project, Gallio and MbUnit, and then add using statements, as shown:

C#:

using System;
using DateLibrary;
using MbUnit.Framework;

VB.NET:

Imports System
Imports DateLibrary
Imports MbUnit.Framework

Now, let’s write our first test.  To reiterate, one of the tenants of TDD is writing your tests first.  Realistically, you might need to write a little application code first.  I prefer to have a little Intellisense guide my test writing, so I just stub out a class and methods, just enough so my app will compile, but no actual code.  In our example, we need to return something, so we just return a blank date and time.  Here’s the code stub:

C#:

using System;
namespace DateLibrary
{
    public class WeekEnd
    {
        public static DateTime BackDate(DayOfWeek EndDay, DateTime FromDate)
        {
            DateTime _backdate = new DateTime();

            return _backdate;
        }
    }
}

VB.NET:

Imports System

Public Class DateLibrary

    Public Function BackDate(ByVal EndDay As DayOfWeek, ByVal FromDate As Date) As Date
        Dim _backdate As New Date

        Return _backdate
    End Function

End Class

The first parameter of our method is the day to figure back to, and the second is the date to figure from.  We use a DayOfWeek for the first parameter to limit input values.

One of the criticisms of TDD is that everything you want to test must be public, since tests are placed in a separate class.  So if you plan on having private methods and classes, you’re either out of luck, or you can change the modifier after your tests are run, have public accessors to your private methods, or include test code in your application.  What you do is up to you, based on the local coding standards and application design.  For this sample, public methods are just fine.

Now we write our test.  In TDD, Assert basically means “I am expecting these values…”.  So, our test case could be thought of as “I am expecting these values are equal”.  The values to be compared are the one we’ll calculate from our code above, using inputs which we already know the answer to, and the answer we already know.  Our test looks like this:

C#:

using System;
using DateLibrary;
using MbUnit.Framework;

namespace DateLibrary
{
    public class WeekEndTest
    {
        [Test]
        public void WeekEndsSunday()
        {
            Assert.AreEqual(new DateTime(2009, 06, 21), WeekEnd.BackDate(DayOfWeek.Sunday, new DateTime(2009, 06, 25)));
        }
    }
}

VB.NET:

Imports System
Imports DateLibrary
Imports MbUnit.Framework

Public Class WeekEndTest

    <Test()> _
    Public Sub WeekEndsSunday()
        Assert.AreEqual(CType(<span class="str">"6/21/2009", Date), WeekEnd.BackDate(DayOfWeek.Sunday, <span class="str">"6/25/2009"))
    End Sub

End Class

The [Test] attribute is used by the test runner to find the tests from the regular methods.

Make sure the solution compiles without errors.  If it does, it’s time to run our tests.  Gallio/MbUnit includes the Icarus test runner, which provides easy to read graphical feedback.  To start Icarus, navigate Start >> All Programs >> Gallio >> Icarus GUI Test Runner.  Once Icarus has started, we need to load in our tests.  Go to Project >> Add Assemblies, navigate to the bin folder of your test project, select the test DLL and click Open.

SS-2009.06.27-15.15.12

The tests will be parsed, and listed in a treeview.  You can add as many test DLLs as you need, we just have the one for this example.

SS-2009.06.25-22.30.57

Click the Start button, and our tests will be run.  The Execution Log shows the results, in this case, red, just like we expected.

SS-2009.06.25-22.34.37

Further down, you can see the expected and returned values.  Our test failed (as expected) because a blank date was returned, and did not match the expected value.

SS-2009.06.26-20.26.48

Great.  Like we said above, “red, green, refactor”.  We now have red taken care of.  Before we do anything else, let’s do a quick sanity check to make sure all systems are correct.  In our test, we’re expecting the returned value to be 6/21/2009.  As a test of our tests, let’s change our procedure slightly to make sure it returns the expected date, and run our test again.  The results should be green.

C#:

using System;

namespace DateLibrary
{
    public class WeekEnd
    {
        public static DateTime BackDate(DayOfWeek EndDay, DateTime FromDate)
        {
            DateTime _backdate = new DateTime(2009, 06, 21);

            return _backdate;
        }
    }
}

VB.NET:

Imports System

Public Class WeekEnd

    Public Shared Function BackDate(ByVal EndDay As DayOfWeek, ByVal FromDate As Date) As Date
        Dim _backdate As New Date

        _backdate = "6/21/2009"

        Return _backdate
    End Function

End Class

Sure enough, our results are green.  This does not satisfy the green portion of “red, green, refactor”, this is merely to confirm our systems are working correctly.

SS-2009.06.26-20.34.03

Now it’s time to write some actual application code, and have our test be green for real.  From the user story above, we arrive at the following code:

C#:

using System;

namespace DateLibrary
{
    public class WeekEnd
    {
        public static DateTime BackDate(DayOfWeek EndDay, DateTime FromDate)
        {
            DateTime _backdate = new DateTime();
            int _dayOfWeek = new int();

            _dayOfWeek = (int)EndDay;

            if (FromDate.DayOfWeek == EndDay)
            {
                _backdate = FromDate;
            }
            else if ((int)FromDate.DayOfWeek &gt; (int)EndDay)
            {
                _backdate = FromDate.AddDays(-(int)FromDate.DayOfWeek - (int)EndDay);
            }
            else
            {
                _backdate = FromDate.AddDays(-(int)EndDay - (int)FromDate.DayOfWeek);
            }

            return _backdate;
        }
    }
}

VB.NET:

Imports System

Public Class WeekEnd

    Public Shared Function BackDate(ByVal EndDay As DayOfWeek, ByVal FromDate As Date) As Date

        Dim _backdate As New Date()
        Dim _dayOfWeek As New Integer()

        _dayOfWeek = CInt(EndDay)

        If FromDate.DayOfWeek = EndDay Then
            _backdate = FromDate
        ElseIf CInt(FromDate.DayOfWeek) &gt; CInt(EndDay) Then
            _backdate = FromDate.AddDays(-CInt(FromDate.DayOfWeek) - CInt(EndDay))
        Else
            _backdate = FromDate.AddDays(-CInt(EndDay) - CInt(FromDate.DayOfWeek))
        End If

        Return _backdate
    End Function

End Class

Now, we run our test again, to make sure our code does what we think it will do:

SS-2009.06.27-15.21.09

 

Success!  This time, we’re green for real.  The final part of the TDD is to refactor.  Refactoring is a process of editing your code to make it more concise, more maintainable, and more reusable.  It’s not an entirely simple process, requiring a good deal of thought.  The best part about TDD is that as you refactor, you can easily tell if you’ve broken your code by running your tests again.  It’s a process we won’t cover here.

 

 

 

 

For more information

To learn about and download MbUnit and Gallio, go to http://www.gallio.org/.

For a deeper look into TDD, the book recognized as starting it all is Test Driven Development By Example, by Kent Beck.  The examples are in Java and JUnit, but this is the book recognized as the authoritative work on TDD.

If you’d prefer to have examples in .NET, you might like Test Driven Development in Microsoft .NET.  James Newkirk is a leader in Agile development, and is one of the founders of NUnit and xUnit.

DotNetKicks Image

June 15, 2009 – MSDN Freedom Roadshow in Pittsburgh

Session 1: Developing on Microsoft Windows 7

Building applications that are easy to use, visually appealing, and offer high performance is a challenge that developers face every day. Innovative applications can greatly improve the user experience, empowering companies to differentiate their services and solutions. However, developers are increasingly asked to do more in less time, while also optimizing the power and performance requirements of their applications. 

The Windows 7 platform makes it easy for developers to create engaging, user-friendly applications by providing familiar tools and rich development features that allow them to take advantage of the latest PC capabilities.  In this session we will explore the new Taskbar and Jump Lists, the Scenic Ribbon, file management with Libraries, and Windows Web Services among many other enhancements to the new operating system.


Session 2: What’s New in Internet Explorer 8 for Developers

With any new browser release, there are two questions of interest to most web developers –
     1.Will this release break my site, and if so, how do I fix it?
     2. What shiny new features does it offer to add value for my visitors?

In this session, we’ll address both of these questions, first showing how developers and users both benefit from improved standards-based rendering in Internet Explorer 8, and how developers can ensure that their sites will render properly for users using IE8. Additionally, we’ll take a look at some of the new features of Internet Explorer 8 that open up new possibilities for web developers, including Accelerators, Web Slices, and Search Providers, as well as AJAX and DOM improvements. Accelerators are helpers added to the browser that allow users to access your web-based services from anywhere, via a simple right-click on any page. Web Slices allow you to designate parts of your application for the user to consume and keep up-to-date in the browser without having to visit the full site. You can leverage these features to add value to your site and make it easier than ever for users to take advantage of the services and content you have to offer. 
 
We'll also look at the new Internet Explorer 8 Developer Tools, which provides you with killer tools for examining and debugging your HTML, CSS, and JavaScript, all without ever leaving the page, plus profiling for finding and fixing the performance bottlenecks in your client-side code. The IE 8 Developer Tools also aid in compatibility testing, by allowing you to change the layout and compatibility modes on the fly. Lastly we’ll look at some best practices.

Session 3: Making JavaScript Fun Again

Let’s face it; most web developers avoid JavaScript at all cost. We do everything we can do avoid it and if we can’t, we typically try to keep things as simple as possible just to write the least amount of JavaScript code possible. This hinders us from creating the best user experience possible which translates to unhappy/unsatisfied users.

Well, you don’t have to avoid it any more. Thanks to jQuery, writing JavaScript code is fun again. In the session we are going to go over the basics of jQuery. I will show you how easy it is to traverse the document object model (DOM), add animation to your UI, handle events and add AJAX functionality to your web applications. Finally, we will discuss the support Visual Studio provides for working with jQuery as well as its integration with ASP.Net

Full info at http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032415478&Culture=en-US

Pgh.NET: Programming Silverlight in the Cloud

Join the Pgh.NET User Group on June 9 as Vijay Koneru gives an overview of programming Silverlight applications using the Azure Cloud Services API. Also, Craig Oaks will provide an introduction to using Silverlight with ArcGIS.

Date:     Tuesday, June 9
Time:     5:30 – 8 p.m.    
Venue:    Microsoft Offices, 30 Isabella Street, 15212

Register: http://webportal.pghtech.org/Events/CalendarEventsListView.aspx

DotNetKicks Image