First, a disclaimer: I admit to being a bit of a sucker for Kent Beck's view that tests should read like a story.Readable tests are good. Readable tests are important, if the tests are to self-document. My question is is there such a thing as 'too readable'? That's rhetorical by the way - of course there isn't. What can be overdone is the work involved in obtaining the clarity we're looking for. This post is the first of a series on how I do it. Hopefully I'm not being a total idiot.
I use Hamcrest. Perhaps too much at times, in fact. I like to look at my tests and see the following:
Meeting meeting = sut.doStuff();Add to that the benefit that when it fails, you get nice messages like:
assertThat(meeting, startsAt(midnight()));
assertThat(meeting, endsAt(oneAm()));
expected: a meeting starting at midnightinstead of a message-less AssertionError (yes, I know I can specify a message, but that's even less readable to my mind). Of course, the down side of some of this readability is the extra code required to create the matchers. For the most part I find that a small price to pay to avoid this:
got: <result of Meeting.toString()>
Meeting meeting = sut.doStuff();
assertEquals(0L,meeting.getStart().getTime());
assertEquals(3600000L, meeting.getEnd().getTime());
Note I say for the most part. Sometimes, the code involved in creating the matchers is quite bulky, requiring as it does both a description method and the actual matching logic. Where do you draw the line? 80/20 rule, DRY, write-twice-refactor, all have their place. My view (as I've said above) is that there is a lot of value in readable tests, and knocking together matchers for them is mostly boilerplate and very little actual work. Worth the time, in all but the most extreme cases, which is why I say I may like Hamcrest a little more than I should.
A second disclaimer: I am a testability nerd - an interested amateur, but evangelical none the less. Those who have asked me for code reviews feel the pain on occasion, but hopefully this helps explain my reasoning.