It recently hit me that I see unit tests as a form of penance (in addition to being a great tool for specification and test driven development). If you fix a bug and don’t add a unit test I suspect you are not actually sorry.
I admit I have a somewhat hairshirt view of the world. But, I have always taught: if you are writing code you are also writing bugs at some rate (hopefully a low rate). Non-visible bugs are unavoidable and therefore justifiable. But you must work to minimize, find, and mitigate them. Debugging is one of the most expensive and emotionally taxing parts of software development (see Six Stages of Debugging). A lot of the grief associated with bugs is they are often visible to customers and partners. So you really want to as much as possible replace debugging with testing and use unit tests to find your problems (instead of using customers and partners to find your problems). I always prefer a test-suite to a bug-tracker.
Once you have gone to the effort of debugging and diagnosing it is wasteful not to capture a least a piece of the research effort in a new unit test. Think of it as a miniature 5-whys exercise: adding the question “why did the bug go unnoticed.”
What set me to thinking about this was a minor flaw (now fixed) in the book we are working on. The issue is that the code examples for the book are stored in XML which requires entity escaping for many special characters that are in fact quite common in source code. At at some point the obvious happened: a few sections got double escaped changing R‘s assignment operator from <- (which has to be encoded as <-) to &lt;- (encoding, quoting, commenting and escaping: endless sources of unforseen consequences). So I did a “belt and suspenders” fix. I used grep to find the problems (and fixed them by hand) and upgraded the code example manager to warn if the string “&” is found in any processed example.
It is what I expect of myself, which means it is also somewhat what I expect from others (even when I am too polite to say so).