The software engineering course at my university covers a lot of material. So much material, actually, that much gets glossed over or exempted. One hour on a Tuesday afternoon we talked about unit testing. Yep, one whole hour to discuss this great, fantastic, oft-blogged about technique. My professor didn't care for unit testing, and didn't see the purpose. His viewpoint was made clear through his rather sarcastic slides and comments. It's a waste of time: If your code runs, you don't need to programmatically test it! Just get it done. I'm paraphrasing a bit here, but there's the gist of it. In his use of the word it, he was referring to our semester long projects. Giant, massive ordeals that were to be completely working, tested, and documented in sixteen weeks; by groups of four or less people. Ours was an amazing adventure, but that's another topic. Needless to say, unit testing was wasn't even attempted on any of our projects.
So, despite my Computer Science degree, I have no real training on unit testing. During my software engineering class, I decided to do some outside research. I downloaded NUnit and gave it a shot. Wow! It was cool! All that green lighting up everywhere, boosting my confidence in my 500-600 line projects. Despite it's crazysexycool appeal, I quickly determined that it was unnecessary. Throwaway code for grades doesn't need unit testing, no matter how you slice it. I tried introducing it into another group project I was working on later and almost suffered a programmer revolt. Unit testing apparently has no appeal for academia. Then again, most programming for classes is built on pizza and beer fueled 48-hour no-source-control code-a-thons.
Now I'm at a real job. Well, not exactly real, but real enough. I'm re-writing a superhuge, 43,000 59,766 line PHP application. (Shut it, I'm new to this.) After two weeks of deciphering both poor naming conventions and rampant use of REGISTER_GLOBALS, I was finally ready to start writing code. One week after the initial repository creation, I realized I hadn't even touched the run button in Visual Studio. This was somewhat alarming; I had 1500 lines of untested C# and 2000 lines of slightly-tested SQL, just staring at me from version control. It compiled, sure, but I've learned that doesn't mean much. Ignoring my insecurities, I continued writing code for the rest of the week. Insecurities don't go away though, they just build. The following week, I couldn't take it anymore. The longer I wrote code without checking it, the larger a chance of a major design flaw appearing later. My work had to be validated. I re-downloaded NUnit (The prior copy being gone, oh, 4 OS installs ago), added some assembly references, and began writing tests.
Unit testing a project that wasn't meant for unit tests causes problems. Google found some best practices and started re-writing my base code. Hours of refactoring later, I had about 10 working unit tests. My code had actually worked pretty well the first time around. I was (and still am) pleased with myself. From that point I decided to use the Test Driven Development (TDD) methodology. Stub your code out, write the tests, watch them fail, then fill in the code and watch them pass. Thirty public void SomeTest()s later, I gave that up. Wait, what? Yes, I gave it up.
I work for a small company that does contract programming. I found, through measuring the time it took me to write classes of comparable complexity, unit testing was doubling to tripling the time it took me to write code. So what!? you cry. You'll get better code in the end, with less time debugging and more confidence! Yep, understandable. Right now, though, I live check to check. If I don't get this code into production, my power bill goes unpaid. I'm willing to take the risk of finding more bugs in the QA stage (which is conducted by the company) by saving time now. Following all the other good development practices should be enough to keep my bug count down, but unit testing just isn't worth the time investment. This is a single company website, custom tailored to their needs. Chances are the only people that will ever see the code are my co-workers.
The fundamental concept of unit testing is sound. I think, given the right time and training, it would greatly improve anyone's code quality. Sometimes that extra quality just isn't necessary. I'll liken this to food, since most people eat. Unit Testing should be used when you want top of the line food, say, Heinz Ketchup. However, if you just need to get the job done (e.g., making something taste like ketchup), get the Great Value brand. Great Value ketchup makes things taste better, but it's not as high quality. Unit testing is the Heinz quality control process. If you have the time or the desire for high quality, use it. If you have a deadline and you can get away with a few bugs, don't bother. Your time is better spent adding new features. Business customers like features, and they're mainly focused on getting the job done.
Note: Don't bother saying Great Value is just some repackaged brand. I'm aware. Just use the damn analogy.
Update 01 May 2007: Fixed linecount due to brand-spankin-new find | cat | wc knowledge.
Print | posted on Tuesday, May 01, 2007 12:58 AM