From: <gu...@st...> - 2002-02-18 16:56:00
|
The method assertEquals(String, String) is very useful, but breaks down with large strings. The problem is that, if the strings differ in only a few characters, or start to differ more than a few lines in, the error message is almost completely useless. expected:<HUGE STRING> but was:<NEARLY IDENTICAL HUGE STRING> When you add in line breaks it gets impossible to "eyeball" the error message and know what's going wrong. It also breaks up the format of the output report with miles of strings, possibly including line breaks. I've written some code that fixes this. The output for a failed test with message "HTML Report" is: HTML Report: strings differ at character 22 Expected: ...>Poll:</b> dummy<br>\n<b>Question:</b> Vote for your favor... Actual: ...>Poll:</b> dummy<br>\r\n<b>Question:</b> Vote for your favo... Note that you can tell right off the bat that the problem is a difference in line endings (since my code escapes those). This particular bug was actually impossible for me to track down using the normal failure message, since line endings are invisible. I'd like to contribute the code to JUnit. I'm just not sure where you want to put it. I see three options: 1. Change the behavior of the existing Assert.assertEquals(String, String) (I don't think this would break anybody's tests, and I doubt anyone has written code that depends on the actual format of the string error messages. I could be wrong, of course.) 2. Add a new assertEqualsDiff to class Assert (This would mean that the benefit of the new messages would not be given to existing tests without massive test code rewrites.) 3. Make a new DiffTestCase that overrides assertEquals (Same problem as above -- existing test code would need to be rewritten. It's also a sloppy substitute for mixins...) If you guys want the code, let me know, and I'll download the JUnit source and give you a patch. - A P.S. I've attached the current version below. I don't think this is the final version, though -- I want it to be smarter about diffs close to the start and end of the strings. -- Alex Chaffee mailto:al...@jg... jGuru - Java News and FAQs http://www.jguru.com/alex/ Creator of Gamelan http://www.gamelan.com/ Founder of Purple Technology http://www.purpletech.com/ Curator of Stinky Art Collective http://www.stinky.com/ void assertEqualsDiff(String message, String expected, String actual) { if (!expected.equals(actual)) { if (expected.length() < 20 || actual.length() < 20) { assertEquals(message, expected, actual); return; // we'll get an exception, but just in case } int at = strdiffat(actual, expected); String expectedContext = Utils.abbreviate(expected.substring(at - 20), 60); String actualContext = Utils.abbreviate(actual.substring(at - 20), 60); assertTrue(message + ": strings differ at character " + at + "\n" + "Expected: ..." + Utils.jsEscape(expectedContext) + "\n" + " Actual: ..." + Utils.jsEscape(actualContext) + "\n", false); } } /** * returns the index where the strings diverge<p> * strdiff("i am a machine", "i am a robot") -> 7<p> * @return -1 if they are the same * **/ public static int strdiffat(String s1, String s2) { int i; for (i=0; i<s1.length() && i<s2.length(); ++i) { if (s1.charAt(i) != s2.charAt(i)) { break; } } if (i<s2.length() || i<s1.length()) return i; return -1; } for abbreviate() and jsEscape() see http://www.purpletech.com/code/src/com/purpletech/util/Utils.java |