Wednesday, August 27, 2008

Bashing and Rants

Here's a good example of the problem with blogging technology. You give anyone the ability to instantly publish and your going end up with some dribble and rants.

This article is nothing but bashing of MS, and provides no substantiation of any of the claims the author makes. Give examples of good projects that have been squashed due to the giant beast gobbling up the developers and forcing them to stop working on a project.

As Oren Eini put it so nicely
Who exactly said that I owe something to anybody? Who exactly said that any of the guys who went to work for Microsoft (many of whom I consider friends) owe you something.


How dare anyone have the audacity to claim an evil doing that a developer of a free tool abandoned the project.

I guess that's the problem of free space and cheap publishing technology but now my rant about the ranters is over.

Enjoy!
Josh

Sunday, August 24, 2008

Unit Tests & Expected Exceptions

Good unit test coverage should include tests that cover the normal use cases in your code, and tests that validate any bounds are being checked. What does this mean? Take for example the following function.


public File OpenFile(string filePath)

{

Check.Require(!string.IsNullOrEmpty(filePath),"Path cannot be null or empty");

Check.Require(File.Exists(filePath), "Path must exist");

...

}




A good unit test suite will ensure that the code handles the exception cases, when the codes pre & post conditions are not met. When writting these tests you will need to watch for exceptions. One quick implementation of this is:

try

{

FileInfo file = OpenFile(null);

}

catch (PreconditionException ex){}

catch (Exception badEx)

{

Assert.Fail();

}



While this works it suffers from a critical problem that how do I know which exception we were expecting to get? Unless this is documented, I can't be certain of the original test writters intentions.

Many of the unit testing frameworks provide a solution to this with an ExpectedException (or some variant there of) attribute which can be placed on a test method. This attribute typically takes a type of exception and optionally a message that should be the message of the exception.

This is definetly better and results in a simple test in the MS Test framework such as the following:


[TestMethod]

[ExpectedException(typeof(PreconditionException))]

public void OpenFile_NullPathTest()

{

FileInfo file = OpenFile(null);

}



This works fine in this simple case, but what if we have a more complex test, or we are doign an integration test and testing lots of components. If any component throws the exception then your test will still pass.

A better way would let us both clearly express the intent of the test, and to narrow down a specific line or set of lines that should generate the exception.

In C# 3.0 we can leverage delgates and extension methods to come up with a simple way that achieves these goals. Our test method now looks like:



[TestMethod]

public void OpenFile_NullPathTest()

{

Action action=delegate{ OpenFile(null); };

action.ExpectedException(typeof(PreconditionException));

}




This test clearly states that the OpenFile(null) call will result in a PreconditionException, and if there is other stuff occuring within the test, we don't have to worry about the test passing when it should have passed.

The ExpectedException method is an extension method on an Action Delegate. Action is a general delegate that takes no arguments and returns a void. To use this you need to add the following method to a static class, and make sure that the class is within a referenced name space (using in C# or imports in vb).



public static void ExpectedException(this Action action, Type expectedException)

{

try

{

action();

Assert.Fail("Expected exception did not occur");

}

catch (Exception ex)

{

Assert.AreEqual(expectedException, ex.GetType(), string.Format("Expected exception of type {0} but recieved exception of {1}", expectedException.Name, ex.GetType().Name));

}

}



This method could be enhanced to allow checking that the right exception is thrown but that the message is what you expect; however, I'll leave that as an exercise for you.

If your not a big fan of extension methods you could do this using a delegate or even nicer with a lamba such as:
TestHelper.ExpectedException(() => OpenFile(null),typeof(PreconditionException));

Enjoy!

Josh

Edited: 11-17-2008 Added an Assert.Fail() after we call the action delegate in our test helper.

Wednesday, August 20, 2008

Overidding a javascript method

As I'm forced to spend more time doing client web development, I'm finding javascript to be an interesting language to work. Recently I've discovered a fun way to override a method on a javascript object that I would like to share.

Let's take the following example:

function apple(color)


{


this._color=color;


}



apple.prototype.AlertColor=function()


{


alert(this._color);


}



var myApp=new apple("red");


myApp.AlertColor();




When you run this inside a web page you'll get an alert box with the color red. Now let's pretend that our apple is an external script, which is used in many web pages; however, in one specific page we need to change the functionality of the AlertColor method. How do we do this?


apple.prototype.AlertColor=function()


{


alert("blue");


}



var myApp=new apple("red");


myApp.AlertColor();




What we are doing here is replacing the definition of AlertColor on all instances of apple with our new function. Running this script will give you an alert of blue. Let us go one step further and pretend that we want to wrap custom functionality around the AlertColor function.


apple.prototype.Original_AlertColor=apple.prototype.AlertColor;



apple.prototype.AlertColor=function()


{


alert("You are asking about the color well I am...");


this.Original_AlertColor();


}



var myApp=new apple("red");


myApp.AlertColor();




Here you will get two alert boxes. What we have essentially done is add a new function called Orginal_AlertColor and we set to the orginal AlertColor function. Then with our new function we call the original function.

Now that hopefully we understand the basic how to, what can I do with this? Here are some examples I've found in the wild:
  • TextBoxWatermark Extender in Ajax Control toolkit uses this approach to replace the default ASP.Net function for submitting a form. They use this to blank out the watermarked text before posting back to the server.
  • Component Art recommends using this to replace the standard window.alert() method which they use to spit out debug information.

Enjoy!