The previous post in this series covered downloading and installing the NUnit testing library for .NET. In this post we will:

         Create a new class library project

         Create a new unit testing project

         Create a new test

         Build the solution

         Pass the test

So let’s get started.

Launch Microsoft Visual Studio and create a new “Class Library” project and name it “BookStore”.

image001

Delete the existing Class1.cs file.

image003

Right-Click on the Solution in the Solution Explorer and SelectAdd > New Project”.

image005

Select a “Class Library” project and name it “BookStoreTests”.

image007

Once again, delete the existing Class1.cs file.

Now that the environment is ready,

Right-Click on the References item under the BookStoreTests project tree and SelectAdd Reference”

image009

Since we will be testing the BookStore project, we will need to add a reference to it.

Select the Projects tab and then Select the BookStore project from the list and Click OK.

image011

Now there is one more reference to add; the reference to the NUnit Framework library.

Right-Click on References again and SelectAdd Reference”.

This time Select the .NET tab and scroll down to the nunit.framework assembly, Select It, and Click OK.

image013

Now we are completely set-up and ready to begin coding.

At this point if you were able to follow along, your Solution Explorer should resemble the one below.

Now to create a test.

image015

Right-Click on the BookStoreTests project and follow the “Add” > “New Item” menu sequence.

image018

Select “Class” as the template and name it “BookStoreControllerTests.cs” and ClickAdd”.

image019

The reason that we named our class as such is, one popular design pattern is to place the UI, business logic, and database features in separate layers (projects or files).

So in our design, we will implement a BookStoreController that will represent our business logic layer. The controllers job is to provide data/objects to our UI layer for display. Therefore, we want to test that our controller (business logic layer or bll) is doing just that, hence the BookStoreControllerTests.cs class.

Next we need to let the compiler know that we would like to use classes and methods provided by the nunit.framework library and the BookStore project that we referenced a moment ago.

Do this by adding using directives to the top of the BookStoreControllerTests.cs class and a special attribute to let nunit know to run the tests in the file as such:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

using NUnit.Framework;

using BookStore;

 

namespace BookStoreTests

{

    [TestFixture]

    public class BookStoreControllerTests

    {

    }

}

 

Next we need to add another nunit specific feature referred to as a setup method. A setup method is identified by the [SetUp] attribute. Set up methods allow you to prepare your objects/classes for testing, so during setup you can create instances of the actual classes that you will test and, if necessary, load data.

We will use ours to create an instance of our BookStoreController.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

using NUnit.Framework;

using BookStore;

 

namespace BookStoreTests

{

    [TestFixture]

    public class BookStoreControllerTests

    {

        //here we know that we are testing the BookStoreController

        //so we need to declare one.

        BookStoreController Controller;

 

        //during the setup for our tests we want to actually instantiate the controller;

        [SetUp]

        public void Build()

        {

            Controller = new BookStoreController();

        }

    }

}

 

And now for the actual test method itself. Using NUnit, a test method is identified by the [Test] attribute. The accepted nomenclature for test methods, while verbose, identifies the expected result. For this test, we would like for the BookStoreController to return a particular book when passed an ISBN. For the purposes of this tutorial I will use a book from my personal library, “Windows Communication Foundation Unleashed”. No big deal, we could very well have made up a book title and ISBN.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

using NUnit.Framework;

using BookStore;

 

namespace BookStoreTests

{

    //let nunit know that this is a test class. So run tests inside.

    [TestFixture]

    public class BookStoreControllerTests

    {

        //here we know that we are testing the BookStoreController

        //so we need to declare one.

        BookStoreController Controller;

 

        //Create a setup for tests that instantiate the controller

        //and add data if necessary.

        [SetUp]

        public void Build()

        {

            //create an instance of the book controller.

            Controller = new BookStoreController();

        }

 

        //Create a test method.

        [Test]

        public void ExpectedToReturnABook()

        {

            //call the get book method on the controller passing in an isbn.

            string isbn = "9780672329487";

            Book WCFUnleashed = Controller.GetBook(isbn);

           

            //test that the book return is not null.

            Assert.IsNotNull(WCFUnleashed);

        }

    }

}

Now let’s build the application. If you’re familiar with programming in .NET using VisualStudio, you’re probably thinking to yourself, this thing will not build. You're correct, and that points out our first objective. When using the TDD approach, we first write out our EXPECTATIONS, then we write the code required to meet them. Therefore when we attempt to build our project, we get the following:

image021

This is because we don’t have any of the referenced classes defined (created). So we need to get our application to build by creating them.

Right-Click on the BookStore project and Select “Add” > “New Item” and choose “Class”.

Enter “Book.cs” as the name.

image023

Follow the same steps and create a file named “BookStoreController.cs”.

Then Right-Click on the BookStore project and Click "Build".

Your BookStoreControllerTests project should resemble the figure below. The BookStoreController and Book classes have now been recognized as indicated by the code coloring.

image025

