Sample

Schnappinger/junit4/org.junit.ComparisonFailure

Human rating uses the original dataset scale.

Human3.75
Lines156

Scores

MethodScoreScaleDataset rank
(0–100)
Posnett00–1; higher is more readable
38.1Δ 5.1
Scalabrino0.6960–1; higher is more readable
37.7Δ 5.6
Dorn0.0770–1; higher is more readable
30.7Δ 12.5
Mi0.1690–1; higher is more readable
13.2Δ 30.0
LLOC60Logical lines; fewer is more readable
34.7Δ 8.6
DeepSeek V4 Pro170–20; mean of three runs
66.8Δ 23.6
GPT-6.1 Sol170–20; mean of three runs
55.3Δ 12.0
BTTF0.3490–1; higher is more readable
27.1Δ 16.2
Human3.751–4; original rating
43.2

Views

Source code

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. * * Inspired by a patch from Alex Chaffee (alex@purpletech.com) * * @since 4.0 */ public class ComparisonFailure extends AssertionError { /** * The maximum length for expected and actual strings. If it is exceeded, the strings should be shortened. * * @see ComparisonCompactor */ private static final int MAX_CONTEXT_LENGTH = 20; private static final long serialVersionUID = 1L; private String expected; private String actual; /** * Constructs a comparison failure. * * @param message the identifying message or null * @param expected the expected string value * @param actual the actual string value */ public ComparisonFailure(String message, String expected, String actual) { super(message); this.expected = expected; this.actual = actual; } /** * Returns "..." in place of common prefix and "..." in * place of common suffix between expected and actual. * * @see Throwable#getMessage() */ @Override public String getMessage() { return new ComparisonCompactor(MAX_CONTEXT_LENGTH, expected, actual).compact(super.getMessage()); } /** * Returns the actual string value * * @return the actual string value */ public String getActual() { return actual; } /** * Returns the expected string value * * @return the expected string value */ public String getExpected() { return expected; } private static class ComparisonCompactor { private static final String ELLIPSIS = "..."; private static final String DELTA_END = "]"; private static final String DELTA_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. */ private int prefix; private int suffix; /** * @param contextLength the maximum length for <code>expected</code> and <code>actual</code> strings. When contextLength * is exceeded, the Strings are shortened. * @param expected the expected string value * @param actual the actual string value */ public ComparisonCompactor(int contextLength, String expected, String actual) { this.contextLength = contextLength; this.expected = expected; this.actual = actual; } private String compact(String message) { if (expected == null || actual == null || areStringsEqual()) { return Assert.format(message, expected, actual); } 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; int end = Math.min(expected.length(), actual.length()); for (; prefix < end; prefix++) { if (expected.charAt(prefix) != actual.charAt(prefix)) { break; } } } 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)) { break; } } suffix = expected.length() - expectedSuffix - 1; } private String computeCommonPrefix() { return (prefix > contextLength ? ELLIPSIS : "") + expected.substring(Math.max(0, prefix - contextLength), prefix); } 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 : ""); } private boolean areStringsEqual() { return expected.equals(actual); } } }

Loading feature diagnosis…

Source regions

Feature contributions

Feature contributions

FeatureValueContribution
(log-odds)
Halstead volumeHow much symbolic information the code contains. It combines the total number of operators and values with the number of distinct ones.3914.587−129.181
Source linesThe number of non-empty source lines.156+62.4
Byte entropyHow varied the bytes in the source text are. Repeated bytes give a lower value; a more even mixture gives a higher value.4.471−6.706

Intercept 8.87 + feature contributions = -64.618 (log-odds).
Score = sigmoid(-64.618) = 0.

Score0.696

Feature contributions

FeatureValueContribution
(log-odds)
Comment layout frequencyHow frequently the layout switches between lines containing only comments or whitespace and lines containing code.156−4.487
Indentation frequencyHow rapidly indentation changes from line to line.114+3.206
Identifier layout (horizontal)How rapidly the visual pattern of identifier characters changes from left to right. It measures spatial frequency, not the meaning of the names.153.981−2.857
Number layout frequencyHow rapidly the number of numeric values per line changes through the code.114−2.195
Identifier layout (vertical)How rapidly the visual pattern of identifier characters changes from top to bottom.154.871+1.755
Comment layout (horizontal)How rapidly the visual pattern of comment characters changes from left to right.153.974+1.68
Operator visual areaThe share of the code’s visual area occupied by operators such as +, =, and *.0.062+0.339

