forked from junit-team/junit4
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request junit-team#919 from AlexYursha/comparison-failure
Improve readability of ComparisonFailure
- Loading branch information
Showing
1 changed file
with
73 additions
and
63 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,10 @@ | ||
package org.junit; | ||
|
||
/** | ||
* Thrown when an {@link org.junit.Assert#assertEquals(Object, Object) assertEquals(String, String)} fails. Create and throw | ||
* a <code>ComparisonFailure</code> manually if you want to show users the difference between two complex | ||
* strings. | ||
* | ||
* Thrown when an {@link org.junit.Assert#assertEquals(Object, Object) assertEquals(String, String)} fails. | ||
* Create and throw a <code>ComparisonFailure</code> manually if you want to show users the | ||
* difference between two complex strings. | ||
* <p/> | ||
* Inspired by a patch from Alex Chaffee ([email protected]) | ||
* | ||
* @since 4.0 | ||
|
@@ -35,8 +35,7 @@ public ComparisonFailure(String message, String expected, String actual) { | |
} | ||
|
||
/** | ||
* Returns "..." in place of common prefix and "..." in | ||
* place of common suffix between expected and actual. | ||
* Returns "..." in place of common prefix and "..." in place of common suffix between expected and actual. | ||
* | ||
* @see Throwable#getMessage() | ||
*/ | ||
|
@@ -65,28 +64,20 @@ public String getExpected() { | |
|
||
private static class ComparisonCompactor { | ||
private static final String ELLIPSIS = "..."; | ||
private static final String DELTA_END = "]"; | ||
private static final String DELTA_START = "["; | ||
private static final String DIFF_END = "]"; | ||
private static final String DIFF_START = "["; | ||
|
||
/** | ||
* The maximum length for <code>expected</code> and <code>actual</code> strings to show. When <code>contextLength</code> | ||
* is exceeded, the Strings are shortened. | ||
*/ | ||
private int contextLength; | ||
|
||
private String expected; | ||
private String actual; | ||
|
||
/** | ||
* The length of the shared prefix / suffix of the expected and actual strings. | ||
* Equals to zero if the strings do not share a common prefix/suffix. | ||
* The maximum length for <code>expected</code> and <code>actual</code> strings to show. When | ||
* <code>contextLength</code> is exceeded, the Strings are shortened. | ||
*/ | ||
private int prefix; | ||
private int suffix; | ||
private final int contextLength; | ||
private final String expected; | ||
private final String actual; | ||
|
||
/** | ||
* @param contextLength the maximum length for <code>expected</code> and <code>actual</code> strings. When contextLength | ||
* is exceeded, the Strings are shortened. | ||
* @param contextLength the maximum length of context surrounding the difference between the compared strings. | ||
* When context length is exceeded, the prefixes and suffixes are compacted. | ||
* @param expected the expected string value | ||
* @param actual the actual string value | ||
*/ | ||
|
@@ -96,61 +87,80 @@ public ComparisonCompactor(int contextLength, String expected, String actual) { | |
this.actual = actual; | ||
} | ||
|
||
private String compact(String message) { | ||
if (expected == null || actual == null || areStringsEqual()) { | ||
public String compact(String message) { | ||
if (expected == null || actual == null || expected.equals(actual)) { | ||
return Assert.format(message, expected, actual); | ||
} else { | ||
DiffExtractor extractor = new DiffExtractor(); | ||
String compactedPrefix = extractor.compactPrefix(); | ||
String compactedSuffix = extractor.compactSuffix(); | ||
return Assert.format(message, | ||
compactedPrefix + extractor.expectedDiff() + compactedSuffix, | ||
compactedPrefix + extractor.actualDiff() + compactedSuffix); | ||
} | ||
|
||
findCommonPrefix(); | ||
findCommonSuffix(); | ||
String expected = compactString(this.expected); | ||
String actual = compactString(this.actual); | ||
return Assert.format(message, expected, actual); | ||
} | ||
|
||
private String compactString(String source) { | ||
String result = DELTA_START + source.substring(prefix, source.length() - suffix) + DELTA_END; | ||
if (prefix > 0) { | ||
result = computeCommonPrefix() + result; | ||
} | ||
if (suffix > 0) { | ||
result = result + computeCommonSuffix(); | ||
} | ||
return result; | ||
} | ||
|
||
private void findCommonPrefix() { | ||
prefix = 0; | ||
private String sharedPrefix() { | ||
int end = Math.min(expected.length(), actual.length()); | ||
for (; prefix < end; prefix++) { | ||
if (expected.charAt(prefix) != actual.charAt(prefix)) { | ||
break; | ||
for (int i = 0; i < end; i++) { | ||
if (expected.charAt(i) != actual.charAt(i)) { | ||
return expected.substring(0, i); | ||
} | ||
} | ||
return expected.substring(0, end); | ||
} | ||
|
||
private void findCommonSuffix() { | ||
int expectedSuffix = expected.length() - 1; | ||
int actualSuffix = actual.length() - 1; | ||
for (; actualSuffix >= prefix && expectedSuffix >= prefix; actualSuffix--, expectedSuffix--) { | ||
if (expected.charAt(expectedSuffix) != actual.charAt(actualSuffix)) { | ||
private String sharedSuffix(String prefix) { | ||
int suffixLength = 0; | ||
int maxSuffixLength = Math.min(expected.length() - prefix.length(), | ||
actual.length() - prefix.length()) - 1; | ||
for (; suffixLength <= maxSuffixLength; suffixLength++) { | ||
if (expected.charAt(expected.length() - 1 - suffixLength) | ||
!= actual.charAt(actual.length() - 1 - suffixLength)) { | ||
break; | ||
} | ||
} | ||
suffix = expected.length() - expectedSuffix - 1; | ||
return expected.substring(expected.length() - suffixLength); | ||
} | ||
|
||
private String computeCommonPrefix() { | ||
return (prefix > contextLength ? ELLIPSIS : "") + expected.substring(Math.max(0, prefix - contextLength), prefix); | ||
} | ||
private class DiffExtractor { | ||
private final String sharedPrefix; | ||
private final String sharedSuffix; | ||
|
||
private String computeCommonSuffix() { | ||
int end = Math.min(expected.length() - suffix + contextLength, expected.length()); | ||
return expected.substring(expected.length() - suffix, end) + (expected.length() - suffix < expected.length() - contextLength ? ELLIPSIS : ""); | ||
} | ||
/** | ||
* Can not be instantiated outside {@link org.junit.ComparisonFailure.ComparisonCompactor}. | ||
*/ | ||
private DiffExtractor() { | ||
sharedPrefix = sharedPrefix(); | ||
sharedSuffix = sharedSuffix(sharedPrefix); | ||
} | ||
|
||
private boolean areStringsEqual() { | ||
return expected.equals(actual); | ||
public String expectedDiff() { | ||
return extractDiff(expected); | ||
} | ||
|
||
public String actualDiff() { | ||
return extractDiff(actual); | ||
} | ||
|
||
public String compactPrefix() { | ||
if (sharedPrefix.length() <= contextLength) { | ||
return sharedPrefix; | ||
} | ||
return ELLIPSIS + sharedPrefix.substring(sharedPrefix.length() - contextLength); | ||
} | ||
|
||
public String compactSuffix() { | ||
if (sharedSuffix.length() <= contextLength) { | ||
return sharedSuffix; | ||
} | ||
return sharedSuffix.substring(0, contextLength) + ELLIPSIS; | ||
} | ||
|
||
private String extractDiff(String source) { | ||
return DIFF_START + source.substring(sharedPrefix.length(), source.length() - sharedSuffix.length()) | ||
+ DIFF_END; | ||
} | ||
} | ||
} | ||
} | ||
} |