I have always advocated this but still I learned the same lesson last week and that is what is driving me to write this (This also serves as a not for me). Am working on a project which is an large inherited legacy app. Most of the application has been rewritten except for a few parts. And the work I was doing kind of flows from new parts to old parts. It all started well as my work spanned mostly new parts, normal Red->Green->Refactor cycle. After my work was completed, I wanted to check the end to end flow so I ran the Selenium test. It all went fine till the part where the app reached the old code. Then all hell broke loose. A table which was supposed to show the past orders was not coming up. We weren't able to localise the problem as there was no tests covering that area. We knew what was broken but not where and so had to debug though hell for next three hours to find what was happening and solve the problem as well write tests.
It is nice that I had selenium test and it helped me in catching the problem. But it couldn't do more than that for me (Or at least I couldn't do more :). What I really wanted was a test which could tell me where exactly it is broken like a x-ray which doctor uses to find a broken bone. And shallow and broadly focused selenium test couldn't show me that. A better test for this situation would be a unit test or a focused integration test which can tell me where exactly the app is broken. Localizing a defect is a very important characteristic of these kinds of tests and it is this property which is important when something is broken. It is frustrating to find a test which says something is broken but not where. Also even if we have a unit test it should not be testing too many things at a time in the unit as we will not know what failed. So we need small tests which is focused in testing the behavior.
Does that mean if I have these test I don't need to debug? Well sometimes I don't but most of the time they help me find where I need to debug exactly to see the values coming it. I don't need to debug though all the layers or across layers to find five lines of code having the problem.
So writing small and focussed tests is good and if you have a legacy code base it is even more important to start doing this as soon as possible. I like writing small and focussed tests even at functional level though I have end to end tests also.
P.S May be I will add code examples here for this post. But now my code highlighter is broken so deferring it till I fix that :)