Thursday, January 29, 2009
Why Unit Tests Matter and How They Will Save You Time
Unit tests can actually save you time in the long run even if you (or your boss) don't currently use or believe in them
The point of the post is to explain why unit tests can actually save you time in the long run even if you or your boss don't currently use or believe in them. It's not my goal to go into some silly religious discussion about why unit tests should or should not be used in a project. There are plenty of forums out there for arguing over various technical concepts and methodologies if you have the time to waste.
Many different philosophies have been proposed that offer solutions for writing quality code. As a result, two people will generally give two different answers if you question them about the best way to write quality code. Regardless of your views on writing quality code, testing has to fit into the picture at some point. We could argue over exactly where testing fits into a project but I don't think anyone would argue that testing can be skipped (and if you're one of those people you can save yourself some time and stop reading now :-)).
I've never been one of those "letter of the law" people when it comes to just about anything and that applies to concepts like testing code as well. I believe balance has to be reached regardless of what you're doing. There is such a thing as going "overboard" when it comes to software development, studying for a test at school, training for sports or many other things. However, everyone's definition of "overboard" differs and I respect that so I'll move on to the heart of the matter which is unit testing and how it can benefit your projects even if you don't agree with the "letter of the law" people out there.
If you're new to unit testing, I'll sum up the general concept quickly: Write tests followed by code to satisfy those tests. That one statement doesn't do unit testing justice, but hopefully you get the basic idea. Do I always write my tests first along with the application's general stub code? Simple answer is "I try to". I try to follow best practices but in reality it doesn't always work out exactly how I want.
Regardless of your view on the overall process, unit tests can still provide significant benefits in my opinion even if you write them later in the development process. The "letter of the law" people probably consider that to be completely wrong, but I try hard to keep in mind that everyone and every project has different skill levels, needs and constraints. Whether you write your unit tests at the beginning, in the middle or even at the end of a project (pushing them off until the end is not recommended and your hand should be slapped with a ruler if you do that :-)), they can still provide you many benefits.
There are numerous Websites dedicated to the topic of unit tests. Wikipedia provides a nice overview here. A few of the benefits unit tests bring to the table include:
Forces more thorough consideration of an application's design.
Simplifies code integration.
Catches bugs more quickly in the development process.
Provides visual test results.
Provides a testing history.
Makes you feel better about the stability of your application (assuming you have good code coverage).
For some people writing unit tests before writing application code (more than just stub code) is absolutely required for writing good software. I agree with that stance overall since if you build testing into a project from the beginning then you should definitely have higher quality code in the end if you stick with it and ensure that you've achieved good code coverage with your tests. However, I've also been on projects where writing all of the unit tests up front simply wasn't going to happen due to the time constraints (which are sometimes ridiculously out of touch with reality) placed on a project. Regardless of your situation, unit tests can still help you in the short-term and long-term.
Here are a few reasons you should consider using them if you're not already. I've found that they actually save time in the long run if you spend a little time up front.
How many times have you written test harness code to test a particular feature? A lot of people whip up a quick console project (or multiple console projects) to do this type of thing. By using unit tests you can save yourself the time of writing test harnesses since unit test frameworks do that for you plus have the ability to run the tests anytime and see their status (green light, red light) aggregated together in one nice report. If you've never worked with unit tests before here's an example of what tests results can look like (this one is generated by Visual Studio 2008):
[Click image to view at full size]
How many times have you or someone else asked, "How will this one quick change affect the application?". For many applications a "small" or "quick" change is made without knowing the impact on the overall application. It's kind of a guessing game for some people. You think it's a simple change only to realize that the one "simple" change affected many other things as well that you or someone else may have forgotten about. If unit tests were in place (assuming good code coverage) you could make the change, run the tests and instantly know how it affects things. It's like having a crystal ball in some ways since by having unit tests you can more accurately predict future changes and the impact they'll have.
How do you know if code contributed from multiple people on a project integrates well? If unit tests were in place you could test their code along with your code and see if things play nicely together. This of course assumes that everyone is writing unit tests for the code.
How do you get test data into and out of a database? While you certainly don't need unit tests for this, startup and cleanup unit test methods can be used to automatically populate a database with test data (with a little work on your part) as tests are run so that your functional tests can be run against real data. People normally write some code to insert test data anyway (or use third-party products to do it like some from RedGate Software) so why not do it as part of your testing process?
How many times have you been asked for a status report on an application? If things are organized really well you'll probably have a project plan in place that can be updated. In other cases, sending the results of unit tests (sending an image like the one above) does wonders to help people see where things stand on a project.
How many times have you had to provide production support for an application someone else wrote? Debugging someone else's code is never fun, especially if documentation is light or non-existent. Imagine inheriting a project that already has good unit tests in place though! You can add your tests (if needed), make the updates or bug fixes and then run all of the tests to see how things look. It's much better than guessing if an application works properly or not especially if you don't know much about the application to start. Plus, unit tests provide a built-in type of documentation since you know what the key methods are in the application that you need to understand and worry about.
To sum things up, I'm a big fan of unit tests simple because I end up writing test harness programs at some point anyway, need to debug a production application or am forced into a situation where someone wants to make that one "simple" change in an application and I don't know the true impact. By using test frameworks such as Visual Studio, nUnit, xUnit.net, mbUnit, and the like (I personally use the features found in Visual Studio), I save myself the time of getting test data into the database, writing test harnesses, maintaining an application, plus much more. By writing unit tests are you going to catch all of the bugs? Obviously not...but you'll be well ahead of where you would have been without them.
Don't take my word for it though, start creating a few unit tests for an application you're already working on (even if the tests are created after the fact in this scenario) and you'll see how nice it is to see green lights as your tests pass or red lights when you need to fix something you wouldn't have caught otherwise. It sure beats pushing off all testing to your end users and wasting their time reporting bugs that you could have dealt with much earlier in the development process.