Daily Software Development

A while back I wrote a blog post regarding this topic. In that post I explain that it is safe to use a return statement inside a using block, because the using block will handle the disposing of the defined IDisposable object. This is one truly great ability of the IDisposable interface. It makes it very important to use in my opinion. The using block in combination is very nice, because it handles the disposal for you.

One of my commenter on that post asked me if I was certain that the return statement was safe. He asked this because he couldn't find it in the documents. He also asked me if I had any code showing that this behavior works as I claim it does. I quickly wrote this simple little piece of code which works to demonstrate this behavior.

In my example I have a few things. I have a class which implements IDisposable and all it does to dispose is to write to the console. I then wrote 3 methods which each create and instance of this class in a using statement. One class is normal; it returns after the using statement is complete. The other two end abruptly. One of them returns from within the using statement, and the other throws an exception within the using statement.

When people write tests there is one metric I hear them mention quite often. Yes, you guessed it. Code coverage is mentioned by many people when talking about how well their code is tested. I believe this is a very useful metric, but as the title of this post states, code coverage is not enough. When testing code it is important to try to check all cases which are likely to be able to produce different results. Odd and interesting cases are important.

Tests should be written to handle different cases which can occur. They should not be written to "cover the code". If you're handling the different cases you will also have code coverage. Notice the important difference here. Why don't we take a look at a nice example here.

For the sake of this example we will assume we have 2 classes; medic and soldier. Medics are supposed to heal wounded soldiers and only wounded soldiers. To check this we will make a method for the medic so it can decide.

publicbool ShouldHealSoldier(Soldier soldierToCheck)

{

return soldierToCheck.IsWounded;

}

So now we will test for code coverage.

[TestMethod]

publicvoid MedicShouldHealSoldierWhoIsWounded()

{

var s = new Soldier();

s.IsWounded = true;

var m = new Medic();

Assert.IsTrue(m.ShouldHealSoldier(s));

}

[TestMethod]

publicvoid MedicShouldNotHealSoldierWhoIsNotWounded()

{

var s = new Soldier();

s.IsWounded = false;

var m = new Medic();

Assert.IsFalse(m.ShouldHealSoldier(s));

}

Notice that I am not really testing much here. I am just making sure to run each line of code. This tends to happen when people test for code coverage. If I were instead trying to handle the cases I thought might come up in this code I probably would have done the following tests.

[TestMethod]

publicvoid MedicShouldHealSoldierWhoIsWounded()

{

var s = new Soldier();

s.IsWounded = true;

var m = new Medic();

Assert.IsTrue(m.ShouldHealSoldier(s));

}

[TestMethod]

publicvoid MedicShouldNotHealSoldierWhoIsNotWounded()

{

var s = new Soldier();

s.IsWounded = false;

var m = new Medic();

Assert.IsFalse(m.ShouldHealSoldier(s));

}

[TestMethod]

[ExpectedException(typeof(ArgumentNullException))]

publicvoid ShouldHealSoldierShouldThrowArgumentNullIfSoldierIsNull()

{

var m = new Medic();

Assert.IsTrue(m.ShouldHealSoldier(null));

}

Notice that now I am handling an extra case. I am not covering the code any more with this, because I can't get any more than 100% test coverage, which is what I had after the first tests. You will notice though that I've tested the code better than I did before. I now also know that my code doesn't handle the exception the way I want it to. It currently throws a null reference exception, but I want it to do something else. By writing the code this way I will now get the method written the way I want it to be written. Not the way I wrote it.

This is just one simple example of how adding extra tests which don't add any extra code coverage help. One big reasons to write tests is so code works the way you want it to. That sounds silly, but if you don't write the tests you will often write code that doesn't do what you want it to. This gets all of your expectations for the code out there so that you will be sure to create them all.

On a project I am currently working, we have some normalized data which we need all instances of our Worker Role to have access to. This data when denormalized for the table structure we use requires us to take each row and turn it into about 50,000 rows. Because of this we obviously don't want to denormalize it and store it in Azure's table storage. We eventually will be doing this, but we need to work with it before denormalizing it.

The plan we came up with is to serialize the data and store it as a blob in Azure storage. We tried it a few different ways running into snags in what seemed to be all directions. I just figured out how to get it to work. Finally.

First we need to check and see if the blob exists, and if it does we need to obtain the data from it.

In classic forum style this is not the first post, but it is close. Just trying to get some content to take up some space on the front page of my new blog. Yes, you heard correctly. NEW BLOG! WOOHOO!!!

Ladies, gentlemen, boys, girls, and anyone who doesn't fit in any of those categories this includes, ruffians, riffraff, hooligans, and probably some other people listen up. I have wonderful news to announce. I am finally moving my blog off of aspadvice.com, the site which has graciously given my blog a home for over two years now.

I welcome everyone to this new experience known for now as...... Brendan Enrick's Blog.

What does this mean to you? Well it means that if you ever visit my blog and read a post you'll have a nice look and feel. It also means better integration for me using Windows Live Writer.

Will any of what you've said above change? Yes, of course it will change. Doesn't everything? Perhaps I will switch to another program for writing my blogs. Until that day comes though who knows.

All crazed lunacy aside, this is my new blog. I hope everyone likes it and enjoys reading it.

Thank you and good night........ um....... I mean morning. It is after all 9:25 AM here right now.