coffee-cup explorations of bacardi bryant RSS 2.0
 Sunday, May 11, 2008

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”.

Delete the existing Class1.cs file.

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

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

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”

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.

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.

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.

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

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

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. When 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:

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.

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.

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:

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 used the BookControllerTests' ExpectedToReturnABook() method to test 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 increased 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.

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!

Sunday, May 11, 2008 9:28:17 PM UTC  #    Comments [0] - Trackback
TDD | NUnit
 Sunday, May 04, 2008

First word of caution, Gateway MT6821 is probably not a good buy. I purchased this laptop about a year ago and was pretty excited as it was a major upgrade from my previous Compaq system. It was well equipped for my needs with a dual core processor, 2GB RAM, and most importantly, 2MB L2 cache.

Often times overlooked, the L2 cache is a major player in overall system performance. While I won't go into the specifics, the next time you are out shopping, take some time to compare systems with varying cache capacities. The difference that 1MB of cache can is shocking.

Well anyways, back to the problem. As of late, my Gateway system has been shutting down unexpectedly. I would strike a key or spin it towards me on the table and the next thing I know, its off. The system displayed no messages such as "Shutting Down..." or "Logging Off...", just an immediate BLACK screen. I remember feeling worse than I did during the infamous BSOD days. At least with a blue screen, you had some reference to what may have happened.

After great frustration and tons of hours of productivity lost, I began to search for these symptoms online and found some interesting threads that suggested that the system is overheating. In essence, the threads claim that some Gateway systems, namely those with larger on chip cache memory (L2), experience overheating and may shutdown unexpectedly. So if this is the case, then I should let my system cool down a day or two each week in between use. So no more working on weekends I guess =P. My wife would love it.

My system refresh cycle has historically been three years, but with last year's purchase of this Gateway, it appears that I will have to do an out-of-cycle refresh. So I guess it's back to DELL for me. Besides, the three year warranty fits my refresh cycle!

Sunday, May 04, 2008 4:48:36 PM UTC  #    Comments [0] - Trackback
General
 Monday, April 21, 2008

Hi all,

I know that the TDD series is lagging behind schedule a bit, but this weekend I decided to move the site from a shared hosting provider to my own server. What a weekend it was. Hats off to all of the server administrators out there that do such a good thing to keep the servers inline. I won't blog about the experience b/c it's nothing more than another IT whine, but hopefully I will be done in a couple of days and can upload the remaining content for the series. I have about six more sites to transfer, but they all require MSSQL databases so I am moving fast to get the db installed and configured.

Anyways, happy coding, will blog again soon.

Monday, April 21, 2008 5:42:25 PM UTC  #    Comments [0] - Trackback
General
 Sunday, April 13, 2008

To install the NUnit unit testing framework, download the NUnit.msi installation file from SourceForge. The latest version at the time of this writing is v2.4.7.

After clicking "Download" you will be redirected to a page with the screen below. Be sure to click the .msi file as we are going with the automatic installation for this tutorial.

When done downloading, install the application accepting all of the default settings by clicking Next, Next, etc.

Quickly, to verify a proper installation. Lauch the NUnit GUI application. (NUnit must be run in Administrator context for some tests to pass).

When the application opens, go to the file menu, choose "Open Project" and select the NUnitTests project. 
 
(For the first run, the FileOpen Dialog box should automatically open in the NUnit bin directory.
If not, the files should be located at "root_drive:\Program Files\NUnit 3.5.7\bin\").

With the top most node in the tree selected, click "Run". All tests should pass. If you find IO related failures, then NUnit is not
running in the context of an Administrator.

Now that NUnit is installed, you are ready for the next phase in TDD, writing code.

Sunday, April 13, 2008 6:26:11 PM UTC  #    Comments [0] - Trackback
NUnit | TDD

Recently I decided that I would adopt TDD or "Test Driven Development" as an approach to building C# applications. While I found plenty of information on testing tools such as RhinoMocks, NUnit, and the newly introduced MoQ pronounced Mock-You, the QuickStarts and code snippets were comprehensive and difficult for a newbie to follow in my opinion.

Therefore, for anyone that is looking to get going with TDD for the first time, as I was, here is a QuickStart Series that I hope will help you along.

As the title mentions, I am focusing on TDD for C#. That said, if you intend to practice along with the tutorials in this series, you will need:

  • A version Microsoft Visual Studio
  • The NUnit Library
  • The RhinoMocks Library
  • The MoQ Library

Although I won't cover it in this series, I should mention that Visual Studio Professional and higher versions have MS Test, a testing framework offered by Microsoft, integrated into the IDE.

The series:

Sunday, April 13, 2008 6:24:10 PM UTC  #    Comments [0] - Trackback
NUnit | TDD

  Hi, my name is Bacardi Bryant.

I am an Application Systems Analyst and have been developing applications using Microsoft´s .NET technologies and ColdFusion for some time now.

Although it is not a high priority now, when I do find the time, I will blog about topics that I have found interesting. Feel free to drop a comment.

Sunday, April 13, 2008 5:32:39 PM UTC  #    Comments [0] - Trackback
General
Categories