Skip to content

Commit 32f2a48

Browse files
committed
feat(#1218): add events onTestEnd, onFinalActionsEnd, onAfterSequenceBeforeTest and onAfterSequenceAfterTest
1 parent cb889b2 commit 32f2a48

File tree

4 files changed

+153
-28
lines changed

4 files changed

+153
-28
lines changed

core/citrus-api/src/main/java/org/citrusframework/report/TestListener.java

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,32 +24,69 @@
2424
*/
2525
public interface TestListener {
2626
/**
27-
* Invoked when test gets started
28-
* @param test
27+
* Invoked when test when a test starts execution
2928
*/
3029
void onTestStart(TestCase test);
3130

3231
/**
33-
* Invoked when test gets finished
34-
* @param test
32+
* Invoked when all test action executions have finished but before final actions execution and AfterSequence execution
3533
*/
3634
void onTestFinish(TestCase test);
3735

3836
/**
39-
* Invoked when test finished with success
40-
* @param test
37+
* Invoked when a test finishes successfully
4138
*/
4239
void onTestSuccess(TestCase test);
4340

4441
/**
45-
* Invoked when test finished with failure
46-
* @param test
42+
* Invoked when a test finishes with failure
4743
*/
4844
void onTestFailure(TestCase test, Throwable cause);
4945

5046
/**
51-
* Invoked when test is skipped
52-
* @param test
47+
* Invoked when a test is skipped
5348
*/
5449
void onTestSkipped(TestCase test);
50+
51+
/**
52+
* Invoked when test execution has completely ended (including final actions and sequences)
53+
*/
54+
default void onTestEnd(TestCase test) {
55+
// Default implementation does nothing
56+
}
57+
58+
/**
59+
* Invoked after final actions have completely finished
60+
*/
61+
default void onFinalActionsEnd(TestCase test) {
62+
// Default implementation does nothing
63+
}
64+
65+
/**
66+
* Invoked after the AfterSequence but before the test has fully ended
67+
*/
68+
default void onAfterSequenceBeforeTest(TestCase test) {
69+
// Default implementation does nothing
70+
}
71+
72+
/**
73+
* Invoked after the AfterSequence and after the test execution
74+
*/
75+
default void onAfterSequenceAfterTest(TestCase test) {
76+
// Default implementation does nothing
77+
}
78+
79+
/**
80+
* Invoked before the sequence and before the test execution
81+
*/
82+
default void onBeforeSequenceBeforeTest(TestCase test) {
83+
// Default implementation does nothing
84+
}
85+
86+
/**
87+
* Invoked before the sequence but after the test execution
88+
*/
89+
default void onBeforeSequenceAfterTest(TestCase test) {
90+
// Default implementation does nothing
91+
}
5592
}

core/citrus-api/src/main/java/org/citrusframework/report/TestListeners.java

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,42 @@ public void onTestStart(TestCase test) {
5555
}
5656
}
5757

58+
public void onTestEnd(TestCase test) {
59+
for (TestListener listener : testListeners) {
60+
listener.onTestEnd(test);
61+
}
62+
}
63+
64+
public void onFinalActionsEnd(TestCase test) {
65+
for (TestListener listener : testListeners) {
66+
listener.onFinalActionsEnd(test);
67+
}
68+
}
69+
70+
public void onAfterSequenceBeforeTest(TestCase test) {
71+
for (TestListener listener : testListeners) {
72+
listener.onAfterSequenceBeforeTest(test);
73+
}
74+
}
75+
76+
public void onAfterSequenceAfterTest(TestCase test) {
77+
for (TestListener listener : testListeners) {
78+
listener.onAfterSequenceAfterTest(test);
79+
}
80+
}
81+
82+
public void onBeforeSequenceBeforeTest(TestCase test) {
83+
for (TestListener listener : testListeners) {
84+
listener.onBeforeSequenceBeforeTest(test);
85+
}
86+
}
87+
88+
public void onBeforeSequenceAfterTest(TestCase test) {
89+
for (TestListener listener : testListeners) {
90+
listener.onBeforeSequenceAfterTest(test);
91+
}
92+
}
93+
5894
public void onTestSuccess(TestCase test) {
5995
for (TestListener listener : testListeners) {
6096
listener.onTestSuccess(test);
@@ -70,7 +106,6 @@ public void addTestListener(TestListener listener) {
70106

71107
/**
72108
* Obtains the testListeners.
73-
* @return
74109
*/
75110
public List<TestListener> getTestListeners() {
76111
return testListeners;

core/citrus-base/src/main/java/org/citrusframework/DefaultTestCase.java

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ public void beforeTest(final TestContext context) {
166166
throw new CitrusRuntimeException("Before test failed with errors", e);
167167
}
168168
}
169+
context.getTestListeners().onAfterSequenceBeforeTest(this);
169170
}
170171

171172
@Override
@@ -179,6 +180,7 @@ public void afterTest(final TestContext context) {
179180
logger.warn("After test failed with errors", e);
180181
}
181182
}
183+
context.getTestListeners().onAfterSequenceAfterTest(this);
182184
}
183185

