Wednesday, 13 August 2008

JUnit 4.4: Why I don't like assertThat

A colleague pointed at the release notes for JUnit 4.4. He was really happy about the new assertThat. I've tried and tried, but I can't share his enthusiasm.

Here are their four examples from the release notes:
assertThat(x, is(3));
assertThat(x, is(not(4)));
assertThat(responseString, either(containsString("color")).or(containsString("colour")));
assertThat(myList, hasItem("3"));
And here is how I'd write that at the moment:
assertTrue("Unexpected value for x, was expecting 3", x==3);
assertTrue("x should not be 4",
"responseString should contain color/colour", responseString.matches(".*colo(u)?r.*"));
"Item 3 not present in myList", myList.contains("3"));

The release notes and my colleague both say that assertThat is shiny because it automatically outputs readable error messages. But I already write readable error messages. (Doesn't everybody? Who in their right mind decided that "AssertionError" with no extra text would help them later when the test failed?) Leaving aside the generic examples from the release notes, a typical message from one of my assertions would be more like "Order 1234: Buy Order's side was Sell instead of Buy". I'd argue that my error messages are more readable and more helpful.

Writing my own messages has the glorious side effect that the error message is documenting what I think the assertion is asserting. I'm effectively adding a comment to each assertion which can be checked by the poor soul who has to look through this stuff in 5 years' time when the test suddenly breaks.

The main reason I'm not a fan of assertThat, though, is that I've devoted a deal of brain space to boolean expressions in C-like languages and a deal more to Java's class libraries. Having done that, I instinctively dislike the idea of having to expend mental effort on internally translating someChar, is('b') into someChar=='b'. Even if it does give me vaguely readable error messages.

1 comment:

alexandroid said...

Your statements will not display the actual value of the variables. I.e. in the first example, they won't tell you what value of 'x' was, they only tell that it is not equal to expected 4. Same for responseString and myList.

When such assertion fails, sometimes it is very obvious what is wrong. But sometimes you need to spend more time to actually debug the test to see the real value of 'x' or other variable being compared.

assertThat saves you that time.