TDD for Beginners pt4 - Unit Tests

by percent20 14. January 2008 16:34

Part 1: TDD Test Driven Development for Beginners pt1
Part 2: TDD for Beginners pt2 - Pig Latin
Part 3: TDD for Beginners pt3 - The Application
Part 4: TDD for Beginners pt4 - Unit Tests

Recap

I just want to remind everyone of the goals of this series.  It is not to be ALL TDD all the time, but a series on what is TDD and how to start using it on an existing project. Part  1, 2, and 3 are all lead ups to doing this.  Part 1 described what TDD is.  Part 2 described how to do TDD.  Finally, Part 3 setup an existing application that we are going to have as our "Existing" project.  Again, since a lot of people want to start using TDD right away they don't always get the option to start a new project so they need to be able to integrate TDD into an existing application.  My purpose is to give a taste of that with this series while describing some of the basics of TDD and over all concepts and goals of TDD.  This is not an all inclusive how to do TDD and would be irresponsible of me if I said it was as I am still learning TDD myself.

Getting Started

Unfortunately, we can't start doing TDD from the very beginning of a project all the time, would be nice.  We often times come into a project and have to put up with existing code that is usually not easily testable which is pretty unfortunate and can leave you with an icky feeling at times.  This part is going to be about how to implement tests on existing code.

What are we going to test?

I am glad that you asked that question.  Since there are many ways to test things we are only going to test our Business Logic Layer we presented in the Part 3 "TDD for Beginners pt 3 - The Application". If you have not read it I highly recommend you do.  We are going to leave the testing of our Data Access Layer to our final part in the series.

So, right now we want to get our code tested at least a little bit before we start adding features so lets write some tests for our 4 methods. 

  • RetrieveContacts()
  • AddContact()
  • UpdateContact()
  • DeleteContact()

Our Solution

There are many ways to set up your projects to do testing.  In this project I simply made a sub folder called tests and am throwing my tests in there, and they will be built into the application.

Solution Explorer 

Lets take a moment and do some planning based on what this code is doing.

First, we are going to be testing the BusinessLogicLayer Class so that means that we want to use the BLL in ever method that we are going to write our test with.  Since the BLL only does data manipulation in a static way we don't really "need" to create an instance of it in each method.  NUnit provides a SetUp attribute that allows you to do "stuff" before any of the tests are ran such as create instances of objects or populate variables to be used in the tests across your current test fixture.

 

SetUp Attribute

At the top of this code we see our class declaration and the class is going to be a test fixture that will have tests in it (explained in Part 2).

BusinessLogicLayer bl;

Here we are setting up the object that will be used by the tests to access and do stuff with our data.

[SetUp]
public void SetUp()

This is a declaration that the SetUp method is going to be called first because of the SetUp attribute.  How, I look at it is the SetUp method with the SetUp attribute is the constructor of the test fixture it is called first before anything. (the method can be named anything it just makes sense to me to name it setup)

bl = new BusinessLogicLayer("Contacts.xml");

This is just creating an instance of BusinessLogicLayer object and adding that instance reference to the bl object.  Pretty straight forward. Like assigning a variable a value.

Before we move on I want to point out that up until this time the code that we had written in the past with no tests had not been implemented while writing the code so basically it lead to having to try and write all the code at once implement it in some way and hope it all works.  By writing tests we can write a test write a bit of code and then test and tweak until the code works.  At least to me this makes me feel safer about my code actually working because I know, pretty much, as I am writing the code it works. So now lets move on.

Lets talk strategy of testing our data interaction.  One way to test is to try and do stuff on existing data, but that can be dangerous because what if we shouldn't touch the data that exists? We still need to test right? This leads us to the option of what about adding our own data that we know everything about and testing against it then removing it (I did not think of this on my own it came from the book Test Driven Development in Microsoft .NET).  Doing it that way makes sense because then that limits me from accidentally deleting something I shouldn't delete.

Now, with that strategy in mind you should realize now that we are going to be adding data in every test.  So something easy we can do is to create a Contact object in the setup since that is the data we are going to be passing around anyway.

SetUp Method

If you notice the only thing we did was to create a new Contact object and populate it.  Pretty straight forward stuff.  So now lets move onto some the tests.  I want to say here that I may switch back and forth between explaining lines of code and/or chunks of code.  So just be prepared for that as you go along.

