Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document that a TestExecutionListener cannot fail the TestPlan #3591

Closed
Tracked by #3838
renyiwei-xinyi opened this issue Dec 5, 2023 · 3 comments
Closed
Tracked by #3838

Comments

@renyiwei-xinyi
Copy link

renyiwei-xinyi commented Dec 5, 2023

  <junit-jupiter.version>5.10.1</junit-jupiter.version>
  <junit-platform.version>1.10.1</junit-platform.version>
  public static void runSuit(TestContext context, Class<?> clazz){

        try (LauncherSession session = LauncherFactory.openSession()) {

            Launcher launcher = session.getLauncher();

            DiscoveryStart discoveryStart = new DiscoveryStart(clazz, context.getSteps().toArray(new String[0]));

            LauncherDiscoveryRequest request = discoveryStart.request();
            TestPlan testPlan = launcher.discover(request);

            ExecutionActionListenerPlus executionActionListenerPlus = new ExecutionActionListenerPlus();
            launcher.registerTestExecutionListeners(executionActionListenerPlus);

            LauncherDiscoveryListener launcherDiscoveryListener = LauncherDiscoveryListeners.abortOnFailure();
            launcher.registerLauncherDiscoveryListeners(launcherDiscoveryListener);

            SummaryGeneratingListener summaryGeneratingListener = new SummaryGeneratingListener();
            launcher.execute(request, summaryGeneratingListener);
        }
     }
  public class ExecutionActionListenerPlus implements TestExecutionListener {
    @Override
    public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) {
        switch (testExecutionResult.getStatus()) {
            case SUCCESSFUL:
                break;
            case ABORTED:
                break;
            case FAILED:
                testExecutionResult.getThrowable().ifPresent((throwable) -> {
                    try {
                        throw throwable.getCause();
                    } catch (Throwable e) {
                        throw new TestException(e.getMessage());
                    }
                });
                break;
            default:
                break;
        }
    }
  }

I execute two test methods in a class, and expect the first test method to terminate execution if it encounters an exception, while the second test method will no longer execute; Actually, the second test method was still executed.

I think this breaks the agreement on the testing lifecycle.

My test component, some tests in a class have dependencies.I don't know how to solve this problem.

I think this is a bug because execution is uncontrollable and it wastes time and resources when executing large batches of cases

@sbrannen sbrannen changed the title [org.junit.platform.launcher] Unable to capture exceptions and interrupt cases TestExecutionListener cannot fail the TestPlan Dec 5, 2023
@sbrannen
Copy link
Member

sbrannen commented Dec 5, 2023

This is by design.

A TestExecutionListener cannot fail the TestPlan, and any exception thrown by a TestExecutionListener is caught and logged at WARN level.

See the following code for details.

private static <T extends TestExecutionListener> void notifyEach(List<T> listeners, IterationOrder iterationOrder,
Consumer<T> consumer, Supplier<String> description) {
iterationOrder.forEach(listeners, listener -> {
try {
consumer.accept(listener);
}
catch (Throwable throwable) {
UnrecoverableExceptions.rethrowIfUnrecoverable(throwable);
logger.warn(throwable, () -> String.format("TestExecutionListener [%s] threw exception for method: %s",
listener.getClass().getName(), description.get()));
}
});
}

This behavior is similar to support for the TestWatcher API in JUnit Jupiter.

However, I can understand that this might not be intuitive.

I am therefore repurposing this ticket to improve the documentation regarding these semantics for the TestExecutionListener API.

@sbrannen sbrannen changed the title TestExecutionListener cannot fail the TestPlan Document that a TestExecutionListener cannot fail the TestPlan Dec 5, 2023
@sbrannen sbrannen added this to the 5.11 M1 milestone Dec 5, 2023
@renyiwei-xinyi
Copy link
Author

Oh~ Thanks. This is consistent with my conjecture after debugging until late at night 🤣
What should I do if I want to customize this design?
I just want to stop the subsequent execution that I think is useless when the case is abnormal 😭.

@sormuras
Copy link
Member

sormuras commented Dec 5, 2023

@sbrannen sbrannen self-assigned this Dec 5, 2023
@marcphilipp marcphilipp assigned marcphilipp and unassigned sbrannen Feb 2, 2024
@marcphilipp marcphilipp modified the milestones: 5.11 M1, 5.10.3 Jun 17, 2024
marcphilipp added a commit that referenced this issue Jun 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants