Showing posts with label Unit Test. Show all posts
Showing posts with label Unit Test. Show all posts

Wednesday, April 9, 2008

Sold on unit testing

I'll tell anyone who asks that I'm NOT a programmer. I've always understood the value in unit tests but considered them somewhat limited in scope. I mean it's pretty much impossible to write a unit test for every possible scenario and (IMHO) impossible to write a unit test that simulates the flow of a user from application login to data entry to logout using the entire infrastructure (i.e. client browser -> through load balancer -> through app server -> database -> back).

Because of those reasons, while I understood the need for unit tests for "stupid stuff", the fact that you had to add unit tests for each bug that popped up over the life of a product felt "odd". Of course this wouldn't stop me from bitching at a developer who's lack of a unit test caused me to restore a filesystem because it would ascend to the parent directory if the file or directory it was trying to delete did not exist! (True story).

So here I am writing my ruby nagios library and realizing that I'm duplicating A LOT of code writing quick little scripts to test my output. I decide to write unit tests for each of my classes. I found an interesting little article on about.com talking about learning ruby via unit tests. It was an interesting concept and one that made sense to me. So I start with my contact class.

Basically all of the classes that exist for a specific nagios object (contact,service,host) have their own class. One method they have is called "hashify". It's different for each object type but essentially creates a nested hash like so:

{
"nagiosadmin"=>
{"service_notification_period"=>"24x7",
"host_notification_options"=>"d,u,r",
"service_notifications_enabled"=>nil,
"host_notification_enabled"=>nil,
"pager"=>nil,
"service_notification_commands"=>"notify-service-by-email",
"host_notification_period"=>"24x7",
"alias"=>"Nagios Admin",
"host_notification_commands"=>"notify-host-by-email",
"service_notification_options"=>"w,u,c,r",
"email"=>"root@localhost"},
"johnv"=>
{"service_notification_period"=>"24x7",
"host_notification_options"=>"d,u,r",
"service_notifications_enabled"=>nil,
"host_notification_enabled"=>nil,
"pager"=>nil,
"service_notification_commands"=>"notify-service-by-email",
"host_notification_period"=>"24x7",
"alias"=>"John E. Vincent",
"host_notification_commands"=>"notify-host-by-email",
"service_notification_options"=>"w,u,c,r",
"email"=>"root@localhost"}
}
So I start writing unit tests. I test that hashify returns a Hash. I test that I have a hash called 'johnv'. Then I start testing for each of the attributes for johnv. This is where it all falls apart. Attribute email is always returning nil even though I can see right in the debugger that it's set to 'root@localhost'.

After about 30 minutes of dicking around I finally realize that, being a Ruby beginner who has used some of the higher-level Ruby stuff for quickies without actually getting into the meat of the language (Rails, Ruport), I was totally confused on the usage of ":" in hashes much less anywhere else in Ruby. Two minutes after that, I stopped throwing symbols all over the place in my classes when building a hash ;)

My unit test passed! I continue to write the remaining tests and run them. I get a failure. I look in detail and realize that in my original Contact class, I had a typo in the hashify method that defined a key as 'host_notifications_period' instead of 'host_notification_period'!

So yeah, I'm sold on unit tests and I'm not writing another lick of code until I finish writing them for the classes I have now.