1616import static org .assertj .core .api .Assertions .assertThat ;
1717import static org .junit .platform .commons .test .PreconditionAssertions .assertPreconditionViolationFor ;
1818import static org .junit .platform .commons .util .ExceptionUtils .throwAsUncheckedException ;
19+ import static org .junit .platform .engine .TestDescriptor .Type .CONTAINER ;
20+ import static org .junit .platform .engine .TestDescriptor .Type .TEST ;
1921import static org .mockito .Mockito .atLeast ;
2022import static org .mockito .Mockito .inOrder ;
2123import static org .mockito .Mockito .mock ;
@@ -245,6 +247,33 @@ void prioritizesChildrenOfStartedContainers() throws Exception {
245247 assertThat (leaf .startTime ).isBeforeOrEqualTo (child2 .startTime );
246248 }
247249
250+ @ Test
251+ void prioritizesTestsOverContainers () throws Exception {
252+ service = new ConcurrentHierarchicalTestExecutorService (configuration (2 ));
253+
254+ var leavesStarted = new CountDownLatch (2 );
255+ var leaf = new TestTaskStub (ExecutionMode .CONCURRENT , leavesStarted ::countDown ) //
256+ .withName ("leaf" ).withLevel (3 ).withType (TEST );
257+ var child1 = new TestTaskStub (ExecutionMode .CONCURRENT , () -> requiredService ().submit (leaf ).get ()) //
258+ .withName ("child1" ).withLevel (2 ).withType (CONTAINER );
259+ var child2 = new TestTaskStub (ExecutionMode .CONCURRENT , leavesStarted ::countDown ) //
260+ .withName ("child2" ).withLevel (2 ).withType (TEST );
261+ var child3 = new TestTaskStub (ExecutionMode .SAME_THREAD , leavesStarted ::await ) //
262+ .withName ("child3" ).withLevel (2 ).withType (TEST );
263+
264+ var root = new TestTaskStub (ExecutionMode .SAME_THREAD ,
265+ () -> requiredService ().invokeAll (List .of (child1 , child2 , child3 ))) //
266+ .withName ("root" ).withLevel (1 );
267+
268+ service .submit (root ).get ();
269+
270+ root .assertExecutedSuccessfully ();
271+ assertThat (List .of (child1 , child2 , child3 )).allSatisfy (TestTaskStub ::assertExecutedSuccessfully );
272+ leaf .assertExecutedSuccessfully ();
273+
274+ assertThat (child2 .startTime ).isBeforeOrEqualTo (child1 .startTime );
275+ }
276+
248277 private static ExclusiveResource exclusiveResource () {
249278 return new ExclusiveResource ("key" , ExclusiveResource .LockMode .READ_WRITE );
250279 }
@@ -267,6 +296,7 @@ private static final class TestTaskStub implements TestTask {
267296 private ResourceLock resourceLock = NopLock .INSTANCE ;
268297 private @ Nullable String name ;
269298 private int level = 1 ;
299+ private TestDescriptor .Type type = TEST ;
270300
271301 private final CompletableFuture <@ Nullable Void > result = new CompletableFuture <>();
272302 private volatile @ Nullable Instant startTime ;
@@ -292,6 +322,11 @@ TestTaskStub withLevel(int level) {
292322 return this ;
293323 }
294324
325+ TestTaskStub withType (TestDescriptor .Type type ) {
326+ this .type = type ;
327+ return this ;
328+ }
329+
295330 TestTaskStub withResourceLock (ResourceLock resourceLock ) {
296331 this .resourceLock = resourceLock ;
297332 return this ;
@@ -314,7 +349,12 @@ public TestDescriptor getTestDescriptor() {
314349 for (var i = 1 ; i < level ; i ++) {
315350 uniqueId = uniqueId .append ("child" , name );
316351 }
317- return new TestDescriptorStub (uniqueId , name );
352+ return new TestDescriptorStub (uniqueId , name ) {
353+ @ Override
354+ public Type getType () {
355+ return type ;
356+ }
357+ };
318358 }
319359
320360 @ Override
0 commit comments