Archive

Archive for the ‘TDD’ Category

Unit Testing as a Method to Enforce Requirements

April 10th, 2008

I have recently started putting a lot of stock in automated unit testing. Not that I didn’t think unit testing was important in the past, I just didn’t know how to write them properly. A little instruction from a co-worker has corrected that situation and I am now writing proper unit tests. I like the test first approach, though I don’t know that I’ll be doing the full “TDD, no code without a test” thing just yet, but at the moment, I am writing tests first. Only time will tell if I can keep it up throughout the life of my project.

I recently ran into a situation that made me see some additional value in my tests. Beyond making sure everything works properly and lives through changes to the application, I am starting to see how my tests keep me in check and make sure I don’t stray from the requirements.

As an example we’ll assume we are testing classes from an application’s business layer. Each class in this layer will inherit from an abstract base class called “ServiceBase”. In this case, the ServiceBase is a generic class with some abstract members, but it also contains implementation code for a Save method.

The Save method accepts a business entity as an argument and decides whether to call Insert or Update in the underlying data access class. If the value passed in is null, the method throws an exception. This behavior is pretty standard, but some classes that inherit from it may have a need to perform some additional steps when saving. To account for this, I have also made the Save method virtual so any implementation that needs to can override the Save method.

Now we will create a couple of subclasses for ServiceBase. Let’s call them ProductService, CustomerService and OrderService. To start we create the ProductService class and make it inherit from the ServiceBase class. Now in order to make sure we have a complete set of unit tests, we create a test that expects an exception if a null item is passed to the save method. As long as the ServiceBase class throws the exception, it will pass for our test against the ProductService class. Now if we repeat the process (including the test) each class (ProductService, CustomerService, and OrderService), they will all have the ability to save an item, and each test that expects the exception should pass.

Now, let’s say the ProductService class has a need to write to a log when its Save method is called. This is easy, all we have to do is create an override for the Save method in our ProductService class. We add our logging code and all is good. We run our test and it fails.

Why did it fail? Because in my contrived story, we forgot to add the code that throws an exception if a null value is passed in. This is an honest mistake, but it’s ok because our test has saved us. This type of requirement cannot be enforced by the compiler through an interface or abstract base class. As far as the compiler is concerned, this code is completely valid. The unit test however, has alerted us to the fact that we did not implement the code according to our requirements (which was the basis for writing the test in the first place).

While this may be a no-brainer for those of you who have been practicing test driven development or just writing solid unit tests for a while, but for those of us who are just starting down this road this is an added benefit that may not seem obvious at first.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

.NET, C#, TDD, Unit Testing, programming , ,

Visual Studio Unit Tests and Abstract Base Classes

April 6th, 2008

I am taking a semi-TDD approach to my most recent project. As I started writing my initial tests, it occurred to me that all of the ServiceLayer/Manager classes in my business layer inherit from a standard base class and that at least a few of the tests will be identical (except of course for the datatypes used). Each test class will also have essentially the same setup and breakdown.

So of course, I immediately fire up a new class and create a generic base class. I added a type parameter for the entity type that will be transported/manipulated through my Bll, one for the class being tested and another for the data access interface that I would be mocking through Rhino Mocks.

I added the internal and private members that would be used for setup and the test initialization method, commented it all out in my actual test class and added my inheritance. So far, so good. My tests ran, but they were still implemented in the original test class, so I commented them out, copied them into my base class and updated them to use my generic type arguments.

At this point, the “CreateInstance()” method that I was using to get a new instance of my target object caused a compiler error due to the fact that it called a constructor on my genric type argument that accepted a parameter. In order to pass in the mock for my data access interface, the parameter had to be there, but there is no way to specify constructor arguments in the constraints for generic type references.

I decided that making the “CreateInstance()” method abstract would give me access to it and then I would just have to add an implementation into my actual test classes… not a bad trade for the ability to “share” a group of core unit tests. So I marked the class as abstract, removed the method implementation, added the override into my actual test class and compiled.

At this point, my test project compiled with no problem, but my tests didn’t show up in test view. I compiled again, closed and re-opened my test class, closed and re-opened Visual Studio… still no tests in the test view window.

A quick Google search turned up this. I haven’t spent much time researching it at this point, but it seems that Visual Studio doesn’t recognize (or won’t run) Unit Tests that are defined in an abstract class. This problem is pretty specific to the unit testing framework that ships with Visual Studio. Sounds to me like this sort of thing would be possible if I were using NUnit (or some other xUnit framework) to do my unit testing.

The base class still seems to handle my setup and breakdown pretty well and I can use it for support methods that I share between tests so it isn’t a total loss, it just would have been nice to be able to inherit some tests as well.

If I find any new information, I will be sure to post it. If you know something I don’t (I’m sure you do but I mean something related…) feel free to share in the comments.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

.NET, TDD, Tools, Unit Testing, Visual Studio , ,