There’s a principle (little-“p”) in the Agile / XP world that your unit tests should roughly reflect your software requirements. Part of this has to do with the fact that if there’s a requirement, it should be tested, and part of it has to do with the low-documentation/code-sharing ethic. In this second scenario, a new developer should be able to get a pretty good handle on what the tested code is supposed to do merely by going through the unit tests.
Of course, as with most software rules of thumb, that’s an abstraction, but it speaks to a real mindset.
I’ve found during those times where I get “stuck” playing around with a new piece of software I’m developing, that when I go back and look at the unit tests, it’s a lot of property testing, and not nearly enough method testing. In other words, I overemphasize state at the expense of behavior. This is a bad thing. In the first case, properties are too easy to test: get/set blocks, assignments and .AreEqual calls, etc. Methods are harder to test — branches, function overloading, loops, messy stuff. In the second case, software is meant to DO something — even state changes are an active process, in the sense that something acts on the software to change its state.
Part of my problem may be too heavy an OOP mindset, in the sense that my first instincts are to say “what is this thing?” rather than “how does this thing behave?”
The answer? Back to theory to get a fresh perspective. Nothing like snuggling up with Grady Booch to get back to first principles and recharge the batteries.