1

I'm trying to run tests in parallel, but with a fixed number of threads.

  • maven-failsafe-plugin 2.22.2
  • JUnit 5.9.1
  • Selenium 4.7.0
  • JDK8
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-failsafe-plugin</artifactId>
  <version>2.22.2</version>
  <!-- Parallel configuration see junit-platform.properties -->
</plugin>

If I start off with junit-platform.properties setting

junit.jupiter.execution.parallel.enabled=false

the tests run single-threaded, as expected.

Setting

junit.jupiter.execution.parallel.enabled=true
junit.jupiter.execution.parallel.mode.default=same_thread
junit.jupiter.execution.parallel.mode.classes.default=concurrent
junit.jupiter.execution.parallel.config.strategy=fixed
junit.jupiter.execution.parallel.config.fixed.parallelism=2

results in ca. 10 browsers starting in parallel. This shows that maven-failsafe-plugin honors the junit-platform.properties, but not the fixed strategy.

JUnit issue 'Parallelism value ignored for the fixed strategy' #2273 describes this issue, and more specifically Selenium issue 'Can no longer limit the number of parallel sessions from JUnit 5 #9359' describes the impact on Selenium versions 4.0.0-alpha-4 and up.

However, implementing a custom parallel strategy as described in the above issues and setting

junit.jupiter.execution.parallel.enabled=true
junit.jupiter.execution.parallel.mode.default=same_thread
junit.jupiter.execution.parallel.mode.classes.default=concurrent
junit.jupiter.execution.parallel.config.strategy=custom
junit.jupiter.execution.parallel.config.custom.class=ch.want.funnel.integration.base.CustomParallelStrategy

doesn't change anything, there are still ca. 10 browsers opening in parallel.

I can't find an SO post nor a github issue describing this behavior, which is that maven-failsafe-plugin does honor junit-platform.properties, does honor the junit.jupiter.execution.parallel.enabled setting therein, but not the parallel.config.strategy.

Update Dec 16th 2022

Looking at ForkJoinPoolHierarchicalTestExecutorService, the ForkJoinPool is created with

private ForkJoinPool createForkJoinPool(ParallelExecutionConfiguration configuration) {
    ForkJoinWorkerThreadFactory threadFactory = new WorkerThreadFactory();
    return Try.call(() -> {
        // Try to use constructor available in Java >= 9
        Constructor<ForkJoinPool> constructor = ForkJoinPool.class.getDeclaredConstructor(Integer.TYPE,
            ForkJoinWorkerThreadFactory.class, UncaughtExceptionHandler.class, Boolean.TYPE, Integer.TYPE,
            Integer.TYPE, Integer.TYPE, Predicate.class, Long.TYPE, TimeUnit.class);
        return constructor.newInstance(configuration.getParallelism(), threadFactory, null, false,
            configuration.getCorePoolSize(), configuration.getMaxPoolSize(), configuration.getMinimumRunnable(),
            configuration.getSaturatePredicate(), configuration.getKeepAliveSeconds(), TimeUnit.SECONDS);
    }).orElseTry(() -> {
        // Fallback for Java 8
        return new ForkJoinPool(configuration.getParallelism(), threadFactory, null, false);
    }).getOrThrow(cause -> new JUnitException("Failed to create ForkJoinPool", cause));
}

so the configuration maxPoolSize is only taken into account for JDK9 and higher. Also, Eclipse calls

ForkJoinPoolHierarchicalTestExecutorService#invokeAll(List<? extends TestTask>) 

individually for each test class, while Maven calls once with all test classes.

Simon
  • 2,994
  • 3
  • 28
  • 37
  • First I would suggest that you upgrade maven-surefire-plugin to most recent version 3.0.0-M7 and recheck. Do you have several test classes or only a single one? – khmarbaise Dec 15 '22 at 09:33
  • Thank @khmarbaise. I've checked 3.0.0-M7, same behavior. There are about 100 test classes, each with 1-5 test methods. – Simon Dec 15 '22 at 12:10
  • Can you post the configuration for maven-surefire-plugin ... – khmarbaise Dec 15 '22 at 13:24
  • @khmarbaise, these are Selenium integration tests running with maven-failsafe-plugin, so surefire shouldn't be relevant here – Simon Dec 15 '22 at 13:47
  • That was not my question. The configuration of maven-surefire-plugin... – khmarbaise Dec 15 '22 at 14:15

1 Answers1

-1

Based on junit.jupiter.execution.parallel.mode.classes.default=concurrent you have allowed to paralellize on class level.

This means if you have a enough cores there will be started appropriate number of threads. If you like to limit the number you have to go via:

junit.jupiter.execution.parallel.config.strategy=fixed
junit.jupiter.execution.parallel.config.fixed.parallelism=6

otherwise the default Fork-Join poil will be taken into account.

khmarbaise
  • 92,914
  • 28
  • 189
  • 235
  • That's really the point of this post. Setting fixed and parallelism doesn't limit the number of threads. I set parallelism=2, and 10 threads start up. (My setup is to run classes in parallel, and methods within classes sequentially. This makes sense in our case because test methods within one class usually use the same test resources) – Simon Dec 15 '22 at 13:49
  • I would first try to limit parallelism to 1 to check... and afterwards changing it... furthermore you should use no custom strategy in the first place...use that later... – khmarbaise Dec 15 '22 at 14:27