You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JUnit 5结合Spock测试无法并行执行问题求助

问题:Spock测试无法通过JUnit 5并行执行配置实现并行运行

我编写了如下Spock测试代码,尝试使用JUnit 5.9.0的@Execution注解实现并行执行:

import org.junit.jupiter.api.parallel.Execution // version 5.9.0
import org.junit.jupiter.api.parallel.ExecutionMode
import spock.lang.Specification
import spock.lang.Unroll

@Execution(ExecutionMode.CONCURRENT)
class ExampleTest extends Specification {

    @Unroll
    @Execution(ExecutionMode.CONCURRENT)
    def "test1: should get valid #testParam"() {
        System.out.println("FirstParallelUnitTest first() start => " + Thread.currentThread().getName() +
                "  id: " + Thread.currentThread().getId());
        given:
            def test = testParam
        expect:
            test != null
            System.out.println("FirstParallelUnitTest first() end => " + Thread.currentThread().getName() +
                    "  id: " + Thread.currentThread().getId());
        where:
            testParam << ["one", "two", "three", "four"]
    }

    @Unroll
    @Execution(ExecutionMode.CONCURRENT)
    def "test2: should get valid #testParam"() {
        System.out.println("FirstParallelUnitTest first() start => " + Thread.currentThread().getName() +
                "  id: " + Thread.currentThread().getId());
        given:
            def test = testParam
        expect:
            test != null
            System.out.println("FirstParallelUnitTest first() end => " + Thread.currentThread().getName() +
                    "  id: " + Thread.currentThread().getId());
        where:
            testParam << ["one", "two", "three", "four"]
    }

    @Unroll
    @Execution(ExecutionMode.CONCURRENT)
    def "test3: should get valid #testParam"() {
        System.out.println("FirstParallelUnitTest first() start => " + Thread.currentThread().getName() +
                "  id: " + Thread.currentThread().getId());
        given:
            def test = testParam
        expect:
            test != null
            System.out.println("FirstParallelUnitTest first() end => " + Thread.currentThread().getName() +
                    "  id: " + Thread.currentThread().getId());
        where:
            testParam << ["one", "two", "three", "four"]
    }
}

我已在src/test/resources下创建junit-platform.properties文件,内容如下:

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

同时在Gradle 7.6的test任务中添加了systemProperties配置:

test {
    testLogging {
        exceptionFormat = 'full'
    }
    useJUnitPlatform()
    systemProperties([
            'junit.jupiter.execution.parallel.enabled': 'true',
            'junit.jupiter.execution.parallel.mode.default': 'concurrent',
            'junit.jupiter.execution.parallel.mode.classes.default': 'concurrent',
    ])
}

测试依赖配置:

testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
testImplementation("org.junit.jupiter:junit-jupiter-params")

还尝试在build.gradle中添加:

subprojects {
    tasks.withType(Test) {
        maxParallelForks = Runtime.runtime.availableProcessors()
    }
}

我的处理器是i7-6600U(2核),期望看到并行执行效果,但运行测试时日志显示线程ID始终为1,所有测试串行执行,start/end顺序固定。请问如何让这些测试及其他测试实现并行执行?


解决方法

1. 确认Spock版本与JUnit 5并行支持的兼容性

Spock 2.x及以上版本才支持JUnit 5的并行执行特性,检查依赖中是否引入了正确的Spock版本,添加核心依赖:

testImplementation("org.spockframework:spock-core:2.3-groovy-4.0")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")

注意:Groovy版本要与Spock版本匹配,比如Spock 2.3对应Groovy 4.0,若使用Groovy 3.x则选择2.3-groovy-3.0。

2. 移除重复的并行配置

同时在junit-platform.properties和Gradle的systemProperties中配置并行参数可能导致冲突,建议只保留其中一处配置,推荐使用junit-platform.properties。

3. 简化注解配置

类上的@Execution(ExecutionMode.CONCURRENT)已让该类下所有测试方法默认并发执行,无需给每个方法重复添加该注解。

4. 调整Gradle的进程级并行配置

maxParallelForks是Gradle进程级并行,与JUnit 5线程级并行是不同维度。你的处理器是2核,设置maxParallelForks = 2即可,避免设置为逻辑核心数导致资源竞争。

5. 优化日志打印

修改日志内容区分不同测试方法和参数,方便验证并行效果:

System.out.println("test1 start (#testParam) => " + Thread.currentThread().getName() + "  id: " + Thread.currentThread().getId());

6. 检查IDE配置

确保IDE的测试运行配置未强制串行执行,比如IntelliJ IDEA中需开启"Run/Debug Configurations"里的"Parallel execution"选项。


内容的提问来源于stack exchange,提问作者tryingHard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 03:21:11