Wednesday, March 19, 2008

I wanted to try out TDD (Test-Driven Development) for a long time. I checked out NUnit, even got a book on it (read just 1 chapter and got the idea, since then read 3 more chapters :)... Time passed since then and due to some other reasons I haven't touched the subject. Now I have the time and I decided to explore TDD again. This series of posts will describe my experience.

1. Unit testing (why it's here -- below).

When I read about TDD before, I also read about unit testing tools that are in VS 2008, but I did not have a chance to play with them at the time. Now I explored what they are and they aren't quite TDD, they are unit tests. The difference between TDD and unit testing is that in TDD tests drive development -- tests are written before the actual features. Unit testing can happen after a feature is put in. VS2008 even has a nice test generator based on the current code. The time spent exploring unit testing was definitely worth it, but I want to develop something using TDD.

Below is the brief rundown on unit testing. By the way, I found a very good article on unit testing that covers what I am about to describe in greater detail. The only other thing I wish it covered is how to get the code coverage analysis from within VS2008, but I think it's just a matter of pushing a couple of buttons in the IDE. By the way, code coverage was something that made me use unit testing tools in VS2008 in the first place, I wanted to see the lines of code that are tested and those that aren't.

So here it comes:

I have an idea in mind for a simple app. A shopping list -- I want to be able to put in new products in the list and check them off when I have them and mark them for purchase when I am out (note to self -- get eggs!). I decided that that would be a good place to exercise the red-green-refactor metaphor. I fired up VS2008, created a simple web project, and then pushed the magic button to generate another project in the same solution for unit tests. Then I created two simple tests to check the database connectivity (I will list somewhat the same code later so I don't put it in now to not repeat myself) and was happy.

Not for long though -- I put in the test code right inside a class the test project, and I did not use any of the web site's classes for it. I sure was checking the connectivity, but that's just testing.

In order to address that, I created a SimpleDataLayer class in the web site, added a simple method to return a SQL connection and wanted to instantiate it from the test project. I could not. It turns out that I created the site in the regular place where my all projects reside (and I sure did not change it in the VS settings -- TODO!), but the tests project got created under Documents/User/... blah. So I could not add a reference and keep testing. I searched google and found on MSDN an option to create Unit Tests (open up the class, right-click in code, Create Unit Tests) and whoa!!! A class appeared and it sure had a lot of things I did not know about (the article explains it nicely).

As you can see, there is now a "ShoppingListSite.accessor," which in fact, has nothing but a path to the web site and the word "WebSite" in it. It must be just a pointer.

Here is what a test looks like:

What exactly is the "SimpleDataLayer_Accessor"? It turns out that it is sort of a proxy between the private class SimpleDataLayer and the one containing the test methods. An instance of the SimpleDataLayer_Accessor can be referred to in the same way as if it was an instance of a SimpleDataLayer.

Another interesting point is that a test is generated inconclusive by default. I think it's a clever idea when someone is using the automated generation of unit tests against a large project, when such a test is run it'll turn out as neither failed nor passed but rather inconclusive.

That's it for now, I'll keep you posted once I make more progress on it.