/** * Hook for post-processing a test class <em>after</em> execution of all tests within the class. * Should be called after any framework-specific <em>after class methods</em> (e.g., methods * annotated with JUnit 4's {@link org.junit.AfterClass @AfterClass}). * * <p>Each registered {@link TestExecutionListener} will be given a chance to perform its * post-processing. If a listener throws an exception, the remaining registered listeners will * still be called. After all listeners have executed, the first caught exception will be rethrown * with any subsequent exceptions {@linkplain Throwable#addSuppressed suppressed} in the first * exception. * * <p>Note that registered listeners will be executed in the opposite * * @throws Exception if a registered TestExecutionListener throws an exception * @since 3.0 * @see #getTestExecutionListeners() * @see Throwable#addSuppressed(Throwable) */ public void afterTestClass() throws Exception { Class<?> testClass = getTestContext().getTestClass(); if (logger.isTraceEnabled()) { logger.trace("afterTestClass(): class [" + testClass.getName() + "]"); } getTestContext().updateState(null, null, null); Throwable afterTestClassException = null; // Traverse the TestExecutionListeners in reverse order to ensure proper // "wrapper"-style execution of listeners. for (TestExecutionListener testExecutionListener : getReversedTestExecutionListeners()) { try { testExecutionListener.afterTestClass(getTestContext()); } catch (Throwable ex) { logException(ex, "afterTestClass", testExecutionListener, testClass); if (afterTestClassException == null) { afterTestClassException = ex; } else { afterTestClassException.addSuppressed(ex); } } } this.testContextHolder.remove(); if (afterTestClassException != null) { ReflectionUtils.rethrowException(afterTestClassException); } }
/** * Hook for pre-processing a test <em>immediately before</em> execution of the {@linkplain * java.lang.reflect.Method test method} in the supplied {@linkplain TestContext test context} * — for example, for timing or logging purposes. * * <p>This method <strong>must</strong> be called after framework-specific <em>before</em> * lifecycle callbacks (e.g., methods annotated with JUnit 4's {@link org.junit.Before @Before}). * * <p>The managed {@link TestContext} will be updated with the supplied {@code testInstance} and * {@code testMethod}. * * <p>An attempt will be made to give each registered {@link TestExecutionListener} a chance to * perform its pre-processing. If a listener throws an exception, however, the remaining * registered listeners will <strong>not</strong> be called. * * @param testInstance the current test instance (never {@code null}) * @param testMethod the test method which is about to be executed on the test instance * @throws Exception if a registered TestExecutionListener throws an exception * @since 5.0 * @see #beforeTestMethod * @see #afterTestMethod * @see #beforeTestExecution * @see #afterTestExecution * @see #getTestExecutionListeners() */ public void beforeTestExecution(Object testInstance, Method testMethod) throws Exception { String callbackName = "beforeTestExecution"; prepareForBeforeCallback(callbackName, testInstance, testMethod); for (TestExecutionListener testExecutionListener : getTestExecutionListeners()) { try { testExecutionListener.beforeTestExecution(getTestContext()); } catch (Throwable ex) { handleBeforeException(ex, callbackName, testExecutionListener, testInstance, testMethod); } } }
private void execute(RootTestDescriptor root) { TestPlan testPlan = TestPlan.from(root); TestExecutionListener testExecutionListener = listenerRegistry.getCompositeTestExecutionListener(); testExecutionListener.testPlanExecutionStarted(testPlan); ExecutionListenerAdapter engineExecutionListener = new ExecutionListenerAdapter(testPlan, testExecutionListener); for (TestEngine testEngine : root.getTestEngines()) { TestDescriptor testDescriptor = root.getTestDescriptorFor(testEngine); testEngine.execute(new ExecutionRequest(testDescriptor, engineExecutionListener)); } testExecutionListener.testPlanExecutionFinished(testPlan); }
/** * Hook for pre-processing a test class <em>before</em> execution of any tests within the class. * Should be called prior to any framework-specific <em>before class methods</em> (e.g., methods * annotated with JUnit 4's {@link org.junit.BeforeClass @BeforeClass}). * * <p>An attempt will be made to give each registered {@link TestExecutionListener} a chance to * pre-process the test class execution. If a listener throws an exception, however, the remaining * registered listeners will <strong>not</strong> be called. * * @throws Exception if a registered TestExecutionListener throws an exception * @since 3.0 * @see #getTestExecutionListeners() */ public void beforeTestClass() throws Exception { Class<?> testClass = getTestContext().getTestClass(); if (logger.isTraceEnabled()) { logger.trace("beforeTestClass(): class [" + testClass.getName() + "]"); } getTestContext().updateState(null, null, null); for (TestExecutionListener testExecutionListener : getTestExecutionListeners()) { try { testExecutionListener.beforeTestClass(getTestContext()); } catch (Throwable ex) { logException(ex, "beforeTestClass", testExecutionListener, testClass); ReflectionUtils.rethrowException(ex); } } }
/** * Hook for post-processing a test <em>after</em> execution of <em>after</em> lifecycle callbacks * of the underlying test framework — for example, tearing down test fixtures, ending a * transaction, etc. * * <p>This method <strong>must</strong> be called immediately after framework-specific * <em>after</em> lifecycle callbacks (e.g., methods annotated with JUnit 4's {@link * org.junit.After @After}). For historical reasons, this method is named {@code afterTestMethod}. * Since the introduction of {@link #afterTestExecution}, a more suitable name for this method * might be something like {@code afterTestTearDown} or {@code afterEach}; however, it is * unfortunately impossible to rename this method due to backward compatibility concerns. * * <p>The managed {@link TestContext} will be updated with the supplied {@code testInstance}, * {@code testMethod}, and {@code exception}. * * <p>Each registered {@link TestExecutionListener} will be given a chance to perform its * post-processing. If a listener throws an exception, the remaining registered listeners will * still be called. After all listeners have executed, the first caught exception will be rethrown * with any subsequent exceptions {@linkplain Throwable#addSuppressed suppressed} in the first * exception. * * <p>Note that registered listeners will be executed in the opposite * * @param testInstance the current test instance (never {@code null}) * @param testMethod the test method which has just been executed on the test instance * @param exception the exception that was thrown during execution of the test method or by a * TestExecutionListener, or {@code null} if none was thrown * @throws Exception if a registered TestExecutionListener throws an exception * @see #beforeTestMethod * @see #beforeTestExecution * @see #afterTestExecution * @see #getTestExecutionListeners() * @see Throwable#addSuppressed(Throwable) */ public void afterTestMethod(Object testInstance, Method testMethod, Throwable exception) throws Exception { String callbackName = "afterTestMethod"; prepareForAfterCallback(callbackName, testInstance, testMethod, exception); Throwable afterTestMethodException = null; // Traverse the TestExecutionListeners in reverse order to ensure proper // "wrapper"-style execution of listeners. for (TestExecutionListener testExecutionListener : getReversedTestExecutionListeners()) { try { testExecutionListener.afterTestMethod(getTestContext()); } catch (Throwable ex) { logException(ex, callbackName, testExecutionListener, testInstance, testMethod); if (afterTestMethodException == null) { afterTestMethodException = ex; } else { afterTestMethodException.addSuppressed(ex); } } } if (afterTestMethodException != null) { ReflectionUtils.rethrowException(afterTestMethodException); } }
/** * Hook for preparing a test instance prior to execution of any individual test methods, for * example for injecting dependencies, etc. Should be called immediately after instantiation of * the test instance. * * <p>The managed {@link TestContext} will be updated with the supplied {@code testInstance}. * * <p>An attempt will be made to give each registered {@link TestExecutionListener} a chance to * prepare the test instance. If a listener throws an exception, however, the remaining registered * listeners will <strong>not</strong> be called. * * @param testInstance the test instance to prepare (never {@code null}) * @throws Exception if a registered TestExecutionListener throws an exception * @see #getTestExecutionListeners() */ public void prepareTestInstance(Object testInstance) throws Exception { Assert.notNull(testInstance, "Test instance must not be null"); if (logger.isTraceEnabled()) { logger.trace("prepareTestInstance(): instance [" + testInstance + "]"); } getTestContext().updateState(testInstance, null, null); for (TestExecutionListener testExecutionListener : getTestExecutionListeners()) { try { testExecutionListener.prepareTestInstance(getTestContext()); } catch (Throwable ex) { if (logger.isErrorEnabled()) { logger.error( "Caught exception while allowing TestExecutionListener [" + testExecutionListener + "] to prepare test instance [" + testInstance + "]", ex); } ReflectionUtils.rethrowException(ex); } } }
@Override public void executionFinished( TestDescriptor testDescriptor, TestExecutionResult testExecutionResult) { testExecutionListener.executionFinished( getTestIdentifier(testDescriptor), testExecutionResult); }
@Override public void executionSkipped(TestDescriptor testDescriptor, String reason) { testExecutionListener.executionSkipped(getTestIdentifier(testDescriptor), reason); }
@Override public void executionStarted(TestDescriptor testDescriptor) { testExecutionListener.executionStarted(getTestIdentifier(testDescriptor)); }
@Override public void dynamicTestRegistered(TestDescriptor testDescriptor) { TestIdentifier testIdentifier = TestIdentifier.from(testDescriptor); testPlan.add(testIdentifier); testExecutionListener.dynamicTestRegistered(testIdentifier); }