10
10
11
11
package org .junit .platform .suite .engine ;
12
12
13
+ import static java .util .Objects .requireNonNull ;
13
14
import static org .assertj .core .api .Assertions .assertThat ;
15
+ import static org .assertj .core .api .Assertions .not ;
14
16
import static org .junit .platform .engine .discovery .DiscoverySelectors .selectClass ;
15
17
import static org .junit .platform .engine .discovery .DiscoverySelectors .selectUniqueId ;
16
18
import static org .junit .platform .launcher .TagFilter .excludeTags ;
22
24
import static org .junit .platform .testkit .engine .EventConditions .event ;
23
25
import static org .junit .platform .testkit .engine .EventConditions .finishedSuccessfully ;
24
26
import static org .junit .platform .testkit .engine .EventConditions .finishedWithFailure ;
27
+ import static org .junit .platform .testkit .engine .EventConditions .skippedWithReason ;
28
+ import static org .junit .platform .testkit .engine .EventConditions .started ;
25
29
import static org .junit .platform .testkit .engine .EventConditions .test ;
26
30
import static org .junit .platform .testkit .engine .TestExecutionResultConditions .instanceOf ;
27
31
import static org .junit .platform .testkit .engine .TestExecutionResultConditions .message ;
32
36
33
37
import java .nio .file .Path ;
34
38
39
+ import org .jspecify .annotations .Nullable ;
35
40
import org .junit .jupiter .api .Test ;
36
41
import org .junit .jupiter .api .io .TempDir ;
37
42
import org .junit .jupiter .engine .descriptor .ClassTestDescriptor ;
38
43
import org .junit .jupiter .engine .descriptor .JupiterEngineDescriptor ;
39
44
import org .junit .jupiter .engine .descriptor .TestMethodTestDescriptor ;
40
45
import org .junit .jupiter .params .ParameterizedTest ;
41
46
import org .junit .jupiter .params .provider .ValueSource ;
47
+ import org .junit .platform .engine .CancellationToken ;
42
48
import org .junit .platform .engine .DiscoveryIssue ;
43
49
import org .junit .platform .engine .DiscoveryIssue .Severity ;
44
50
import org .junit .platform .engine .EngineExecutionListener ;
51
57
import org .junit .platform .engine .support .store .NamespacedHierarchicalStore ;
52
58
import org .junit .platform .launcher .PostDiscoveryFilter ;
53
59
import org .junit .platform .launcher .core .NamespacedHierarchicalStoreProviders ;
60
+ import org .junit .platform .suite .api .AfterSuite ;
61
+ import org .junit .platform .suite .api .BeforeSuite ;
54
62
import org .junit .platform .suite .api .SelectClasses ;
55
63
import org .junit .platform .suite .api .Suite ;
56
64
import org .junit .platform .suite .engine .testcases .ConfigurationSensitiveTestCase ;
@@ -628,11 +636,6 @@ void discoveryIssueOfNestedTestEnginesAreReported() throws Exception {
628
636
// @formatter:on
629
637
}
630
638
631
- @ Suite
632
- @ SelectClasses (SingleTestTestCase .class )
633
- abstract private static class AbstractPrivateSuite {
634
- }
635
-
636
639
@ Test
637
640
void suiteEnginePassesRequestLevelStoreToSuiteTestDescriptors () {
638
641
UniqueId engineId = UniqueId .forEngine (SuiteEngineDescriptor .ENGINE_ID );
@@ -643,15 +646,87 @@ void suiteEnginePassesRequestLevelStoreToSuiteTestDescriptors() {
643
646
644
647
EngineExecutionListener listener = mock (EngineExecutionListener .class );
645
648
NamespacedHierarchicalStore <Namespace > requestLevelStore = NamespacedHierarchicalStoreProviders .dummyNamespacedHierarchicalStore ();
649
+ var cancellationToken = CancellationToken .create ();
646
650
647
651
ExecutionRequest request = mock ();
648
652
when (request .getRootTestDescriptor ()).thenReturn (engineDescriptor );
649
653
when (request .getEngineExecutionListener ()).thenReturn (listener );
650
654
when (request .getStore ()).thenReturn (requestLevelStore );
655
+ when (request .getCancellationToken ()).thenReturn (cancellationToken );
651
656
652
657
new SuiteTestEngine ().execute (request );
653
658
654
- verify (mockDescriptor ).execute (same (listener ), same (requestLevelStore ));
659
+ verify (mockDescriptor ).execute (same (listener ), same (requestLevelStore ), same (cancellationToken ));
660
+ }
661
+
662
+ @ Test
663
+ void reportsSuiteClassAsSkippedWhenCancelledBeforeExecution () {
664
+ CancellingSuite .cancellationToken = CancellationToken .create ();
665
+ try {
666
+ var testKit = EngineTestKit .engine (ENGINE_ID ) //
667
+ .selectors (selectClass (CancellingSuite .class ), selectClass (SelectMethodsSuite .class )) //
668
+ .cancellationToken (CancellingSuite .cancellationToken );
669
+
670
+ var results = testKit .execute ();
671
+
672
+ results .allEvents ().debug ().assertEventsMatchLooselyInOrder ( //
673
+ event (container (CancellingSuite .class ), started ()), //
674
+ event (container (SingleTestTestCase .class ), skippedWithReason ("Execution cancelled" )), //
675
+ event (container (CancellingSuite .class ), finishedSuccessfully ()), //
676
+ event (container (SelectMethodsSuite .class ), not (container (MultipleTestsTestCase .class )),
677
+ skippedWithReason ("Execution cancelled" )) //
678
+ );
679
+ }
680
+ finally {
681
+ CancellingSuite .cancellationToken = null ;
682
+ }
683
+ }
684
+
685
+ @ Test
686
+ void reportsChildrenOfEnginesInSuiteAsSkippedWhenCancelledDuringExecution () {
687
+ CancellingSuite .cancellationToken = CancellationToken .create ();
688
+ try {
689
+ var testKit = EngineTestKit .engine (ENGINE_ID ) //
690
+ .selectors (selectClass (CancellingSuite .class )) //
691
+ .cancellationToken (CancellingSuite .cancellationToken );
692
+
693
+ var results = testKit .execute ();
694
+
695
+ results .allEvents ().assertThatEvents () //
696
+ .haveExactly (1 , event (container (SingleTestTestCase .class ),
697
+ skippedWithReason ("Execution cancelled" ))).haveExactly (0 , event (test (), started ()));
698
+
699
+ assertThat (CancellingSuite .afterCalled ) //
700
+ .describedAs ("@AfterSuite method was called" ) //
701
+ .isTrue ();
702
+ }
703
+ finally {
704
+ CancellingSuite .cancellationToken = null ;
705
+ }
706
+ }
707
+
708
+ // -----------------------------------------------------------------------------------------------------------------
709
+
710
+ static class CancellingSuite extends SelectClassesSuite {
711
+
712
+ static @ Nullable CancellationToken cancellationToken ;
713
+ static boolean afterCalled ;
714
+
715
+ @ BeforeSuite
716
+ static void beforeSuite () {
717
+ CancellingSuite .afterCalled = false ;
718
+ requireNonNull (cancellationToken ).cancel ();
719
+ }
720
+
721
+ @ AfterSuite
722
+ static void afterSuite () {
723
+ afterCalled = true ;
724
+ }
725
+ }
726
+
727
+ @ Suite
728
+ @ SelectClasses (SingleTestTestCase .class )
729
+ abstract private static class AbstractPrivateSuite {
655
730
}
656
731
657
732
@ Suite
0 commit comments