184186
@Override
@@ -237,6 +239,7 @@ public void finish(final TestContext context) {
237239

238240
context.getTestListeners().onTestFinish(this);
239241
executeFinalActions(context);
242+
context.getTestListeners().onFinalActionsEnd(this);
240243

241244
if (contextException != null) {
242245
throw new TestCaseFailedException(contextException);
@@ -261,6 +264,8 @@ public void finish(final TestContext context) {
261264
afterTest(context);
262265

263266
completeTestResultWithDuration();
267+
268+
context.getTestListeners().onTestEnd(this);
264269
}
265270
}
266271

@@ -326,9 +331,6 @@ private void executeFinalActions(TestContext context) {
326331

327332
/**
328333
* Print variables in given test context.
329-
*
330-
* @param scope
331-
* @param context
332334
*/
333335
private void debugVariables(String scope, TestContext context) {
334336
/* Debug print global variables */
@@ -342,9 +344,6 @@ private void debugVariables(String scope, TestContext context) {
342344

343345
/**
344346
* Sets test parameters as test variables.
345-
*
346-
* @param parameters
347-
* @param context
348347
*/
349348
private void initializeTestParameters(Map<String, Object> parameters, TestContext context) {
350349
// add default variables for test
@@ -359,9 +358,6 @@ private void initializeTestParameters(Map<String, Object> parameters, TestContex
359358

360359
/**
361360
* Initialize the test variables in the given test context.
362-
*
363-
* @param variableDefinitions
364-
* @param context
365361
*/
366362
private void initializeTestVariables(Map<String, Object> variableDefinitions, TestContext context) {
367363
/* build up the global test variables in TestContext by
@@ -381,8 +377,6 @@ private void initializeTestVariables(Map<String, Object> variableDefinitions, Te
381377

382378
/**
383379
* Setter for variables.
384-
*
385-
* @param variableDefinitions
386380
*/
387381
public void setVariableDefinitions(final Map<String, Object> variableDefinitions) {
388382
this.variableDefinitions = variableDefinitions;
@@ -395,8 +389,6 @@ public Map<String, Object> getVariableDefinitions() {
395389

396390
/**
397391
* Setter for finally chain.
398-
*
399-
* @param finalActions
400392
*/
401393
public void setFinalActions(final List<TestAction> finalActions) {
402394
this.finalActions = finalActions.stream().map(action -> (TestActionBuilder<?>) () -> action).collect(Collectors.toList());
@@ -543,17 +535,13 @@ public void setGroups(final String[] groups) {
543535

544536
/**
545537
* Sets the timeout.
546-
*
547-
* @param timeout
548538
*/
549539
public void setTimeout(final long timeout) {
550540
this.timeout = timeout;
551541
}
552542

553543
/**
554544
* Gets the timeout.
555-
*
556-
* @return
557545
*/
558546
public long getTimeout() {
559547
return timeout;

core/citrus-base/src/test/java/org/citrusframework/DefaultTestCaseTest.java

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.citrusframework;
22

3+
import org.citrusframework.TestCaseMetaInfo.Status;
34
import org.citrusframework.actions.AbstractAsyncTestAction;
45
import org.citrusframework.actions.EchoAction;
56
import org.citrusframework.actions.SleepAction;
@@ -10,6 +11,8 @@
1011
import org.citrusframework.exceptions.CitrusRuntimeException;
1112
import org.citrusframework.exceptions.TestCaseFailedException;
1213
import org.citrusframework.functions.core.CurrentDateFunction;
14+
import org.citrusframework.report.TestListener;
15+
import org.mockito.InOrder;
1316
import org.slf4j.LoggerFactory;
1417
import org.testng.annotations.BeforeMethod;
1518
import org.testng.annotations.Test;
@@ -26,12 +29,20 @@
2629
import static java.util.Collections.singletonMap;
2730
import static org.citrusframework.DefaultTestActionBuilder.action;
2831
import static org.citrusframework.TestResult.RESULT.FAILURE;
32+
import static org.citrusframework.TestResult.failed;
2933
import static org.citrusframework.TestResult.success;
3034
import static org.citrusframework.util.TestUtils.WAIT_THREAD_PREFIX;
35+
import static org.mockito.Mockito.doThrow;
36+
import static org.mockito.Mockito.inOrder;
3137
import static org.mockito.Mockito.mock;
38+
import static org.mockito.Mockito.times;
39+
import static org.mockito.Mockito.verify;
40+
import static org.mockito.Mockito.verifyNoMoreInteractions;
41+
import static org.mockito.Mockito.when;
3242
import static org.testng.Assert.assertEquals;
3343
import static org.testng.Assert.assertNotNull;
3444
import static org.testng.Assert.assertNull;
45+
import static org.testng.Assert.assertThrows;
3546
import static org.testng.Assert.fail;
3647

3748
public class DefaultTestCaseTest extends UnitTestSupport {
@@ -165,6 +176,60 @@ public void doExecuteAsync(final TestContext context) {
165176
}
166177
}
167178

179+
@Test
180+
public void testTestListenerEventsWithSuccessTestResult() {
181+
TestListener testListenerMock = mock();
182+
context.getTestListeners().addTestListener(testListenerMock);
183+
184+
fixture.doExecute(context);
185+
fixture.finish(context);
186+
187+
InOrder inOrder = inOrder(testListenerMock);
188+
inOrder.verify(testListenerMock, times(1)).onTestStart(fixture);
189+
inOrder.verify(testListenerMock, times(1)).onAfterSequenceBeforeTest(fixture);
190+
inOrder.verify(testListenerMock, times(1)).onTestFinish(fixture);
191+
inOrder.verify(testListenerMock, times(1)).onFinalActionsEnd(fixture);
192+
inOrder.verify(testListenerMock, times(1)).onTestSuccess(fixture);
193+
inOrder.verify(testListenerMock, times(1)).onAfterSequenceAfterTest(fixture);
194+
inOrder.verify(testListenerMock, times(1)).onTestEnd(fixture);
195+
verifyNoMoreInteractions(testListenerMock);
196+
}
197+
198+
@Test(expectedExceptions = TestCaseFailedException.class)
199+
public void testTestListenerEventsWithFailedTestResult() {
200+
TestAction testActionMock = mock();
201+
doThrow(CitrusRuntimeException.class).when(testActionMock).execute(context);
202+
fixture.addTestAction(testActionMock);
203+
TestListener testListenerMock = mock();
204+
context.getTestListeners().addTestListener(testListenerMock);
205+
206+
fixture.doExecute(context);
207+
fixture.finish(context);
208+
209+
verify(testListenerMock, times(1)).onTestStart(fixture);
210+
verify(testListenerMock, times(1)).onAfterSequenceBeforeTest(fixture);
211+
verify(testListenerMock, times(1)).onTestFinish(fixture);
212+
verify(testListenerMock, times(1)).onFinalActionsEnd(fixture);
213+
verify(testListenerMock, times(1)).onTestFailure(fixture, fixture.getTestResult().getCause());
214+
verify(testListenerMock, times(1)).onTestEnd(fixture);
215+
verifyNoMoreInteractions(testListenerMock);
216+
}
217+
218+
@Test
219+
public void testListenerEventOnTestSkipped() {
220+
TestCaseMetaInfo testCaseMetaInfoMock = new TestCaseMetaInfo();
221+
testCaseMetaInfoMock.setStatus(Status.DISABLED);
222+
fixture.setMetaInfo(testCaseMetaInfoMock);
223+
TestListener testListenerMock = mock();
224+
context.getTestListeners().addTestListener(testListenerMock);
225+
226+
fixture.doExecute(context);
227+
fixture.finish(context);
228+
229+
verify(testListenerMock, times(1)).onTestSkipped(fixture);
230+
verifyNoMoreInteractions(testListenerMock);
231+
}
232+
168233
@Test
169234
public void testExecutionWithVariables() {
170235
fixture.setName("MyTestCase");

0 commit comments

Comments
 (0)