diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC1.adoc index 8381557f7970..1b3a5f0a8fd7 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC1.adoc @@ -26,8 +26,7 @@ repository on GitHub. [[release-notes-6.0.0-RC1-junit-platform-new-features-and-improvements]] ==== New Features and Improvements -* ❓ - +* Prune stack traces up to test or lifecycle method [[release-notes-6.0.0-RC1-junit-jupiter]] === JUnit Jupiter diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ExceptionUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ExceptionUtils.java index cb20454d6fc1..350f443b3ad1 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ExceptionUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ExceptionUtils.java @@ -97,11 +97,15 @@ public static String readStackTrace(Throwable throwable) { } /** - * Prune the stack trace of the supplied {@link Throwable} by removing - * {@linkplain StackTraceElement stack trace elements} from the {@code org.junit}, - * {@code jdk.internal.reflect}, and {@code sun.reflect} packages. If a - * {@code StackTraceElement} matching one of the supplied {@code classNames} - * is encountered, all subsequent elements in the stack trace will be retained. + * Prune the stack trace of the supplied {@link Throwable}. + * + *

Prune all {@linkplain StackTraceElement stack trace elements} up one + * of the supplied {@code classNames} are pruned. All subsequent elements + * in the stack trace will be retained. + * + *

If the {@code classNames} do not match any of the stacktrace elements + * then the {@code org.junit}, {@code jdk.internal.reflect}, and + * {@code sun.reflect} packages are pruned. * *

Additionally, all elements prior to and including the first JUnit Platform * Launcher call will be removed. @@ -128,6 +132,9 @@ public static void pruneStackTrace(Throwable throwable, List classNames) String className = element.getClassName(); if (classNames.contains(className)) { + // We found the test + // everything before that is not informative. + prunedStackTrace.clear(); // Include all elements called by the test prunedStackTrace.addAll(stackTrace.subList(i, stackTrace.size())); break; diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StackTracePruningEngineExecutionListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StackTracePruningEngineExecutionListener.java index 835a272e0af9..61354ac809b9 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StackTracePruningEngineExecutionListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StackTracePruningEngineExecutionListener.java @@ -13,6 +13,7 @@ import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.stream.Stream; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.engine.EngineExecutionListener; @@ -46,8 +47,9 @@ public void executionFinished(TestDescriptor testDescriptor, TestExecutionResult } private static List getTestClassNames(TestDescriptor testDescriptor) { - return testDescriptor.getAncestors() // - .stream() // + Stream self = Stream.of(testDescriptor); + Stream ancestors = testDescriptor.getAncestors().stream(); + return Stream.concat(self, ancestors) // .map(TestDescriptor::getSource) // .flatMap(Optional::stream) // .map(source -> { diff --git a/platform-tests/src/test/java/org/junit/platform/StackTracePruningTests.java b/platform-tests/src/test/java/org/junit/platform/StackTracePruningTests.java index 5f7b97f88728..83e56373d509 100644 --- a/platform-tests/src/test/java/org/junit/platform/StackTracePruningTests.java +++ b/platform-tests/src/test/java/org/junit/platform/StackTracePruningTests.java @@ -115,7 +115,7 @@ void shouldAlwaysKeepJupiterAssumptionStackTraceElement() { } @Test - void shouldKeepEverythingAfterTestCall() { + void shouldKeepExactlyEverythingAfterTestCall() { EngineExecutionResults results = EngineTestKit.engine("junit-jupiter") // .configurationParameter("junit.platform.stacktrace.pruning.enabled", "true") // .selectors(selectMethod(FailingTestTestCase.class, "failingAssertion")) // @@ -128,7 +128,6 @@ void shouldKeepEverythingAfterTestCall() { \\Qorg.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:\\E.+ \\Qorg.junit.jupiter.api.Assertions.fail(Assertions.java:\\E.+ \\Qorg.junit.platform.StackTracePruningTests$FailingTestTestCase.failingAssertion(StackTracePruningTests.java:\\E.+ - >>>> """); } @@ -136,7 +135,7 @@ void shouldKeepEverythingAfterTestCall() { @ValueSource(strings = { "org.junit.platform.StackTracePruningTests$FailingBeforeEachTestCase", "org.junit.platform.StackTracePruningTests$FailingBeforeEachTestCase$NestedTestCase", "org.junit.platform.StackTracePruningTests$FailingBeforeEachTestCase$NestedTestCase$NestedNestedTestCase" }) - void shouldKeepEverythingAfterLifecycleMethodCall(Class methodClass) { + void shouldKeepExactlyEverythingAfterLifecycleMethodCall(Class methodClass) { EngineExecutionResults results = EngineTestKit.engine("junit-jupiter") // .configurationParameter("junit.platform.stacktrace.pruning.enabled", "true") // .selectors(selectMethod(methodClass, "test")) // @@ -149,7 +148,6 @@ void shouldKeepEverythingAfterLifecycleMethodCall(Class methodClass) { \\Qorg.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:\\E.+ \\Qorg.junit.jupiter.api.Assertions.fail(Assertions.java:\\E.+ \\Qorg.junit.platform.StackTracePruningTests$FailingBeforeEachTestCase.setUp(StackTracePruningTests.java:\\E.+ - >>>> """); }