Yesterday, I noticed a behavioral regression on a screen I'm working on, but no tests were failing. Today, my first task was to track this down. I found the problem, wrote the fix, and then realized my tests were still passing. So I added tests to make sure I was covering the problem. Then my tests passed and I had an interesting epiphany. Since I wrote my tests after I wrote the code to fix the bug, I had no way to ensure that I was really testing the bug fix.
I backed out my changes and and my new tests were indeed failing -- but they weren't my expected failures. Instead, I had written buggy tests! I fixed the tests, ensured thay failed in ways I was expecting, put my changes back in, made sure the tests passed and checked in my work.
We're now at 3,628 tests on the most complicated application I've ever worked on. We have no code ownership. I might do a quick fix on something that I know better than someone else, but everyone is pretty much free to work on what they will. Somehow, it works, the app is pretty good and development is still rapid.
Testing, without a doubt, is the single best thing I have ever learned about programming. Give me a programmer who only know baby Perl and if I can teach them testing, I'll gladly work with them over the ubercoder who won't test. I should know. The baby Perl programmer sits about twenty feet away from me.