When you write tests, you find bugs. Period.
I've been using unit testing in various guises for over ten years, in a variety of languages and environments. Anytime you push your code coverage numbers up, you WILL find bugs.
I think the authors of this article should emphasise combining unit tests with code coverage. Writing tests that increase code coverage is the fastest way to find those latent bugs.
It is always better to find bugs in your unit tests than in the wild and wooly environment of your code.
Had an example of this tonight; I was adding code to check that the classes being generated at runtime using BCEL actually implemented all abstract methods declared in superclasses and interfaces. I had to write a small class to represent a method signature. Completely straight forward, but from discipline, I wrote a small JUnit test suite for this class.
And the test failed. I spent some time with the debugger and some time staring at the code, before I found the tiny error in my implementation of hashCode().
Had I tried to debug this in a running Tapestry application it would have been a nightmare, because of the sheer complexity: many classes, interfaces and use of BCEL to create "enhanced" subclasses (at runtime) with additional methods and fields ... and this latent bug was sitting right in the middle of it all and would have screwed it up painfully.
So, five minutes to write the tests plus ten or fifteen minutes to chase down the hashCode() bug vs. anywhere from 45 minutes to two hours to try and track it down inside a running application. Multiply by 100's of classes in the framework ...
The other points in the article are extremely valid. For anyone who has been following Tapestry's (http://jakarta.apache.org/tapestry) light-speed reinvention lately, the root of it is the JUnit test suite built before making all the radical changes.