From a04c129c227bbefc54c6f7b89d445aa264d6b97b Mon Sep 17 00:00:00 2001 From: Andy Huynh Date: Thu, 6 Feb 2025 12:35:02 +0100 Subject: [PATCH] feat(#1218): add further methods to TestListener Co-authored-by: Thorsten Schlathoelter --- .../citrusframework/report/TestListener.java | 93 ++++++++++-- .../citrusframework/report/TestListeners.java | 60 +++++++- .../citrusframework/report/TestReporters.java | 10 +- .../report/TestReportersTest.java | 8 +- .../org/citrusframework/DefaultTestCase.java | 93 ++++++++---- .../report/AbstractTestListener.java | 2 +- .../citrusframework/report/HtmlReporter.java | 16 +- .../report/LoggingReporter.java | 2 +- .../report/MessageTracingTestListener.java | 10 +- .../citrusframework/DefaultTestCaseTest.java | 138 +++++++++++++++++- .../MessageTracingTestListenerTest.java | 4 +- .../http/CitrusRestDocConfigurer.java | 2 +- .../soap/CitrusRestDocSoapConfigurer.java | 2 +- 13 files changed, 357 insertions(+), 83 deletions(-) diff --git a/core/citrus-api/src/main/java/org/citrusframework/report/TestListener.java b/core/citrus-api/src/main/java/org/citrusframework/report/TestListener.java index 7a688128db..baaa37e114 100644 --- a/core/citrus-api/src/main/java/org/citrusframework/report/TestListener.java +++ b/core/citrus-api/src/main/java/org/citrusframework/report/TestListener.java @@ -20,36 +20,105 @@ /** * Test listener interface. Listeners invoked on test start, finish, failure, skip, success. - * */ public interface TestListener { /** - * Invoked when test gets started - * @param test + * Invoked when test when a test starts execution */ void onTestStart(TestCase test); /** - * Invoked when test gets finished - * @param test + * @deprecated use on {@link #onTestExecutionEnd(TestCase)} + */ + @Deprecated(forRemoval = true) + default void onTestFinish(TestCase test) { + // Do nothing + } + + /** + * Invoked when test execution has ended (after final actions execution and + * before {@link org.citrusframework.container.AfterTest} execution) + * + * @see #onTestEnd(TestCase) + */ + default void onTestExecutionStart(TestCase test) { + onTestFinish(test); + } + + + /** + * Invoked when test execution has ended (after final actions execution and + * before {@link org.citrusframework.container.AfterTest} execution) + * + * @see #onTestEnd(TestCase) */ - void onTestFinish(TestCase test); + default void onTestExecutionEnd(TestCase test) { + onTestFinish(test); + } /** - * Invoked when test finished with success - * @param test + * Invoked at the very end of test execution + * + * @see #onTestFinish(TestCase) + */ + default void onTestEnd(TestCase test) { + // Default implementation does nothing + } + + /** + * Invoked when a test finishes successfully */ void onTestSuccess(TestCase test); /** - * Invoked when test finished with failure - * @param test + * Invoked when a test finishes with failure */ void onTestFailure(TestCase test, Throwable cause); /** - * Invoked when test is skipped - * @param test + * Invoked when a test is skipped */ void onTestSkipped(TestCase test); + + /** + * Invoked when final actions start, only if any exist + */ + default void onFinalActionsStart(TestCase test) { + // Default implementation does nothing + } + + /** + * Invoked after final actions have completely finished, only if any exist + */ + default void onFinalActionsEnd(TestCase test) { + // Default implementation does nothing + } + + /** + * Invoked when {@link org.citrusframework.container.BeforeTest} execution starts, only if any exist + */ + default void onBeforeTestStart(TestCase test) { + // Default implementation does nothing + } + + /** + * Invoked when {@link org.citrusframework.container.BeforeTest} execution ends, only if any exist + */ + default void onBeforeTestEnd(TestCase test) { + // Default implementation does nothing + } + + /** + * Invoked when {@link org.citrusframework.container.AfterTest} execution starts, only if any exist + */ + default void onAfterTestStart(TestCase test) { + // Default implementation does nothing + } + + /** + * Invoked when {@link org.citrusframework.container.AfterTest} execution ends, only if any exist + */ + default void onAfterTestEnd(TestCase test) { + // Default implementation does nothing + } } diff --git a/core/citrus-api/src/main/java/org/citrusframework/report/TestListeners.java b/core/citrus-api/src/main/java/org/citrusframework/report/TestListeners.java index 2f9bcbf51e..d1cd1df3be 100644 --- a/core/citrus-api/src/main/java/org/citrusframework/report/TestListeners.java +++ b/core/citrus-api/src/main/java/org/citrusframework/report/TestListeners.java @@ -37,12 +37,29 @@ public void onTestFailure(TestCase test, Throwable cause) { } } + /** + * @deprecated use on {@link #onTestExecutionEnd(TestCase)} + */ + @Deprecated(forRemoval = true) public void onTestFinish(TestCase test) { for (TestListener listener : testListeners) { listener.onTestFinish(test); } } + public void onTestExecutionStart(TestCase test) { + for (TestListener listener : testListeners) { + listener.onTestExecutionStart(test); + } + + } + + public void onTestExecutionEnd(TestCase test) { + for (TestListener listener : testListeners) { + listener.onTestExecutionEnd(test); + } + } + public void onTestSkipped(TestCase test) { for (TestListener listener : testListeners) { listener.onTestSkipped(test); @@ -55,6 +72,48 @@ public void onTestStart(TestCase test) { } } + public void onTestFinalization(TestCase test) { + for (TestListener listener : testListeners) { + listener.onTestEnd(test); + } + } + + public void onFinalActionsStart(TestCase test) { + for (TestListener listener : testListeners) { + listener.onFinalActionsStart(test); + } + } + + public void onFinalActionsEnd(TestCase test) { + for (TestListener listener : testListeners) { + listener.onFinalActionsEnd(test); + } + } + + public void onBeforeTestEnd(TestCase test) { + for (TestListener listener : testListeners) { + listener.onBeforeTestEnd(test); + } + } + + public void onAfterTestEnd(TestCase test) { + for (TestListener listener : testListeners) { + listener.onAfterTestEnd(test); + } + } + + public void onBeforeTestStart(TestCase test) { + for (TestListener listener : testListeners) { + listener.onBeforeTestStart(test); + } + } + + public void onAfterTestStart(TestCase test) { + for (TestListener listener : testListeners) { + listener.onAfterTestStart(test); + } + } + public void onTestSuccess(TestCase test) { for (TestListener listener : testListeners) { listener.onTestSuccess(test); @@ -70,7 +129,6 @@ public void addTestListener(TestListener listener) { /** * Obtains the testListeners. - * @return */ public List getTestListeners() { return testListeners; diff --git a/core/citrus-api/src/main/java/org/citrusframework/report/TestReporters.java b/core/citrus-api/src/main/java/org/citrusframework/report/TestReporters.java index d1c5c45d91..8b69b1ab94 100644 --- a/core/citrus-api/src/main/java/org/citrusframework/report/TestReporters.java +++ b/core/citrus-api/src/main/java/org/citrusframework/report/TestReporters.java @@ -80,7 +80,7 @@ public void onTestStart(TestCase test) { } @Override - public void onTestFinish(TestCase test) { + public void onTestExecutionEnd(TestCase test) { if (nonNull(test.getTestResult())) { testResults.addResult(test.getTestResult()); } @@ -108,8 +108,6 @@ public void addTestReporter(TestReporter testReporter) { /** * Obtains the testReporters. - * - * @return */ public List getTestReporters() { return unmodifiableList(testReporters); @@ -117,8 +115,6 @@ public List getTestReporters() { /** * Obtains the autoClear. - * - * @return */ public boolean isAutoClear() { return autoClear; @@ -126,8 +122,6 @@ public boolean isAutoClear() { /** * Specifies the autoClear. - * - * @param autoClear */ public void setAutoClear(boolean autoClear) { this.autoClear = autoClear; @@ -135,8 +129,6 @@ public void setAutoClear(boolean autoClear) { /** * Gets the testResults. - * - * @return */ public TestResults getTestResults() { return testResults; diff --git a/core/citrus-api/src/test/java/org/citrusframework/report/TestReportersTest.java b/core/citrus-api/src/test/java/org/citrusframework/report/TestReportersTest.java index 0a94b023b1..369cf4671b 100644 --- a/core/citrus-api/src/test/java/org/citrusframework/report/TestReportersTest.java +++ b/core/citrus-api/src/test/java/org/citrusframework/report/TestReportersTest.java @@ -77,11 +77,11 @@ private void verifyGenerateReport(Runnable invocation) { } @Test - public void onTestFinishAddsTestResultToList() { + public void onTestExecutionEndAddsTestResultToList() { var testResultMock = mock(TestResult.class); doReturn(testResultMock).when(testCaseMock).getTestResult(); - fixture.onTestFinish(testCaseMock); + fixture.onTestExecutionEnd(testCaseMock); var testResults = fixture.getTestResults().asList(); assertEquals(1, testResults.size()); @@ -89,10 +89,10 @@ public void onTestFinishAddsTestResultToList() { } @Test - public void onTestFinishIgnoresNullTestResult() { + public void onTestExecutionEndIgnoresNullTestResult() { doReturn(null).when(testCaseMock).getTestResult(); - fixture.onTestFinish(testCaseMock); + fixture.onTestExecutionEnd(testCaseMock); var testResults = fixture.getTestResults().asList(); assertEquals(0, testResults.size()); diff --git a/core/citrus-base/src/main/java/org/citrusframework/DefaultTestCase.java b/core/citrus-base/src/main/java/org/citrusframework/DefaultTestCase.java index d25b0fc2a5..6f698f49c7 100644 --- a/core/citrus-base/src/main/java/org/citrusframework/DefaultTestCase.java +++ b/core/citrus-base/src/main/java/org/citrusframework/DefaultTestCase.java @@ -116,9 +116,7 @@ public void doExecute(final TestContext context) { try { start(context); - for (final TestActionBuilder actionBuilder : actions) { - executeAction(actionBuilder.build(), context); - } + executeTest(context); testResult = getTestResultInstanceProvider(context).createSuccess(this); } catch (final TestCaseFailedException e) { @@ -134,10 +132,17 @@ public void doExecute(final TestContext context) { } } + private void executeTest(TestContext context) { + context.getTestListeners().onTestExecutionStart(this); + for (final TestActionBuilder actionBuilder : actions) { + executeAction(actionBuilder.build(), context); + } + } + @Override public void start(final TestContext context) { context.getTestListeners().onTestStart(this); - + try { logger.debug("Initializing test case"); @@ -157,6 +162,19 @@ public void start(final TestContext context) { public void beforeTest(final TestContext context) { restartTimer(); + if (context.getBeforeTest().isEmpty()) { + return; + } + + try { + context.getTestListeners().onBeforeTestStart(this); + doExecuteSequenceBefore(context); + } finally { + context.getTestListeners().onBeforeTestEnd(this); + } + } + + private void doExecuteSequenceBefore(TestContext context) { for (final BeforeTest sequenceBeforeTest : context.getBeforeTest()) { try { if (sequenceBeforeTest.shouldExecute(getName(), packageName, groups)) { @@ -170,6 +188,19 @@ public void beforeTest(final TestContext context) { @Override public void afterTest(final TestContext context) { + if (context.getAfterTest().isEmpty()) { + return; + } + + try { + context.getTestListeners().onAfterTestStart(this); + } finally { + doExecuteSequenceAfter(context); + context.getTestListeners().onAfterTestEnd(this); + } + } + + private void doExecuteSequenceAfter(TestContext context) { for (final AfterTest sequenceAfterTest : context.getAfterTest()) { try { if (sequenceAfterTest.shouldExecute(getName(), packageName, groups)) { @@ -235,7 +266,6 @@ public void finish(final TestContext context) { waitForCompletion(this, context, timeout); } - context.getTestListeners().onTestFinish(this); executeFinalActions(context); if (contextException != null) { @@ -250,6 +280,13 @@ public void finish(final TestContext context) { testResult = getTestResultInstanceProvider(context).createFailed(this, e); throw new TestCaseFailedException(e); } finally { + context.getTestListeners().onTestExecutionEnd(this); + doFinishTest(context); + } + } + + private void doFinishTest(TestContext context) { + try { if (testResult != null) { if (testResult.isSuccess()) { context.getTestListeners().onTestSuccess(this); @@ -259,8 +296,9 @@ public void finish(final TestContext context) { } afterTest(context); - completeTestResultWithDuration(); + } finally { + context.getTestListeners().onTestFinalization(this); } } @@ -289,7 +327,25 @@ private void gracefullyStopTimer() { * Run final test actions. */ private void executeFinalActions(TestContext context) { + if (!finalActions.isEmpty() || !context.getFinalActions().isEmpty()) { + try { + context.getTestListeners().onFinalActionsStart(this); + doExecuteFinalActions(context); + } finally { + context.getTestListeners().onFinalActionsEnd(this); + } + } + + if (testResult.isSuccess() && context.hasExceptions()) { + CitrusRuntimeException contextException = context.getExceptions().remove(0); + testResult = getTestResultInstanceProvider(context).createFailed(this, contextException); + throw new TestCaseFailedException(contextException); + } + } + + private void doExecuteFinalActions(TestContext context) { if (!finalActions.isEmpty()) { + logger.debug("Entering finally block in test case"); /* walk through the finally-chain and execute the actions in there */ @@ -307,6 +363,8 @@ private void executeFinalActions(TestContext context) { /* test context may also have some actions to run finally */ for (final TestActionBuilder actionBuilder : context.getFinalActions()) { + context.getTestListeners().onFinalActionsStart(this); + TestAction action = actionBuilder.build(); if (!action.isDisabled(context)) { context.getTestActionListeners().onTestActionStart(this, action); @@ -316,19 +374,10 @@ private void executeFinalActions(TestContext context) { context.getTestActionListeners().onTestActionSkipped(this, action); } } - - if (testResult.isSuccess() && context.hasExceptions()) { - CitrusRuntimeException contextException = context.getExceptions().remove(0); - testResult = getTestResultInstanceProvider(context).createFailed(this, contextException); - throw new TestCaseFailedException(contextException); - } } /** * Print variables in given test context. - * - * @param scope - * @param context */ private void debugVariables(String scope, TestContext context) { /* Debug print global variables */ @@ -342,9 +391,6 @@ private void debugVariables(String scope, TestContext context) { /** * Sets test parameters as test variables. - * - * @param parameters - * @param context */ private void initializeTestParameters(Map parameters, TestContext context) { // add default variables for test @@ -359,9 +405,6 @@ private void initializeTestParameters(Map parameters, TestContex /** * Initialize the test variables in the given test context. - * - * @param variableDefinitions - * @param context */ private void initializeTestVariables(Map variableDefinitions, TestContext context) { /* build up the global test variables in TestContext by @@ -381,8 +424,6 @@ private void initializeTestVariables(Map variableDefinitions, Te /** * Setter for variables. - * - * @param variableDefinitions */ public void setVariableDefinitions(final Map variableDefinitions) { this.variableDefinitions = variableDefinitions; @@ -395,8 +436,6 @@ public Map getVariableDefinitions() { /** * Setter for finally chain. - * - * @param finalActions */ public void setFinalActions(final List finalActions) { this.finalActions = finalActions.stream().map(action -> (TestActionBuilder) () -> action).collect(Collectors.toList()); @@ -543,8 +582,6 @@ public void setGroups(final String[] groups) { /** * Sets the timeout. - * - * @param timeout */ public void setTimeout(final long timeout) { this.timeout = timeout; @@ -552,8 +589,6 @@ public void setTimeout(final long timeout) { /** * Gets the timeout. - * - * @return */ public long getTimeout() { return timeout; diff --git a/core/citrus-base/src/main/java/org/citrusframework/report/AbstractTestListener.java b/core/citrus-base/src/main/java/org/citrusframework/report/AbstractTestListener.java index c3e4016407..171c863426 100644 --- a/core/citrus-base/src/main/java/org/citrusframework/report/AbstractTestListener.java +++ b/core/citrus-base/src/main/java/org/citrusframework/report/AbstractTestListener.java @@ -29,7 +29,7 @@ public abstract class AbstractTestListener implements TestListener { public void onTestFailure(TestCase test, Throwable cause) {} @Override - public void onTestFinish(TestCase test) {} + public void onTestExecutionEnd(TestCase test) {} @Override public void onTestSkipped(TestCase test) {} diff --git a/core/citrus-base/src/main/java/org/citrusframework/report/HtmlReporter.java b/core/citrus-base/src/main/java/org/citrusframework/report/HtmlReporter.java index e093ce1e96..50d2453d9c 100644 --- a/core/citrus-base/src/main/java/org/citrusframework/report/HtmlReporter.java +++ b/core/citrus-base/src/main/java/org/citrusframework/report/HtmlReporter.java @@ -47,7 +47,7 @@ public class HtmlReporter extends AbstractOutputFileReporter implements TestList private static final Logger logger = LoggerFactory.getLogger(HtmlReporter.class); /** Map holding additional information of test cases */ - private Map details = new HashMap<>(); + private final Map details = new HashMap<>(); /** Static resource for the HTML test report template */ private String reportTemplate = HtmlReporterSettings.getReportTemplate(); @@ -119,8 +119,6 @@ public String getReportContent(TestResults testResults) { /** * Reads citrus logo png image and converts to base64 encoded string for inline HTML image display. - * @return - * @throws IOException */ private String getLogoImageData() { ByteArrayOutputStream os = new ByteArrayOutputStream(); @@ -158,7 +156,6 @@ private String getLogoImageData() { * Gets the code section from test case XML which is responsible for the * error. * @param cause the error cause. - * @return */ private String getCodeSnippetHtml(Throwable cause) { StringBuilder codeSnippet = new StringBuilder(); @@ -229,7 +226,6 @@ private String getCodeSnippetHtml(Throwable cause) { /** * Construct HTML code snippet for stack trace information. * @param cause the causing error. - * @return */ private String getStackTraceHtml(Throwable cause) { StringBuilder stackTraceBuilder = new StringBuilder(); @@ -243,7 +239,7 @@ private String getStackTraceHtml(Throwable cause) { } return "" + - "
" + stackTraceBuilder.toString() +
+        		"
" + stackTraceBuilder +
         		"
" + getCodeSnippetHtml(cause) + "
"; } @@ -253,7 +249,7 @@ public void onTestStart(TestCase test) { } @Override - public void onTestFinish(TestCase test) { + public void onTestExecutionEnd(TestCase test) { // do nothing } @@ -292,7 +288,6 @@ public String getReportDirectory() { /** * Sets the reportFileName property. * - * @param reportFileName */ public void setReportFileName(String reportFileName) { this.reportFileName = reportFileName; @@ -301,7 +296,6 @@ public void setReportFileName(String reportFileName) { /** * Gets the reportFileName. * - * @return */ @Override public String getReportFileName() { @@ -311,7 +305,6 @@ public String getReportFileName() { /** * Sets the dateFormat property. * - * @param dateFormat */ public void setDateFormat(DateFormat dateFormat) { this.dateFormat = dateFormat; @@ -320,7 +313,6 @@ public void setDateFormat(DateFormat dateFormat) { /** * Sets the reportTemplate property. * - * @param reportTemplate */ public void setReportTemplate(String reportTemplate) { this.reportTemplate = reportTemplate; @@ -329,7 +321,6 @@ public void setReportTemplate(String reportTemplate) { /** * Sets the testDetailTemplate property. * - * @param testDetailTemplate */ public void setTestDetailTemplate(String testDetailTemplate) { this.testDetailTemplate = testDetailTemplate; @@ -337,7 +328,6 @@ public void setTestDetailTemplate(String testDetailTemplate) { /** * Sets the enabled property. - * @param enabled */ public void setEnabled(boolean enabled) { this.enabled = enabled; diff --git a/core/citrus-base/src/main/java/org/citrusframework/report/LoggingReporter.java b/core/citrus-base/src/main/java/org/citrusframework/report/LoggingReporter.java index 2091346389..ea9f75e690 100644 --- a/core/citrus-base/src/main/java/org/citrusframework/report/LoggingReporter.java +++ b/core/citrus-base/src/main/java/org/citrusframework/report/LoggingReporter.java @@ -169,7 +169,7 @@ public void onTestStart(TestCase test) { } @Override - public void onTestFinish(TestCase test) { + public void onTestExecutionEnd(TestCase test) { // do nothing } diff --git a/core/citrus-base/src/main/java/org/citrusframework/report/MessageTracingTestListener.java b/core/citrus-base/src/main/java/org/citrusframework/report/MessageTracingTestListener.java index 771973daa4..a10b96f3ab 100644 --- a/core/citrus-base/src/main/java/org/citrusframework/report/MessageTracingTestListener.java +++ b/core/citrus-base/src/main/java/org/citrusframework/report/MessageTracingTestListener.java @@ -34,10 +34,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static java.lang.System.lineSeparator; + /** * Test listener collects all messages sent and received by Citrus during test execution. Listener * writes a trace file with all message content per test case to a output directory. - * + *

* Note: This class is not thread safe! Parallel test execution leads to behaviour that messages get mixed. * Proper correlation to test case is not possible here. * @@ -77,7 +79,7 @@ public void onTestStart(TestCase test) { * {@inheritDoc} */ @Override - public void onTestFinish(TestCase test) { + public void onTestExecutionEnd(TestCase test) { if (messages.isEmpty()) { return; // do not write empty message trace file } @@ -118,7 +120,6 @@ public void onOutboundMessage(Message message, TestContext context) { /** * Creates message separator line. - * @return */ private String separator() { return "======================================================================"; @@ -126,10 +127,9 @@ private String separator() { /** * Get new line character. - * @return */ private String newLine() { - return System.getProperty("line.separator"); + return lineSeparator(); } /** diff --git a/core/citrus-base/src/test/java/org/citrusframework/DefaultTestCaseTest.java b/core/citrus-base/src/test/java/org/citrusframework/DefaultTestCaseTest.java index 1a530ddfbf..cdf67744c1 100644 --- a/core/citrus-base/src/test/java/org/citrusframework/DefaultTestCaseTest.java +++ b/core/citrus-base/src/test/java/org/citrusframework/DefaultTestCaseTest.java @@ -1,15 +1,20 @@ package org.citrusframework; +import org.citrusframework.TestCaseMetaInfo.Status; import org.citrusframework.actions.AbstractAsyncTestAction; import org.citrusframework.actions.EchoAction; import org.citrusframework.actions.SleepAction; +import org.citrusframework.container.AfterTest; import org.citrusframework.container.Async; +import org.citrusframework.container.BeforeTest; import org.citrusframework.container.SequenceAfterTest; import org.citrusframework.container.SequenceBeforeTest; import org.citrusframework.context.TestContext; import org.citrusframework.exceptions.CitrusRuntimeException; import org.citrusframework.exceptions.TestCaseFailedException; import org.citrusframework.functions.core.CurrentDateFunction; +import org.citrusframework.report.TestListener; +import org.mockito.InOrder; import org.slf4j.LoggerFactory; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -18,6 +23,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.function.Function; @@ -28,10 +34,15 @@ import static org.citrusframework.TestResult.RESULT.FAILURE; import static org.citrusframework.TestResult.success; import static org.citrusframework.util.TestUtils.WAIT_THREAD_PREFIX; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertThrows; import static org.testng.Assert.fail; public class DefaultTestCaseTest extends UnitTestSupport { @@ -165,6 +176,126 @@ public void doExecuteAsync(final TestContext context) { } } + @Test + public void testTestListenerEventsWithSuccessfulTestResult() { + TestListener testListenerMock = mock(); + context.getTestListeners().addTestListener(testListenerMock); + + BeforeTest beforeTestMock = mock(); + List beforeTestListMock = new ArrayList<>(){{add(beforeTestMock);}}; + context.setBeforeTest(beforeTestListMock); + + TestAction testActionMock = mock(); + List testActionListMock = new ArrayList<>(){{add(testActionMock);}}; + fixture.setFinalActions(testActionListMock); + + AfterTest afterTestMock = mock(); + List afterTestListMock = new ArrayList<>(){{add(afterTestMock);}}; + context.setAfterTest(afterTestListMock); + + fixture.doExecute(context); + fixture.finish(context); + + InOrder inOrder = inOrder(testListenerMock); + inOrder.verify(testListenerMock, times(1)).onTestStart(fixture); + inOrder.verify(testListenerMock, times(1)).onBeforeTestStart(fixture); + inOrder.verify(testListenerMock, times(1)).onBeforeTestEnd(fixture); + inOrder.verify(testListenerMock, times(1)).onTestExecutionStart(fixture); + inOrder.verify(testListenerMock, times(1)).onFinalActionsStart(fixture); + inOrder.verify(testListenerMock, times(1)).onFinalActionsEnd(fixture); + inOrder.verify(testListenerMock, times(1)).onTestExecutionEnd(fixture); + inOrder.verify(testListenerMock, times(1)).onTestSuccess(fixture); + inOrder.verify(testListenerMock, times(1)).onAfterTestStart(fixture); + inOrder.verify(testListenerMock, times(1)).onAfterTestEnd(fixture); + inOrder.verify(testListenerMock, times(1)).onTestEnd(fixture); + verifyNoMoreInteractions(testListenerMock); + } + + @Test + public void testTestListenerEventsWithTestActionFailedTestResult() { + TestAction testActionMock = mock(); + doThrow(new CitrusRuntimeException()).when(testActionMock).execute(context); + fixture.addTestAction(testActionMock); + TestListener testListenerMock = mock(); + context.getTestListeners().addTestListener(testListenerMock); + + List beforeTestListMock = List.of(mock(BeforeTest.class)); + context.setBeforeTest(beforeTestListMock); + + List testActionListMock = List.of(mock(TestAction.class)); + fixture.setFinalActions(testActionListMock); + + List afterTestListMock = List.of(mock(AfterTest.class)); + context.setAfterTest(afterTestListMock); + + assertThrows(TestCaseFailedException.class, () -> fixture.doExecute(context)); + fixture.finish(context); + + InOrder inOrder = inOrder(testListenerMock); + inOrder.verify(testListenerMock, times(1)).onTestStart(fixture); + inOrder.verify(testListenerMock, times(1)).onBeforeTestStart(fixture); + inOrder.verify(testListenerMock, times(1)).onBeforeTestEnd(fixture); + inOrder.verify(testListenerMock, times(1)).onTestExecutionStart(fixture); + inOrder.verify(testListenerMock, times(1)).onFinalActionsStart(fixture); + inOrder.verify(testListenerMock, times(1)).onFinalActionsEnd(fixture); + inOrder.verify(testListenerMock, times(1)).onTestExecutionEnd(fixture); + inOrder.verify(testListenerMock, times(1)).onTestFailure(fixture, fixture.getTestResult().getCause()); + inOrder.verify(testListenerMock, times(1)).onAfterTestStart(fixture); + inOrder.verify(testListenerMock, times(1)).onAfterTestEnd(fixture); + inOrder.verify(testListenerMock, times(1)).onTestEnd(fixture); + verifyNoMoreInteractions(testListenerMock); + } + + @Test + public void testTestListenerEventsWithFinalActionFailedTestResult() { + + TestListener testListenerMock = mock(); + context.getTestListeners().addTestListener(testListenerMock); + + List beforeTestListMock = List.of(mock(BeforeTest.class)); + context.setBeforeTest(beforeTestListMock); + + TestAction finalActionMock = mock(); + fixture.addFinalAction(finalActionMock); + doThrow(new CitrusRuntimeException()).when(finalActionMock).execute(context); + + List afterTestListMock = List.of(mock(AfterTest.class)); + context.setAfterTest(afterTestListMock); + + fixture.doExecute(context); + assertThrows(TestCaseFailedException.class, () -> fixture.finish(context)); + + InOrder inOrder = inOrder(testListenerMock); + inOrder.verify(testListenerMock, times(1)).onTestStart(fixture); + inOrder.verify(testListenerMock, times(1)).onBeforeTestStart(fixture); + inOrder.verify(testListenerMock, times(1)).onBeforeTestEnd(fixture); + inOrder.verify(testListenerMock, times(1)).onTestExecutionStart(fixture); + inOrder.verify(testListenerMock, times(1)).onFinalActionsStart(fixture); + inOrder.verify(testListenerMock, times(1)).onFinalActionsEnd(fixture); + inOrder.verify(testListenerMock, times(1)).onTestExecutionEnd(fixture); + inOrder.verify(testListenerMock, times(1)).onTestFailure(fixture, fixture.getTestResult().getCause()); + inOrder.verify(testListenerMock, times(1)).onAfterTestStart(fixture); + inOrder.verify(testListenerMock, times(1)).onAfterTestEnd(fixture); + inOrder.verify(testListenerMock, times(1)).onTestEnd(fixture); + verifyNoMoreInteractions(testListenerMock); + } + + @Test + public void testListenerEventOnTestSkipped() { + TestCaseMetaInfo testCaseMetaInfoMock = new TestCaseMetaInfo(); + testCaseMetaInfoMock.setStatus(Status.DISABLED); + fixture.setMetaInfo(testCaseMetaInfoMock); + TestListener testListenerMock = mock(); + context.getTestListeners().addTestListener(testListenerMock); + + fixture.doExecute(context); + fixture.finish(context); + + InOrder inOrder = inOrder(testListenerMock); + inOrder.verify(testListenerMock, times(1)).onTestSkipped(fixture); + verifyNoMoreInteractions(testListenerMock); + } + @Test public void testExecutionWithVariables() { fixture.setName("MyTestCase"); @@ -291,9 +422,8 @@ public void testDurationCalculation() { } private static Duration verifyDurationHasBeenMeasured(TestResult fixture) { - var testResult = fixture; - assertNotNull(testResult); - assertNotNull(testResult.getDuration()); - return testResult.getDuration(); + assertNotNull(fixture); + assertNotNull(fixture.getDuration()); + return fixture.getDuration(); } } diff --git a/core/citrus-base/src/test/java/org/citrusframework/report/MessageTracingTestListenerTest.java b/core/citrus-base/src/test/java/org/citrusframework/report/MessageTracingTestListenerTest.java index 9239cc659a..8343c35df1 100644 --- a/core/citrus-base/src/test/java/org/citrusframework/report/MessageTracingTestListenerTest.java +++ b/core/citrus-base/src/test/java/org/citrusframework/report/MessageTracingTestListenerTest.java @@ -43,13 +43,13 @@ public void setupTestling() { } @Test - public void shouldReturnTheSameTraceFile() throws Exception { + public void shouldReturnTheSameTraceFile() { String testname = "SomeDummyTest"; Assert.assertEquals(testling.getTraceFile(testname).getAbsolutePath(), testling.getTraceFile(testname).getAbsolutePath()); } @Test - public void shouldContainMessages() throws Exception { + public void shouldContainMessages() { String testname = "SomeDummyTest"; String inboundPayload = "Inbound Message"; String outboundPayload = "Outbound Message"; diff --git a/tools/restdocs/src/main/java/org/citrusframework/restdocs/http/CitrusRestDocConfigurer.java b/tools/restdocs/src/main/java/org/citrusframework/restdocs/http/CitrusRestDocConfigurer.java index 1573589f54..7727236c4e 100644 --- a/tools/restdocs/src/main/java/org/citrusframework/restdocs/http/CitrusRestDocConfigurer.java +++ b/tools/restdocs/src/main/java/org/citrusframework/restdocs/http/CitrusRestDocConfigurer.java @@ -77,7 +77,7 @@ public void onTestStart(TestCase test) { } @Override - public void onTestFinish(TestCase test) { + public void onTestExecutionEnd(TestCase test) { } @Override diff --git a/tools/restdocs/src/main/java/org/citrusframework/restdocs/soap/CitrusRestDocSoapConfigurer.java b/tools/restdocs/src/main/java/org/citrusframework/restdocs/soap/CitrusRestDocSoapConfigurer.java index ef7de35f5e..6425505734 100644 --- a/tools/restdocs/src/main/java/org/citrusframework/restdocs/soap/CitrusRestDocSoapConfigurer.java +++ b/tools/restdocs/src/main/java/org/citrusframework/restdocs/soap/CitrusRestDocSoapConfigurer.java @@ -96,7 +96,7 @@ public void onTestStart(TestCase test) { } @Override - public void onTestFinish(TestCase test) { + public void onTestExecutionEnd(TestCase test) { if (contextProvider instanceof ManualRestDocumentation) { ((ManualRestDocumentation) contextProvider).afterTest(); }