Library tutorials & articles

Improving Application Quality Using Test-Driven Development (TDD)

Adding Functionality

What we’ve seen so far, whilst sound TDD practices, hasn’t resulted in much demonstrable code. We know that MagazineIndex is going to manage a collection of zero or more instances of the class Magazine, so it stands to reason that we might have an AddMagazine method. So let us set about writing the test for AddMagazine.

Listing 4 presents our new test case – remember, we must write our tests before we write any implementation code! I’ve done the simplest thing possible, added CheckAddMagazine that creates an instance of MagazineIndex, adds a magazine name, and then checks that the magazine name was added correctly. Listing 4 is not going to compile – there’s no AddMagazine method defined, nor is there an IsMember function.

[Test]
public void CheckAddMagazine()
{
    MagazineIndex cbtMagazineIndex;
    cbtMagazineIndex = new MagazineIndex();
    cbtMagazineIndex.AddMagazine("Methods & Tools");
    Assert.IsTrue(cbtMagazineIndex.IsMember("Methods & Tools"), "Magazine was not added to collection!");
}

Listing 4: Adding functionality

Doing the simplest thing to Listing 2 will allow our new test in Listing 4 to compile. This means adding the AddMagazine and IsMember methods to the class MagazineIndex. Listing 5 presents MagazineIndex with these modifications.

namespace WinApp
{

    public class MagazineIndex
    {

        public void AddMagazine(string MagazineName)
        {
        }

        public bool IsMember(string MagazineName)
        {
            return false;
        }
    }
}

Listing 5: Doing the simplest thing

With Listing 5 in place, we can re-compile the solution and re-run the test. Prepare yourself for some bad news.

Figure 6: Red bar, test fails

Bad news, the test failed. What do we need to do in order to fix this? What might move us in the right direction would be a change to the AddMagazine and the IsMember methods, and the introduction of a string called MagazineList, this is the simplest thing. Listing 6 presents the updated MagazineIndex class.

public class MagazineIndex
{

    private string MagazineList;
    public void AddMagazine(string MagazineName)
    {
        MagazineList = MagazineName;
    }

    public bool IsMember(string MagazineName)
    {
        return MagazineList == MagazineName;
    }

}

Listing 6: Small steps, tests pass

Figure 7: One magazine, the test passes

Adding Two Magazines

Like all good developers, we will write some test code that exercises adding more than one magazine. Listing 7 presents a new test that does just this.

[Test]
public void CheckAddTwoMagazines()
{
    MagazineIndex cbtMagazineIndex;
    cbtMagazineIndex = new MagazineIndex();
    cbtMagazineIndex.AddMagazine("Methods & Tools");
    cbtMagazineIndex.AddMagazine("The Delphi Magazine");

    Assert.IsTrue(cbtMagazineIndex.IsMember("Methods & Tools"), "M&T was not added to collection!");
    Assert.IsTrue(cbtMagazineIndex.IsMember("The Delphi Magazine"), "TDM was not added to collection!");
}

Listing 7: Adding two magazines to the collection

Figure 8: Two magazines, the test fails

Our simple approach of using a string to manage the MagazineList has caused a test to fail. That is part of the TDD process – let the tests dictate (drive) which code is developed and how it is developed. In this case, CheckAddTwoMagazines dictates that we need to develop a collection or list of some sort to replace the simple string. The TDD mantra of "red, green, refactor" seems to stand true. It is time to refactor the AddMagazine and IsMember methods.

namespace WinApp
{
    using System.Collections;

    public class MagazineIndex
    {

        private ArrayList MagazineList = new ArrayList();

        public void AddMagazine(string MagazineName)
        {
            MagazineList.Add(MagazineName);
        }

        public bool IsMember(string MagazineName)
        {
            return (MagazineList.Contains(MagazineName));
        }
    }
}

Listing 8: Introducing an ArrayList

After the introduction of Listing 8 , re-compiling and re-running the tests reveals Figure 9 and a green bar.

Figure 9: Two magazines and a green bar

ArrayLists in .NET languages are a useful mechanism that allows us to manage groups of object references, in our case strings. An ArrayList has the ability to grow as new object references are added – hence it is the ideal abstraction for managing a collection of magazine titles. ArrayLists support useful methods like Add, Insert, Remove, and conveniently for us a Contains method (we have used this in our IsMember implementation.)

Comments

  1. 05 Sep 2009 at 19:25

    Great article Craig. Well written.

    One slight amend however, I believe Setup / Teardown attributes are run once before / after each test, and the SetUpFixture / TearDownFixture attributes are called once for the TestFixture class at creation / distruction.

  2. 24 Dec 2008 at 21:42
  3. 07 Aug 2007 at 18:28
    This article is very well documented for a person like me who is new in test driven development. Thanks.
  4. 01 Jan 1999 at 00:00

Leave a comment

Sign in or Join us (it's free).

Craig Murphy
AddThis

Related podcasts

  • Vote of No Confidence

    In this episode Ward Bell (from IdeaBlade) and Jeremy Miller discuss the Vote of No Confidence on Microsoft's Entity Framework and what it means for the Alt.NET and .NET communities.This episode does not have a sponsor, so if you are interested in sponsoring the podcast please contact us.Ward and...

Events coming up

  • Nov 18

    15 Minutes of Fame

    Dresher, United States

    This is a yearly tradition. We select 10 of the favorite speakers from monthly meetings, code camps, and hands on labs. Each one does a 15 minute talk on their favorite .NET technology. This is our 10th anniversary so we plan a gala event with special prizes and refreshments.

Want to stay in touch with what's going on? Follow us on twitter!