Wednesday, October 18, 2006

I Code Like A Rock Star!

Originally Posted On: DATE: 10/07/2005 11:27:57

Today I was working with one of my office mates on reproducing a problem reported at a field site. He had already gotten the source from the tip, built, and tested it, and then added a test case to demonstate the problem we were seeing in the field. The conversation went something like this:
Him: "I added the test, and it all works."
Me: "Really? That change should have caused a failure. Let's take a look."
We looked at the code, and sure enough, the test that should fail was in the test case.
Me: "This is really strange..."
I added a fail(...) to the test case, and it still didn't cause any failures.
Me: "This is really bothering me..."
I added a compile time error to the test case, and the compiler did complain this time.
Finally, we looked in the test suite (this is a fairly old class that's still using NUnit 1.x) and found that the suite wasn't including this test class. We added the class to the suite, and the failures happened in the way we were expecting. We then backed all the cruft we had just added to the test class back out, and worked on the problem from the beginning. It was very disconcerting to be able to add errors to the test class but not have them show up.

Two lessons I learned from this episode:
  1. Don't Take Short Cuts. There's a great article on The Three Rules Of TDD by Bob Martin. We should not have added anything to a class that wasn't really being called. There are ways to validate that the classes are actually included. This problem would be alleviated by using NUnit 2 somewhat, since the tests there are tagged instead of named, and the Suite class is unneeded.
  2. Don't Trust Anything. Whenever something smells wrong, there's probably a good reason. Start with the simplest thing (like - is the editor, the compiler, and test running all pointing at the same place?) and work up in complexity to find where things start to stink. Then iterate around there until you find the problem.

Another One Bites The Dust

Originally Posted On: DATE: 09/18/2005 10:59:45

When I was in high school in the early eighties, a friend of mine (David Jackson) told me that there were hidden lyrics in a song by the rock group Queen. I didn't believe him, so he put my copy of the LP (we had vinyl LP records then) on my record player, and turned the record backwards by hand. On the song "Another One Bites The Dust", there were some very interesting lyrics. Take a listen to both versions and see if you can hear what I thought I heard in the backwards version. (Note that before you listen to any of this that this song is (c) Queen, and I have no rights to it whatsoever. I'm just making an interesting observation about a 5 second snippet of it.)
  • Here's the snippet I'm talking about played normally.
  • Here's the exact same snippet played backwards.
To me, it sounds like the backwards version says "it's fun to smoke marijuana" several times. Now that you think I heard that when I listened to it, listen to the backwards version again. Did the things I heard affect what you heard? There are a couple of interesting thoughts here:
  • If it really says that, how did the guys in the band manage to make it say that?
  • If it doesn't, how much does your expectation that something will say something affect what you actually hear?

Personally I can imagine a bunch of guys messing around with audio equipment, trying to find something to write a song about and finding out that "i like to smoke marijuana" sounds like "another one bites the dust" backwards, and using that in a song.

In the end, it doesn't really matter. I seriously doubt that there's any subconscious decoding that will take lyrics backwards, and put them in your memory, and further, I still think that the song is a fun song.

Excellent Fowler Article

I saw an excellent article by Martin Fowler today. It hits the nail on the head of why it's so hard to do something new even though it has a very good chance of being easier/better than how we do it today. This was my experience in learning Test Driven Development.

Tuesday, October 10, 2006

Automatically Dismissing The Unhandled Exception Dialog

On our build system, we were having two problems. First of all, there was a smoke test that was throwing an unhandled exception. Second of all, the .net framework was presenting a dialog to ask the user what to do about the exception. In the spirit of fail fast, this was causing a big problem for the entire build, since we normally don't have somebody staring at the build box, expecting to give user input. It's very important that the build box be headless and input-less. It's OK to have a management console like CruiseControl to request builds, but there should never be an interactive dialog.

I googled for an answer on how to automatically dismiss the dialog, and finally found the answer. Essentially, all you have to do is modify the registry key:

HKEY_LOCAL_MACHINE\Software\Microsoft\ .NETFramework\DbgJITDebugLaunchSetting

and change it's value to 1. This will allow the process throwing the unhandled exception to terminate with a stack dump with no user interaction.

Friday, October 06, 2006

Upgrading From NAnt 0.84+ to NAnt 0.85 rc4

I converted our nightly and integration builds from NAnt 0.84 (with some local mods) to NAnt 0.85 rc4 today. Overall, the upgrade was pretty painless. There were several changes that I had to make to our build file to make it work, plus there were many warnings that I wanted to remove after trying things out. Here's the list of things I did:
  • Copied the support dlls from the NAnt contrib project into the nant/bin directory. This was required for several support tasks and attributes. It also makes it easier to upgrade the build file later since everything will be available.
  • Copied support tasks created locally into the nant/bin directory. These tasks were still compatible with the new version of NAnt, and didn't even require a rebuild.
  • Used to have to set an environment variable with inline C# code, but we can now take advantage of the setenv command. This even speeds up the build slightly since the dll that sets the env. variable doesn't have to be compiled and loaded.
  • Changed all includes and excludes to include and exclude respectively. There were many filesets in the build file. This was by far the most common change. This was not required, but removed many warnings.
  • Changed all user in vssget and vsslabel to username. Again, this was not required, but generated deprication warnings.
  • Had to add some code to ensure the write-only bit was off before touching some files to change the timestamp (this was necesssary because of making sure IIS saw the webservice files as new). This was a required change due to some new behavior in NAnt.
  • Used to have some code to remove a service before we installed it for Smoke Tests. With the newer NAnt (in the contrib project), there is a service::is-installed() check we can use. This eliminates severa lof the warnings we used to get on our Smoke Tests. This was a nice enhancement made possible by the new check.
  • In our nunit2 tasks, we formerly used haltonerror attributes. These are now "failonerror".
  • In our Acceptance Tests, we formerly only used the basedir attribute. With the newer NAnt, we now need to set both the basedir and workingdir attributes. This is necessary only for programs that expect data/config files to be in the executable directory. If running a program that takes no input, this would not be necessary. This was a required change to allow the tests to run.
  • All of the nunit (aka Nunit1) test suites are tagged as depricated, and generate warnings in the build logs. I like this because it will encourage us to upgrade those tests over the next while.