I remember a time when I didn't write unit tests. I'm not sure why I didn't. Maybe because I thought that the projects I was working on were too simple to warrant unit testing (which actually wasn't true, my thesis project would have really benefited from it). Or maybe because I thought it would take too much time when the schedule was really tight. Or maybe because I doubted the time-effectiveness of spending time writing a lot of basic tests.
But no longer. A couple weeks ago I started development for an enhancement to an existing project at work. Prior to this phase, no unit tests had been written for the project, and I figured it was a good time to start. So I bought the book Test Driven: TDD and Acceptance TDD for Java Developers, read up on some of the basics of JUnit, and started writing tests alongside my components (not always test-first, but at the very latest, test-right-after). And the immediate effectiveness shocked me.
On the first day of writing unit tests for every new object I created, I found 4 bugs, even thought at this point the code couldn't even be deployed and executed. Two of these bugs would have been really hard to catch if I hadn't found them right away – they were in a complicated copy constructor for a big object tree. If I didn't have unit tests to catch these bugs they wouldn't have been immediately obvious, things would have seemed really bizarre when I did finally notice them, and I guarantee it would have taken a LOT longer to find and fix them than the 30 minutes it took to write the tests. The other 2 weren't as complicated, but it was still much easier for a unit test to point at the problem than for me to find them myself. As I've continued to write unit tests, they have continued to pay off. I imagine on a larger project with more than a single full-time developer, the payoff would be even greater.
So I am now officially a believer, and anything more complicated than a tiny little utility warrants a set of JUnit tests. I highly recommend this book if you're working with Java. I'm still figuring out how to test more complicated code (i.e. database, network) and finding a way to calculate test coverage, but the method and class-scoped tests are immensely effective by themselves. The time and quality benefits are obvious, and the "look-at-the-deadline-no-time-to-unit-test" line that I've heard before doesn't hold water. If you've got a tight deadline, then you're probably too busy NOT to unit test.