This post is a place-holder for a longer post with examples, but I’ve been sitting on this one for months, so I thought I’d just toss it out there for what its worth.
Unit testing practices often make no bones with writing test names that describe the implementation. You see signs of this when programmer-speak shows up in test names. More egregious words like “returns” and “calls” and “invokes” and “raises” and “throws” litter the test names. In more subtle cases, the test names describe the code in the test method itself.
Behavior-driven test names, or specification names, should describe the experience of the user of the, even if the immediate use is another piece of code.
For example rather than using “…throws an exception” in a test name, you could say, “…is not allowed.”
You might think that this will lead to tests that are less discoverable, but it doesn’t work out that way in practice. When I follow stick to good test code practices and patterns all around, I end up with code that is as discoverable, and often more discoverable than if I tired to capture in the test name that which is already in the test code.
This means having a single concern per test. This often equates to having one assert per test, but the one assert per test rule is a poor choice of language that doesn’t express the essence of the problem directly, and depends on the programmer to already know what the rule is rather than rely on how the rule is commonly expressed by those who already know it instinctively (a common problem in agile development).
It also means keeping setup code focused on a single concern and not using too many mocks. And it means a whole lot of stuff that is probably too subtle to describe than it is to demonstrate in code.