When testing with JUnit, one often has to compare the expected result of a computation with the actual result. A convenient way of doing this is to turn the actual result into a string and then compare two strings. On one hand, the convenience is because converting the actual result to string is often simpler than constructing an object for the expected result (the final decision between these two options depends on which one of the two has applications beyond unit testing). On the other hand, Eclipse helps with string comparisons in two ways:
- Preference “Java → Editor → Typing → Escape text when pasting into a string literal”: Allows one to quickly turn blocks of text into Java string literals for the expected result.
- Built-in diff for assertEquals(): If assertEquals() fails for two strings, Eclipse shows a nice diff of the results. This makes it easy to figure out what went wrong.
Obviously, the output has to be deterministic which is a problem for, say, HashMaps. With this motivation in mind, now a question: What is the quickest way of turning a Map into a string where the keys are sorted?
public static <K extends Comparable<? super K>, V> String toStringSorted(
Map<K, V> map) {
return new TreeMap<K, V>(map).toString();
}
Select the text between the braces to make it visible.
2 comments:
The downside to using strings like this in your tests is that makes them rather brittle -- changing toString's really shouldn't cause tests to fail.
I'd propose that a cleaner solution is to have a utility function which compares two maps, and you pass it matchers for the key and value types. (By "matcher", I mean a Comparator-like strategy that can compare values of two different types to see if they match.)
Once you've done the initial hard work of writing the matchers, it's then really easy to construct expected maps using simple objects (strings, say).
Yes, often a good builder (as in "builder pattern") and an equals method is preferable. Part of the reason why I like string comparison in Eclipse is that the result of a non-string comparison is displayed in a less readable manner.
Tests that fail too easily are not ideal, but still fulfill their purpose (of flagging potential problems). A bigger problem that I've once encountered was that sometimes string comparison does not fail quickly enough, as Integer.toString(1) is equal to "1".toString(), but 1 clearly is not equal to "1".
Post a Comment