maven-failsafe-plugin在JUnit5中不遵循固定并行度配置问题
环境信息
- maven-failsafe-plugin 2.22.2
- JUnit 5.9.1
- Selenium 4.7.0
- JDK 8
Maven Failsafe 插件配置
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-failsafe-plugin</artifactId> <version>2.22.2</version> <!-- Parallel configuration see junit-platform.properties --> </plugin>
单线程测试(符合预期)
在junit-platform.properties中设置:
junit.jupiter.execution.parallel.enabled=false
测试按预期以单线程运行。
固定并行策略不生效问题
当设置以下并行配置时:
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
实际有约10个浏览器并行启动,说明maven-failsafe-plugin能读取junit-platform.properties中的启用配置,但不遵循固定并行数策略。
已知相关问题
JUnit的GitHub问题#2273《Parallelism value ignored for the fixed strategy》描述过该问题,Selenium的GitHub问题#9359《Can no longer limit the number of parallel sessions from JUnit 5》进一步说明该问题影响Selenium 4.0.0-alpha-4及以上版本。
自定义并行策略尝试无效
按照上述问题中的方案实现自定义并行策略,并修改配置:
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
问题依旧,仍有约10个浏览器并行打开。目前未找到相关Stack Overflow帖子或GitHub issue描述这种「maven-failsafe-plugin遵循启用配置但不遵循并行策略配置」的行为。
2022年12月16日更新
查看ForkJoinPoolHierarchicalTestExecutorService的代码,ForkJoinPool的创建逻辑如下:
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)); }
可见maxPoolSize配置仅在JDK 9及以上版本生效。另外发现:Eclipse会为每个测试类单独调用ForkJoinPoolHierarchicalTestExecutorService#invokeAll(List<? extends TestTask>),而Maven会一次性传入所有测试类调用该方法。
内容的提问来源于stack exchange,提问作者Simon