Intercept 0.07 + feature contributions = -2.489 (log-odds).
Score = sigmoid(-2.489) = 0.077.

Score0.169
Score60
Run 1

The code is well-structured and highly readable. It follows a clean logical organization with a clear separation between the outer exception class and its inner helper class. Nesting is minimal: only one level of nested class plus short, flat methods. The intent is very clear—both the class-level Javadoc and method comments explain the failure-diff formatting logic. Code length is appropriate, with each method focused on a single responsibility. Action granularity is good: most lines perform one operation, and loop constructs are compact but understandable. The reading flow is natural—fields, constructors, public getters, then private helper methods in the order they are used. Minor deductions: the `findCommonSuffix` loop uses two control variables that may require a moment to parse, and `computeCommonSuffix` has a slightly dense condition. Overall, this is exemplary Java code with strong readability.

Run 2

The code is well-structured and readable. The class hierarchy is clear (ComparisonFailure extends AssertionError), fields are logically grouped, and methods are concise with descriptive names. Nesting is minimal, and the inner ComparisonCompactor class cleanly separates string-compaction logic. Clarity of intent is mostly strong due to good Javadoc comments. However, the compactString method relies on substring arithmetic that could be cryptic without careful reading, slightly reducing clarity. Method length is acceptable, and most lines perform one action. Reading flow is natural, but some complexity in computeCommonPrefix/computeCommonSuffix and the loop conditions in findCommonSuffix may require extra attention. Overall, the code is maintainable but could benefit from minor refactoring or additional comments around the substring logic.

Run 3

The code is well-structured, with a clear separation between the exception class and its internal string-compaction logic. It uses a private static nested class to encapsulate helper behavior, which keeps the main class focused. Nesting is minimal and methods are small, single-purpose, and named clearly. Javadoc comments explain intent for both the class and its methods. The private helper methods (findCommonPrefix, findCommonSuffix, computeCommonPrefix, computeCommonSuffix) are logically ordered and each performs one action, aiding readability. The only minor drawbacks are slightly dense string-building logic in computeCommonSuffix and a few long lines, but these do not significantly hinder understanding. Overall, the code is highly readable and maintainable.

Run 1

1. Code Structure: Well organized into an exception class and a dedicated compactor, with focused helper methods. 2. Nesting: Shallow overall; loops contain only simple conditional breaks. 3. Clarity of intent: Descriptive names and documentation explain string comparison and compaction, although context-length comments misleadingly suggest a maximum total string length. Local variables shadow fields, and suffix arithmetic requires careful reading. 4. Code length: Generally concise, though repetitive documentation and a trivial equality wrapper add modest overhead. 5. Action granularity: Mostly one action per line; the suffix loop updates two indices, and long return expressions combine several operations. 6. Reading flow: Compaction proceeds naturally from validation through shared-prefix/suffix detection to formatting. Stateful helper dependencies and dense substring calculations slightly interrupt otherwise clear flow.

Run 2

Code Structure: Well organized, separating the exception interface from string-compaction logic in a nested helper class with focused methods. Nesting: Shallow conditionals and loops keep control flow easy to follow. Clarity of intent: Descriptive names and documentation explain the overall purpose, although prefix/suffix index arithmetic requires careful reading and context-length comments are slightly misleading. Code length: Mostly concise, with some repetitive documentation and a trivial equality helper adding modest verbosity. Action granularity: Most lines perform one clear action; the suffix loop updates two counters, and long substring/concatenation expressions combine several operations. Reading flow: Methods follow a logical progression from comparison to prefix/suffix discovery and formatting. Mutable helper state and local variables shadowing expected/actual fields introduce minor cognitive overhead.

Run 3

Code Structure: Well organized, with the exception API separated from string-compaction logic in a private helper class. Nesting: Shallow control flow; loops contain only simple comparisons, and an early return handles special cases. Clarity of intent: Descriptive method names and documentation explain the purpose, although mutable prefix/suffix state, local variables shadowing fields, and index arithmetic require extra attention. Code length: Methods are short and focused, but some documentation is repetitive. Action granularity: Mostly one action per line; the suffix loop updates two indices, and several return expressions combine multiple operations. Reading flow: Compaction proceeds naturally from validation to finding shared regions and formatting differences. Long substring expressions and implicit dependencies between helper methods slightly interrupt otherwise clear reading.