Now try and build the project again by right-clicking on “Solution ‘BookStore’ (2 projects)” and clicking “Build”. Again you should receive an error. This is because, although we have created our classes, the BookStoreController.cs file does not contain a method called GetBook that accepts a string argument. So let’s fix this by adding the method below to the BookStoreController.cs file.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace BookStore

{

    public class BookStoreController

    {

        //Get a book from the store by isbn

        public Book GetBook(string isbn)

        {

            //Create a book instance and set it to a null object.

            Book RequestedBook = null;

 

            //Return the book

            return RequestedBook;

        }

    }

}

 

Since OOP principles are beyond the scope of this tutorial, we will go with some basic implementations just to get our projects to build, and our unit tests to pass.  There is one change to the class files that I should point out, and that is the use of the public keyword. The public keyword indicates that a class is accessible outside of its current assembly (dll) or project however you would like to look at it. By default, VisualStudio does not add the public keyword to newly created classes. So for each of the classes that were created, Book.cs and BookStoreController.cs,

Change:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace BookStore

{

    class BookStoreController

    {

To read:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace BookStore

{

    public class BookStoreController

    {

Now with our GetBook() method in place, lets attempt to build our project again.

Right-Click on the BookControllerTests project and select “Build”.

If you have followed along successfully, your Visual Studio Output window should display the text below, with an emphasis on the statement indicating that the build of our 2 projects succeeded.

------ Build started: Project: BookStore, Configuration: Debug Any CPU ------

BookStore -> C:\Users\Bacardi\Documents\Visual Studio 2008\Projects\BookStore\BookStore\bin\Debug\BookStore.dll

------ Build started: Project: BookStoreTests, Configuration: Debug Any CPU ------

BookStoreTests -> C:\Users\Bacardi\Documents\Visual Studio 2008\Projects\BookStore\BookStoreTests\bin\Debug\BookStoreTests.dll

========== Build: 2 succeeded or up-to-date, 0 failed, 0 skipped ==========

 

Now for the reason that we went through all of this, THE TEST!

At this point let’s launch NUnit and run the tests just as we did in the first lesson of this series.

From the NUnit application, SelectFile” > “Open Project” and navigate to the BookStore project in the Visual Studio > Projects directory. Since we are testing our BookStoreTests assembly, we will navigate to the BookStoreTests/Bin/Debug folder and select the BookStoreTests.dll file.

For a normal installation on Windows Vista, the directory path would be:

C:\Users\[username]\Documents\Visual Studio 2008\Projects\BookStore\BookStoreTests\bin\Debug

You should see your project appear in the NUnit Gui’s left panel and then click “RUN” to run the test. If you have followed along successfully you should see the following:

image027

Just as we should have suspected, our test failed. This is because we explicitly set our book object to a null object in the BookStoreController’s GetBook() method, and then we ran a test in the BookControllerTests' ExpectedToReturnABook() method that tested that was to ensure that the book was not null.

So again in TDD, we want to specify our expectations first, then write the code that fulfills ONLY THAT expectation. There are some theories on efficiency and the like surrounding this, but again that is beyond the scope here. Therefore, in sticking with the program, lets get the test to pass.

In order to do so, we need for our BookStoreController to return a book object that is not null, and the code below accomplishes this. So replace the existing code in your BookStoreController.cs file with this modified code.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace BookStore

{

    public class BookStoreController

    {

        //Get a book from the store by isbn

        public Book GetBook(string isbn)

        {

            //Create a book instance.

            Book RequestedBook = new Book();

 

 

            //Set the properties for the book. For this tutorial

            //lets pretend that the controller actually pulled book details

            //from the database, xml repository, or webservice where ever.

            //One approach is to call a service that returns the requested book

            //overriding the null on created above. So that might look like:

            //

            //  try{

            //       RequestedBook = _bookService.getBook(isbn);

            //  }

            //

            //Where _bookService represents a service layer that handles calls to

            //a repository of some type, hosted somewhere.

            RequestedBook.Isbn = isbn;

            RequestedBook.Title = "Windows Communication Foundation Unleashed";

 

            //Return the book

            return RequestedBook;

        }

    }

}

 

Also, we need our Book object to actually have the properties that we are setting in our BookStoreController.cs file defined. So modify your Book.cs file to resemble the code below.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace BookStore

{

    public class Book

    {

        private string _isbn;

        private string _title;

 

        public string Isbn

        {

            get { return this._isbn; }

            set { this._isbn = value; }

        }

        public string Title

        {

            get { return this._title; }

            set { this._title = value; }

        }

    }

}

 

Build the solution again.

Go to NUnit and ClickRUN”, and as the French would say it “voila” our test has passed.

image029

And that’s a wrap. In this very detailed part of the series we created a class library project, created a unit testing project, created a new test, wrote the code necessary to build the solution, and finally wrote the code necessary to pass the test.

As basic as it is, I hope this helps you conceptualize test driven development. Future tutorials in this series will not be as in-depth, as I would assume that the fundamentals of tests and how they work are understood. So tune back for the tutorials on the RhinoMocks and MoQ testing frameworks.

The series:

Happy Testing!

Comments


Comments are closed