Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c75bb85

Browse files
committedJul 18, 2023
add a diff section to report of AssertionFailedError
With this commit, a dependency to https://github.com/java-diff-utils/java-diff-utils is introduced. java-diff-utils is used to create a diff from the expected and the actual result and report it. See #3139
1 parent acb6e65 commit c75bb85

File tree

5 files changed

+76
-1
lines changed

5 files changed

+76
-1
lines changed
 

‎gradle/libs.versions.toml

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ gradle-versions = { module = "com.github.ben-manes:gradle-versions-plugin", vers
4141
groovy4 = { module = "org.apache.groovy:groovy", version = "4.0.13" }
4242
groovy2-bom = { module = "org.codehaus.groovy:groovy-bom", version = "2.5.21" }
4343
hamcrest = { module = "org.hamcrest:hamcrest", version = "2.2" }
44+
java-diff-utils = { module = "io.github.java-diff-utils:java-diff-utils", version = "4.12" }
4445
jfrunit = { module = "org.moditect.jfrunit:jfrunit-core", version = "1.0.0.Alpha2" }
4546
jimfs = { module = "com.google.jimfs:jimfs", version = "1.3.0" }
4647
jmh-core = { module = "org.openjdk.jmh:jmh-core", version.ref = "jmh" }

‎junit-platform-console/junit-platform-console.gradle.kts

+5-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ dependencies {
1515

1616
compileOnly(libs.openTestReporting.events)
1717

18+
implementation(libs.java.diff.utils)
19+
1820
shadowed(libs.picocli)
1921

2022
osgiVerification(projects.junitJupiterEngine)
@@ -27,7 +29,9 @@ tasks {
2729
"--add-modules", "org.opentest4j.reporting.events",
2830
"--add-reads", "${project.projects.junitPlatformReporting.dependencyProject.javaModuleName}=org.opentest4j.reporting.events",
2931
"--add-modules", "info.picocli",
30-
"--add-reads", "${javaModuleName}=info.picocli"
32+
"--add-reads", "${javaModuleName}=info.picocli",
33+
"--add-modules", "io.github.javadiffutils",
34+
"--add-reads", "${javaModuleName}=io.github.javadiffutils"
3135
))
3236
}
3337
shadowJar {

‎junit-platform-console/src/main/java/org/junit/platform/console/tasks/ConsoleTestExecutor.java

+3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import java.util.Optional;
2222
import java.util.function.Supplier;
2323

24+
import com.github.difflib.text.DiffRowGenerator;
25+
2426
import org.apiguardian.api.API;
2527
import org.junit.platform.commons.JUnitException;
2628
import org.junit.platform.commons.util.ClassLoaderUtils;
@@ -143,6 +145,7 @@ private SummaryGeneratingListener registerListeners(PrintWriter out, Optional<Pa
143145
private Optional<DetailsPrintingListener> createDetailsPrintingListener(PrintWriter out) {
144146
ColorPalette colorPalette = getColorPalette();
145147
Theme theme = outputOptions.getTheme();
148+
146149
switch (outputOptions.getDetails()) {
147150
case SUMMARY:
148151
// summary listener is always created and registered

‎junit-platform-console/src/main/java/org/junit/platform/console/tasks/FlatPrintingListener.java

+34
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,20 @@
1111
package org.junit.platform.console.tasks;
1212

1313
import java.io.PrintWriter;
14+
import java.util.Arrays;
15+
import java.util.List;
16+
import java.util.stream.Collectors;
17+
18+
import com.github.difflib.text.DiffRow;
19+
import com.github.difflib.text.DiffRowGenerator;
1420

1521
import org.junit.platform.commons.util.ExceptionUtils;
22+
import org.junit.platform.commons.util.StringUtils;
1623
import org.junit.platform.engine.TestExecutionResult;
1724
import org.junit.platform.engine.reporting.ReportEntry;
1825
import org.junit.platform.launcher.TestIdentifier;
1926
import org.junit.platform.launcher.TestPlan;
27+
import org.opentest4j.AssertionFailedError;
2028

2129
/**
2230
* @since 1.0
@@ -27,10 +35,19 @@ class FlatPrintingListener implements DetailsPrintingListener {
2735

2836
private final PrintWriter out;
2937
private final ColorPalette colorPalette;
38+
private final DiffRowGenerator diffRowGenerator;
3039

3140
FlatPrintingListener(PrintWriter out, ColorPalette colorPalette) {
3241
this.out = out;
3342
this.colorPalette = colorPalette;
43+
this.diffRowGenerator = DiffRowGenerator.create() //
44+
.showInlineDiffs(true) //
45+
.mergeOriginalRevised(true) //
46+
.inlineDiffByWord(true) //
47+
.oldTag(f -> "~") //
48+
.newTag(f -> "**") //
49+
.build();
50+
;
3451
}
3552

3653
@Override
@@ -78,9 +95,26 @@ private void printlnTestDescriptor(Style style, String message, TestIdentifier t
7895
}
7996

8097
private void printlnException(Style style, Throwable throwable) {
98+
if (throwable instanceof AssertionFailedError) {
99+
AssertionFailedError assertionFailedError = (AssertionFailedError) throwable;
100+
String expected = assertionFailedError.getExpected().getStringRepresentation();
101+
String actual = assertionFailedError.getActual().getStringRepresentation();
102+
String diff = calculateDiff(expected, actual);
103+
104+
printlnMessage(style, "Expected ", expected);
105+
printlnMessage(style, "Actual ", actual);
106+
printlnMessage(style, "Diff ", diff);
107+
}
81108
printlnMessage(style, "Exception", ExceptionUtils.readStackTrace(throwable));
82109
}
83110

111+
private String calculateDiff(String expected, String actual) {
112+
List<String> expectedLines = Arrays.asList(StringUtils.nullSafeToString(expected));
113+
List<String> actualLines = Arrays.asList(StringUtils.nullSafeToString(actual));
114+
List<DiffRow> diffRows = diffRowGenerator.generateDiffRows(expectedLines, actualLines);
115+
return diffRows.stream().map(DiffRow::getOldLine).collect(Collectors.joining("\n"));
116+
}
117+
84118
private void printlnMessage(Style style, String message, String detail) {
85119
println(style, INDENTATION + "=> " + message + ": %s", indented(detail));
86120
}

‎platform-tests/src/test/java/org/junit/platform/console/tasks/FlatPrintingListenerTests.java

+33
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.junit.platform.engine.reporting.ReportEntry;
2727
import org.junit.platform.fakes.TestDescriptorStub;
2828
import org.junit.platform.launcher.TestIdentifier;
29+
import org.opentest4j.AssertionFailedError;
2930

3031
/**
3132
* @since 1.0
@@ -71,6 +72,38 @@ void executionFinishedWithFailure() {
7172
() -> assertEquals(INDENTATION + "=> Exception: java.lang.AssertionError: Boom!", lines[1]));
7273
}
7374

75+
@Nested
76+
class DiffOutputTests {
77+
@Test
78+
void printDiffForAssertionFailedErrors() {
79+
var stringWriter = new StringWriter();
80+
listener(stringWriter).executionFinished(newTestIdentifier(),
81+
failed(new AssertionFailedError("Detail Message", "Expected content", "Actual content")));
82+
var lines = lines(stringWriter);
83+
84+
assertTrue(lines.length >= 5, "At least 5 lines are expected in failure report!");
85+
assertAll("lines in the output", //
86+
() -> assertEquals("Finished: demo-test ([engine:demo-engine])", lines[0]), //
87+
() -> assertEquals(INDENTATION + "=> Expected : Expected content", lines[1]), //
88+
() -> assertEquals(INDENTATION + "=> Actual : Actual content", lines[2]), //
89+
() -> assertEquals(INDENTATION + "=> Diff : ~Expected~**Actual** content", lines[3]), //
90+
() -> assertEquals(INDENTATION + "=> Exception: org.opentest4j.AssertionFailedError: Detail Message",
91+
lines[4]));
92+
}
93+
94+
@Test
95+
void ignoreDiffForAnyAssertionErrors() {
96+
var stringWriter = new StringWriter();
97+
listener(stringWriter).executionFinished(newTestIdentifier(), failed(new AssertionError("Detail Message")));
98+
var lines = lines(stringWriter);
99+
100+
assertTrue(lines.length >= 2, "At least 2 lines are expected in failure report!");
101+
assertAll("lines in the output", //
102+
() -> assertEquals("Finished: demo-test ([engine:demo-engine])", lines[0]), //
103+
() -> assertEquals(INDENTATION + "=> Exception: java.lang.AssertionError: Detail Message", lines[1]));
104+
}
105+
}
106+
74107
@Nested
75108
class ColorPaletteTests {
76109

0 commit comments

Comments
 (0)
Please sign in to comment.