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

如何用Gradle实现部分Cucumber测试并行、其余串行执行?

解决方案:Gradle中混合并行/串行执行Cucumber测试

一、当前实现的问题分析

你的核心思路(先跑并行测试,再跑串行测试)是可行的,但当前代码存在两个关键问题:

  1. 不必要的exec嵌套:第二次Cucumber执行被包裹在exec块中,这会触发Gradle额外启动进程,大概率是导致2分钟延迟的原因。
  2. 标签逻辑丢失:第二次执行硬编码了标签(@api) and (not @parallel),没有保留用户传入的原始过滤条件(比如not @skip、not @bug)。

二、修正后的基础实现

直接在doLast中连续调用两次javaexec,去掉多余的exec嵌套,同时修正标签逻辑,完整保留原始过滤条件:

task("cucumber") {
    dependsOn("assemble", "compileTestJava")
    doLast {
        val baseTags = getProperty("tags", "((@api) and (not @skip) and (not @bug))")
        
        // 1. 运行带@parallel标签的测试(并行)
        val parallelTags = "$baseTags and @parallel"
        javaexec {
            mainClass.set("io.cucumber.core.cli.Main")
            classpath = cucumberRuntime + sourceSets.main.get().output + sourceSets.test.get().output
            systemProperties(System.getProperties().mapKeys { it.key as String })
            args = listOf(
                "--plugin", "io.qameta.allure.cucumber7jvm.AllureCucumber7Jvm",
                "--glue", "com.myproject", "src/test/resources",
                "--tags", parallelTags,
                "--threads", "4"
            )
            environment("tags", parallelTags)
        }

        // 2. 运行不带@parallel标签的测试(串行)
        val serialTags = "$baseTags and not @parallel"
        javaexec {
            mainClass.set("io.cucumber.core.cli.Main")
            classpath = cucumberRuntime + sourceSets.main.get().output + sourceSets.test.get().output
            systemProperties(System.getProperties().mapKeys { it.key as String })
            args = listOf(
                "--plugin", "io.qameta.allure.cucumber7jvm.AllureCucumber7Jvm",
                "--glue", "com.myproject", "src/test/resources",
                "--tags", serialTags,
                "--threads", "1"
            )
            environment("tags", serialTags)
        }
    }
}

这个版本消除了冗余进程开销,应该能解决延迟问题,同时确保所有原始标签过滤条件都被应用。

三、更优的Gradle任务设计

如果追求代码可维护性和调试便利性,建议拆分两个独立任务,再用总任务串联:

// 并行测试任务
task("cucumberParallel") {
    dependsOn("assemble", "compileTestJava")
    doLast {
        val baseTags = getProperty("tags", "((@api) and (not @skip) and (not @bug))")
        val parallelTags = "$baseTags and @parallel"
        javaexec {
            mainClass.set("io.cucumber.core.cli.Main")
            classpath = cucumberRuntime + sourceSets.main.get().output + sourceSets.test.get().output
            systemProperties(System.getProperties().mapKeys { it.key as String })
            args = listOf(
                "--plugin", "io.qameta.allure.cucumber7jvm.AllureCucumber7Jvm",
                "--glue", "com.myproject", "src/test/resources",
                "--tags", parallelTags,
                "--threads", "4"
            )
            environment("tags", parallelTags)
        }
    }
}

// 串行测试任务
task("cucumberSerial") {
    dependsOn("assemble", "compileTestJava")
    doLast {
        val baseTags = getProperty("tags", "((@api) and (not @skip) and (not @bug))")
        val serialTags = "$baseTags and not @parallel"
        javaexec {
            mainClass.set("io.cucumber.core.cli.Main")
            classpath = cucumberRuntime + sourceSets.main.get().output + sourceSets.test.get().output
            systemProperties(System.getProperties().mapKeys { it.key as String })
            args = listOf(
                "--plugin", "io.qameta.allure.cucumber7jvm.AllureCucumber7Jvm",
                "--glue", "com.myproject", "src/test/resources",
                "--tags", serialTags,
                "--threads", "1"
            )
            environment("tags", serialTags)
        }
    }
}

// 总任务:先跑并行,再跑串行
task("cucumber") {
    dependsOn("cucumberParallel", "cucumberSerial")
    // 强制串行任务在并行任务完成后执行
    tasks.cucumberSerial.mustRunAfter(tasks.cucumberParallel)
}

这种设计的优势:

  • 任务职责单一,可单独调试某一类测试(比如./gradlew cucumberSerial)
  • 依赖关系明确,执行顺序可控
  • 代码复用性强,后续修改只需调整对应任务

四、测试报告合并说明

你使用的Allure报告会自动合并多次执行的结果:两次Cucumber运行的结果默认写入build/allure-results目录,生成最终报告时Allure会自动扫描并合并所有结果文件。如果需要区分并行/串行结果,可自定义输出路径:

// 并行任务指定结果目录
"--plugin", "io.qameta.allure.cucumber7jvm.AllureCucumber7Jvm:build/allure-results/parallel",
// 串行任务指定结果目录
"--plugin", "io.qameta.allure.cucumber7jvm.AllureCucumber7Jvm:build/allure-results/serial",

Allure生成报告时会自动识别所有子目录的结果文件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 21:22:49