Skip to content

Commit 824e0c8

Browse files
authored
Prune stack traces up to test method (#4829)
Everything before the test method is invoked is not informative for the end user. Discarding that part of the stacktrace removes a few more frames. Additionally, when pruning consider the source of the test descriptor not merely its ancestors. Fixes #4828.
1 parent 2466457 commit 824e0c8

File tree

4 files changed

+19
-13
lines changed

4 files changed

+19
-13
lines changed

documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC1.adoc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ repository on GitHub.
2626
[[release-notes-6.0.0-RC1-junit-platform-new-features-and-improvements]]
2727
==== New Features and Improvements
2828

29-
* ❓
30-
29+
* Prune stack traces up to test or lifecycle method
3130

3231
[[release-notes-6.0.0-RC1-junit-jupiter]]
3332
=== JUnit Jupiter

junit-platform-commons/src/main/java/org/junit/platform/commons/util/ExceptionUtils.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,15 @@ public static String readStackTrace(Throwable throwable) {
9797
}
9898

9999
/**
100-
* Prune the stack trace of the supplied {@link Throwable} by removing
101-
* {@linkplain StackTraceElement stack trace elements} from the {@code org.junit},
102-
* {@code jdk.internal.reflect}, and {@code sun.reflect} packages. If a
103-
* {@code StackTraceElement} matching one of the supplied {@code classNames}
104-
* is encountered, all subsequent elements in the stack trace will be retained.
100+
* Prune the stack trace of the supplied {@link Throwable}.
101+
*
102+
* <p>Prune all {@linkplain StackTraceElement stack trace elements} up one
103+
* of the supplied {@code classNames} are pruned. All subsequent elements
104+
* in the stack trace will be retained.
105+
*
106+
* <p>If the {@code classNames} do not match any of the stacktrace elements
107+
* then the {@code org.junit}, {@code jdk.internal.reflect}, and
108+
* {@code sun.reflect} packages are pruned.
105109
*
106110
* <p>Additionally, all elements prior to and including the first JUnit Platform
107111
* Launcher call will be removed.
@@ -128,6 +132,9 @@ public static void pruneStackTrace(Throwable throwable, List<String> classNames)
128132
String className = element.getClassName();
129133

130134
if (classNames.contains(className)) {
135+
// We found the test
136+
// everything before that is not informative.
137+
prunedStackTrace.clear();
131138
// Include all elements called by the test
132139
prunedStackTrace.addAll(stackTrace.subList(i, stackTrace.size()));
133140
break;

junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StackTracePruningEngineExecutionListener.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import java.util.List;
1414
import java.util.Objects;
1515
import java.util.Optional;
16+
import java.util.stream.Stream;
1617

1718
import org.junit.platform.commons.util.ExceptionUtils;
1819
import org.junit.platform.engine.EngineExecutionListener;
@@ -46,8 +47,9 @@ public void executionFinished(TestDescriptor testDescriptor, TestExecutionResult
4647
}
4748

4849
private static List<String> getTestClassNames(TestDescriptor testDescriptor) {
49-
return testDescriptor.getAncestors() //
50-
.stream() //
50+
Stream<? extends TestDescriptor> self = Stream.of(testDescriptor);
51+
Stream<? extends TestDescriptor> ancestors = testDescriptor.getAncestors().stream();
52+
return Stream.concat(self, ancestors) //
5153
.map(TestDescriptor::getSource) //
5254
.flatMap(Optional::stream) //
5355
.map(source -> {

platform-tests/src/test/java/org/junit/platform/StackTracePruningTests.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ void shouldAlwaysKeepJupiterAssumptionStackTraceElement() {
115115
}
116116

117117
@Test
118-
void shouldKeepEverythingAfterTestCall() {
118+
void shouldKeepExactlyEverythingAfterTestCall() {
119119
EngineExecutionResults results = EngineTestKit.engine("junit-jupiter") //
120120
.configurationParameter("junit.platform.stacktrace.pruning.enabled", "true") //
121121
.selectors(selectMethod(FailingTestTestCase.class, "failingAssertion")) //
@@ -128,15 +128,14 @@ void shouldKeepEverythingAfterTestCall() {
128128
\\Qorg.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:\\E.+
129129
\\Qorg.junit.jupiter.api.Assertions.fail(Assertions.java:\\E.+
130130
\\Qorg.junit.platform.StackTracePruningTests$FailingTestTestCase.failingAssertion(StackTracePruningTests.java:\\E.+
131-
>>>>
132131
""");
133132
}
134133

135134
@ParameterizedTest
136135
@ValueSource(strings = { "org.junit.platform.StackTracePruningTests$FailingBeforeEachTestCase",
137136
"org.junit.platform.StackTracePruningTests$FailingBeforeEachTestCase$NestedTestCase",
138137
"org.junit.platform.StackTracePruningTests$FailingBeforeEachTestCase$NestedTestCase$NestedNestedTestCase" })
139-
void shouldKeepEverythingAfterLifecycleMethodCall(Class<?> methodClass) {
138+
void shouldKeepExactlyEverythingAfterLifecycleMethodCall(Class<?> methodClass) {
140139
EngineExecutionResults results = EngineTestKit.engine("junit-jupiter") //
141140
.configurationParameter("junit.platform.stacktrace.pruning.enabled", "true") //
142141
.selectors(selectMethod(methodClass, "test")) //
@@ -149,7 +148,6 @@ void shouldKeepEverythingAfterLifecycleMethodCall(Class<?> methodClass) {
149148
\\Qorg.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:\\E.+
150149
\\Qorg.junit.jupiter.api.Assertions.fail(Assertions.java:\\E.+
151150
\\Qorg.junit.platform.StackTracePruningTests$FailingBeforeEachTestCase.setUp(StackTracePruningTests.java:\\E.+
152-
>>>>
153151
""");
154152
}
155153

0 commit comments

Comments
 (0)