Skip to content

Commit dfe4ade

Browse files
committed
Prune stack traces up to test method
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 fc94772 commit dfe4ade

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)