Brendan Enrick

Daily Software Development

Updating RSS Feed Location

I have set up a new feed on feedburner. I am hoping most of my readers will be willing to switch to the new RSS feed. http://feeds.feedburner.com/BrendanEnrick

Please update your subscription to http://feeds.feedburner.com/BrendanEnrick

Looking forward to posting more and better content since this blog should be easier for me to use.

For the time being the old RSS feed location will work just fine, but I'd rather consolidate everyone into one nice more generic rss feed.

foreach (Reader blogReader in myBlog.Readers)
{
    Say("Thank you for reading!");
}

Code Coverage Is Not Enough

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.

public bool ShouldHealSoldier(Soldier soldierToCheck)
{
    return soldierToCheck.IsWounded;
}

So now we will test for code coverage.

[TestMethod]
public void MedicShouldHealSoldierWhoIsWounded()
{
    var s = new Soldier();
    s.IsWounded = true;
    var m = new Medic();
 
    Assert.IsTrue(m.ShouldHealSoldier(s));
}
 
[TestMethod]
public void 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]
public void MedicShouldHealSoldierWhoIsWounded()
{
    var s = new Soldier();
    s.IsWounded = true;
    var m = new Medic();
 
    Assert.IsTrue(m.ShouldHealSoldier(s));
}
 
[TestMethod]
public void MedicShouldNotHealSoldierWhoIsNotWounded()
{
    var s = new Soldier();
    s.IsWounded = false;
    var m = new Medic();
 
    Assert.IsFalse(m.ShouldHealSoldier(s));
}
 
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void 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.

Storing and Retrieving Serialized Data with Azure Blob Storage

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.

var blob = BlobStorage.Create(
        StorageAccountInfo.GetDefaultBlobStorageAccountFromConfiguration()).
        GetBlobContainer("myblobcontainer");
 
var encoding = new ASCIIEncoding();
 
if (blob.DoesBlobExist("myblob"))
{
    Stream stream = new MemoryStream();
    var contents = new BlobContents(stream);
    blob.GetBlob("myblob", contents, false );
    
    string myXml = encoding.GetString(contents.AsBytes());
    
    StringReader stringReader = new StringReader(myXml);
    var reader = new XmlTextReader(stringReader);
 
    var deserializer = new XmlSerializer(typeof(List<MyObject>));
    var myDataObjects = (List<MyObject>)deserializer.Deserialize(reader);
}

Second we need to work with the data.

// Do a whole bunch of work here.
// This stuff is really important.
// Did you really just read a block
// of comments in a blog?
 
// I am being honest when I say that
// these blocks of comments are
// not really needed at all, but
// wasn't it fun reading this pointless
// block?

Third we put the data back with updates

var serializer = new XmlSerializer(typeof(List<MyObject>));
var stringBuilder = new StringBuilder();
XmlWriter writer = XmlWriter.Create(stringBuilder);
serializer.Serialize(writer, myDataObjects);
 
byte[] theseBytes = encoding.GetBytes(stringBuilder.ToString());
 
blob.CreateBlob(
       new BlobProperties("myblob") { ContentType = "text/xml" },
       new BlobContents(theseBytes),
       true);

Hooray! We're now able to serialize to Azure Blobs.

First Post?

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!!!

Blog Moving Here

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.