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!

Wednesday, July 23, 2008

webdev.webserver.exe has stopped working

Yesterday I had opened up my Visual Studio 2008 solution which contains a couple of web sites, a WCF project, and some other project types. I am currently using the Cassini web server, since we have a couple of developers who do some work for us off an on and they share a single server using terminal services to do their work.

When I tried to browse a page in my site, I was prompted with a wonderful crash dialog indicating: webdev.webserver.exe has stopped working. This continued no matter how often I tried or rebooted.

I am not sure why the failure occured, but I noticed a coupled things:

  • A new web site in a new solution worked fine

  • My existing web sites in a new solution did not work

  • The event log had the following message: Fault bucket 158894065, type 5
    Event Name: CLR20r3
    Response: None
    Cab Id: 0

    Problem signature:
    P1: webdev.webserver.exe
    P2: 9.0.0.0
    P3: 4731664b
    P4: System
    P5: 2.0.0.0
    P6: 47577deb
    P7: 2c04
    P8: 40
    P9: System.Net.Sockets.Socket
    P10:



I am not sure of the relevance of P9 but I thought hmm could the port it was using be blocked. Running netstat -a did not show the ports in use but I decided to try and change the ports anyways.

Visual Studio stores all the project settings for a web site in the solution file. To change the default port for a web site you need to find the following line and edit it:

Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "Project Name", "Project Name", "{3BD859EC-9AF2-4866-B43C-EE8AEFF0DF49}"
ProjectSection(WebsiteProperties) = preProject
...Addition project properties....
VWDPort = "58332"
EndProjectSection


After modifying it to use a different port Cassini had no issue launching. Hope someone else finds this helpful. And if you have any idea of additional things I should have looked at please leave a comment!


Edit
Editting a solution file is very easy. Find the solution file, and open it up in your favorite text editor. Then find the port setting setting, and edit it.

Monday, July 21, 2008

Fixing users in SQL2005 after restoring a DB

After you restore a database in SQL Server 2005 to a different server, you will need to fix the login associated with the users in the database this can be done by using the following stored procedure:

exec sp_change_users_login 'AUTO_FIX','UserName'


If you don't do this you will get an error while trying to login as the user. This needs to be done for each user in the database.