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

Jenkins声明式流水线:并行批量执行测试用例问题求助

批量并行执行Postman集合的完善方案

针对你遇到的Jenkins执行Postman集合时的资源耗尽、批次中断问题,这里提供两种可落地的解决方案:

1. Groovy脚本原生线程实现(适合自由风格项目)

核心思路是单独捕获每个Newman任务的退出码,不直接让Jenkins感知非零退出码中断流程,最后统一汇总失败状态,同时保持批次内并行、批次间串行的执行逻辑:

// 动态从多仓库拉取的测试集合列表(替换成你的实际获取逻辑)
def testCollections = findFiles(glob: "**/*.postman_collection.json").collect { it.path }
// 可根据Jenkins节点资源调整(10-20之间)
def batchSize = 15
// 线程安全的失败集合存储
def failedCollections = Collections.synchronizedList([])

// 分批处理集合
for (int i = 0; i < testCollections.size(); i += batchSize) {
    def currentBatch = testCollections.subList(i, Math.min(i + batchSize, testCollections.size()))
    def batchFutures = []
    
    // 批次内并行执行每个集合
    currentBatch.each { collectionPath ->
        batchFutures.add(Thread.start {
            println "启动测试集合: ${collectionPath}"
            // 执行Newman命令并捕获退出码
            def newmanProcess = "newman run ${collectionPath}".execute()
            // 打印输出(可选,便于排查问题)
            newmanProcess.in.eachLine { line -> println line }
            newmanProcess.err.eachLine { line -> println "ERROR: ${line}" }
            newmanProcess.waitFor()
            
            def exitCode = newmanProcess.exitValue()
            if (exitCode != 0) {
                synchronized(failedCollections) {
                    failedCollections.add(collectionPath)
                }
                println "集合 ${collectionPath} 执行失败,退出码: ${exitCode}"
            } else {
                println "集合 ${collectionPath} 执行成功"
            }
        })
    }
    
    // 等待当前批次所有任务完成,再执行下一批
    batchFutures.each { it.join() }
    println "=== 第 ${(i / batchSize).toInteger() + 1} 批次执行完成 ==="
}

// 最后统一判定构建状态
if (!failedCollections.isEmpty()) {
    println "\n=== 以下测试集合执行失败 ==="
    failedCollections.each { println "- ${it}" }
    // 抛出错误标记构建失败
    error("测试执行失败,共 ${failedCollections.size()} 个集合未通过")
} else {
    println "\n=== 所有测试集合执行成功 ==="
}

关键细节:

  • 用Thread.start实现批次内并行,避免sh命令默认的非零退出码中断逻辑
  • 用Collections.synchronizedList保证多线程环境下失败集合的线程安全
  • 打印Newman的标准输出和错误输出,便于后续排查失败原因
  • 批次执行完成后再推进到下一批,避免资源瞬间耗尽

2. Jenkins Pipeline Parallel步骤实现(适合Pipeline项目)

如果使用Jenkins Pipeline,官方的parallel步骤更规范,且自带线程管理,结合sh returnStatus: true捕获退出码:

pipeline {
    agent any
    stages {
        stage('批量执行Postman测试') {
            steps {
                script {
                    // 动态获取测试集合(替换成你的多仓库拉取逻辑)
                    def testCollections = findFiles(glob: "**/*.postman_collection.json").collect { it.path }
                    def batchSize = 15
                    def failedCollections = []
                    
                    for (int i = 0; i < testCollections.size(); i += batchSize) {
                        def currentBatch = testCollections.subList(i, Math.min(i + batchSize, testCollections.size()))
                        def parallelTasks = [:]
                        
                        // 构建当前批次的并行任务
                        currentBatch.each { collectionPath ->
                            parallelTasks["测试集合: ${collectionPath}"] = {
                                script {
                                    def exitCode = sh(
                                        script: "newman run ${collectionPath}",
                                        returnStatus: true,
                                        label: "执行集合 ${collectionPath}"
                                    )
                                    if (exitCode != 0) {
                                        failedCollections.add(collectionPath)
                                    }
                                }
                            }
                        }
                        
                        // 执行当前批次并行任务
                        parallel parallelTasks
                        echo "=== 第 ${(i / batchSize).toInteger() + 1} 批次执行完成 ==="
                    }
                    
                    // 最终状态判定
                    if (!failedCollections.isEmpty()) {
                        echo "\n=== 失败集合列表 ==="
                        failedCollections.each { echo "- ${it}" }
                        error "测试失败,共 ${failedCollections.size()} 个集合未通过"
                    } else {
                        echo "\n=== 所有测试集合执行成功 ==="
                    }
                }
            }
        }
    }
}

关键细节:

  • sh returnStatus: true会返回命令的退出码,而非直接中断Pipeline
  • parallel步骤由Jenkins管理线程,比手动创建线程更稳定
  • 每个任务带label,便于在Jenkins控制台查看每个集合的执行状态

额外优化建议

  • 动态调整批次大小:根据Jenkins节点的CPU核心数自动计算,比如def batchSize = Runtime.runtime.availableProcessors() * 2,适配不同节点资源
  • Newman性能优化:执行时添加--silent减少输出,或指定--reporters cli只输出必要信息,降低IO开销
  • 资源隔离:如果Jenkins节点支持,可使用node标签指定专门的测试执行节点,避免影响其他任务

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 07:02:50