RetrieveContacts()

Code:

CropperCapture[13] 

Test:

RetrieveContacts Test

I am not going to explain the naming convention of the test that is done in Part 2 of this series needless to say you kind of get the idea of what the purpose of the test is by the name of it.  Again this part assumes you have read at least part 2 and 3.

List<Contact> l = bll.RetrieveContacts();

This line is fairly simple it is getting a list of all contacts that are in the xml file.

Assert.IsNotEmpty(l);

I like this assertion it you can check to make sure if the method was successful with out having to do much at all just make sure the collection isn't empty.

AddContact()

Code:

CropperCapture[14]

Test:

AddContact Test

bll.AddContact(contact);
List<Contact> l = bll.RetrieveContacts();

Right of the bat we are adding our contact to our xml file and then going ahead and retrieving all the contacts out of the xml file.  So lets now check and see if it is even in there.

bool foundWhatINeed = false;

We are setting up this bool as kind of a switch that if the contact information is in collection then this switch will be true all all will be right in the land of oz.  If not the bad monkeys will come down and take us away and the switch will be false.

Contact theContact = null;

The reason we are setting this up is because if the contact does exist we still have something to do with the contact, like at least remove it.  To do this we need information about it so a good way to do is to get an instance of that contact.

foreach (Contact c in l)
{
    if(c.Name == contact.Name && c.Email == contact.Email)
    {
        theContact = c;
        foundWhatINeed = true;
    }
}

So, we are basically just iterating through all of our contacts, and since we know the specific information about our contact we just compare the name an email address of our hopefully completely unique name and e-mail address.  If it is in the collection we flip our switch and assign the instance of the object to theContact variable.

if (!foundWhatINeed)
        Assert.Fail("Contact was not in list");

Here is what is done with our little on off switch.  If our contact wasn't able to be found we force failure of the test with Assert.Fail and leave a message of why.  Please, be more descriptive than what I was when you do this.

bll.DeleteContact(theContact.sGuid);

And finally since we no longer need that data in the xml file because we added and checked that it was there we can go ahead and delete it from the xml file.

UpdateContact()

Code:

CropperCapture[15]

Test:

UpdateContact Test

I am not going to explain this code line by line as it does the exact same thing as the last 2 tests just a bit more involved.  I am going to do a bullet point description.

  • Add our initial contact and retrieve all contacts from the list
  • Setup our initial switch and object for getting the contact
  • Checks to see if contact is there if so then adds the contact to theContact object if contact is there test fails right there
  • Change a basic bit of information the name and assign the guid of the object to our original object that we are just updating
  • Update the contact
  • Next we just run through our check again to make sure it was all updated if not the test fails
  • then we delete the contact from the xml file.

DeleteContact()

Code:

DeleteContact()

Test:

DeleteContact Test

Same principle applies here as above you know what is going on so I am going to bullet point the explanation, but this is going to be even shorter since it is basically the same code.

  • Add the contact
  • Make sure it was added
  • Delete the contact
  • Make sure it was deleted

Wrap-Up

So in wrapping up this part of our TDD series I want to stress that these are in no way excellent tests that should be reproduced for all time because they are so great.  In fact they can use improvement and can be done different and better ways.  I just wanted to show you how to write some basic Unit Tests for existing code in an existing application.  I hope that this gives you an idea of A how you can write tests for code.  Stay tuned for our next part where we start using TDD on this application to add a new feature.

Final Notes

Here is a bit of homework please I am adding the files for you to download and play with please take a look and see if you can simplify the tests even more or see if you can write them a different way.  Please, play around a bit to see what you can do.

Also note that there are 2 BusinessLogicLayerFixture classes both have the same tests the one with 2 at the end is a simplified version of the other.  I wanted to include both to show that you should and can try to clean up your test to make them look and work better.  I left some more stuff to be cleaned up and move around in the Fixture2 hoping you would give it a shot. Please download and play.

TDDContactManagementApplication_UnitTests.zip (9.11 kb)

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , , ,

Comments

Add comment


(Will show your Gravatar icon)  

  Country flag

biuquote
  • Comment
  • Preview
Loading



Powered by BlogEngine.NET 1.4.5.0
Theme by Mads Kristensen

RecentComments

Comment RSS