« It's Alive! | Main | A Pattern By Any Other Name Would Still Sell As Well »
March 14, 2004
RE assertions in JUnit
Whilst busily TDDing the other day, I found myself writing a lot of test code like:
assertTrue(foo.endsWith("bar"));
where foo and bar are both of type String.
My tests didn't care how the start of foo looked, only the end so I didn't want to make them too brittle by using assertEquals.
And here's the rub...
I really like assertEquals. The thing which raises this method above the rest of JUnit's is that a failure of one of these calls results in an instantly useful error message along the lines of "Expected 'foo' but got 'bar'". All you get when an assertTrue fails is a most unhelpful AssertionFailedError.
So, to allow me to maintain my fidelity to assertEquals whilst still keeping my tests fairly clear and loose, I came up with:
public void assertLike(String expected, String actual) throws AssertionFailedError {
Pattern pattern = Pattern.compile(expected, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(actual);
try {
assertTrue(matcher.find());
} catch (AssertionFailedError e) {
throw new ComparisonFailure("RE comparison failed - ", expected, actual);
}
}
In short, I'm using the inbuilt JDK RE classes to provide "fuzzy" matching in assertion checks and, if a check fails, emulating an assertEquals failure to present the error in the format I like. The method can be invoked as follows:
assertLike(".bar", foo);
Using RE matching in assertion easily leads to a far richer set of string assertion methods (wrapping assertLike) along the lines of:
assertEndsWithassertBeginsWithassertContainsassertDoesNotContain
However, I'll leave this stuff as an exercise for the reader.
p.s. Eclipse does a really nice job of present these errors in it's JUnit plugin. I'll post a screenshot as soon as I work out how to post images to this blog.
Posted by Andy Marks at March 14, 2004 07:24 PM
Comments
Actually, you can use the overloaded AssertTrue method in which the first parameter is a String that displays when the assertion fails. Such as
Asserts.assertTrue("The value of foo did not end in bar", foo.endsWith("bar"));
In fact, all of the assert methods in JUnit have this overloaded method. Most of the other assert methods are convenience methods that end up using assertTrue anyway.
Posted by: Pamela at March 24, 2004 11:02 AM
The problem, of course, is that the convenience methods are exactly that: convenient. If you've got a common test, writing a new convenience method helps a lot.
One I often end up doing is an assertContentsEquals(), where I verify that two collections hold the same data.
Andy, if I was you, I'd put an explanatory message into the assertTrue call...
Posted by: Robert Watkins at March 31, 2004 08:57 PM
Post a comment
Thanks for signing in, . Now you can comment. (sign out)
(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)