如何在Jenkins中实现按文件夹批量运行GitHub仓库的JMeter性能脚本套件
指定文件夹批量识别JMeter脚本的落地实现方案
核心实现逻辑
完全基于现有Jenkinsfile的Groovy语法能力,不需要引入额外插件,仅需替换原来逐一枚举JMX脚本的硬编码逻辑,通过本地目录遍历能力,读取指定路径下所有符合规则的.jmx文件,生成和原硬编码格式完全对齐的脚本列表,兼容现有所有后续执行、结果收集的流程。
前置校验
- Jenkins节点(控制器/代理节点)已配置全局
jmeter命令环境变量,可直接调用 - 仓库拉取后指定脚本文件夹的内容无过滤,可正常在工作空间中访问
- Groovy沙箱已开放
File类相关基础方法的调用权限,无遍历操作拦截
具体代码实现
1. 替换原硬编码的脚本列表生成逻辑
原来的硬编码写法(逐行罗列脚本,维护成本极高):
// 旧写法:150+个脚本需要逐行录入 def jmxScripts = [ "perf-scripts/1/user_login.jmx", "perf-scripts/1/order_pay.jmx", // ... 剩余148个脚本重复罗列 ]
新增通用脚本扫描方法,放到Jenkinsfile的全局方法区,一次编写全局复用:
// 通用扫描方法:输入目标文件夹相对工作空间的路径,返回所有有效JMX脚本的相对路径列表 def scanJmxByFolder(String targetFolderRelPath) { // 构造目标文件夹在当前工作空间的绝对路径对象 def targetDir = new File(env.WORKSPACE, targetFolderRelPath) // 基础校验,异常直接中断流水线 if (!targetDir.exists() || !targetDir.isDirectory()) { error "执行终止:指定的脚本文件夹不存在 ${targetFolderRelPath}" } // 过滤目录下的有效JMX文件,自动排除临时/备份/隐藏文件 def scriptList = targetDir.listFiles().findAll { entry -> entry.isFile() && entry.name.endsWith('.jmx') && !entry.name.contains('.bak') && !entry.name.startsWith('.') && !entry.name.startsWith('debug_') // 自动跳过标记为debug的临时脚本 }.collect { entry -> // 生成和旧硬编码完全一致的相对路径格式,无兼容性问题 return "${targetFolderRelPath}/${entry.name}" } // 按文件名字典序排序,匹配脚本的编号执行顺序 scriptList.sort() // 空列表校验 if (scriptList.size() == 0) { error "执行终止:文件夹 ${targetFolderRelPath} 下未找到有效可执行的JMX脚本" } // 打印扫描结果,方便流水线日志排查 echo "已从文件夹 ${targetFolderRelPath} 识别到 ${scriptList.size()} 个有效脚本,执行列表:\n${scriptList.join('\n')}" return scriptList }
2. 流水线调用替换
原来需要硬编码脚本列表的stage,直接替换为扫描方法调用,仅需传入目标文件夹路径即可:
pipeline { agent any stages { stage('批量执行性能测试') { steps { // 原来硬编码列表的位置,直接调用扫描方法 def targetScripts = scanJmxByFolder("perf-scripts/1") script { // 沿用原有已经写好的JMeter执行逻辑,无需调整 targetScripts.each { scriptPath -> def scriptName = scriptPath.tokenize('/').last() sh """ jmeter -n -t ${scriptPath} \ -l test-results/${scriptName}.jtl \ -e -o test-results/report/${scriptName} """ } } } } } }
最佳实践优化
- 把目标文件夹路径做成流水线参数化选项,无需修改Jenkinsfile即可切换测试范围:
调用时直接传入参数值即可:// 加到pipeline块最上方 parameters { choice( name: 'TARGET_FOLDER', choices: ['perf-scripts/1', 'perf-scripts/2', 'perf-scripts/3'], description: '选择本次要执行的性能测试脚本所属文件夹' ) }def targetScripts = scanJmxByFolder(params.TARGET_FOLDER) - 针对150+脚本的批量执行场景,可对扫描得到的脚本列表做分组,配合Jenkins的并行执行能力,控制单节点资源占用,避免所有脚本串行等待的低效率问题
- 过滤规则可自定义扩展,比如按脚本文件名的前缀匹配需要执行的子集,不用改动目录结构
- 不要通过shell通配符拼接命令的方式(比如
sh "ls ${folder}/*.jmx")获取脚本列表,遇到带空格的文件名会导致命令解析错误,Groovy原生的File遍历方式跨Windows/Linux节点通用,稳定性更高
常见问题规避
- 如果Groovy沙箱拦截了文件遍历操作,仅需对
File类的基础方法做一次白名单审批即可,无额外安全风险 - 扫描逻辑中已加
isFile()判断,不会递归读取子目录中的脚本,严格匹配“仅扫描当前指定文件夹下的脚本”的需求 - 所有返回的脚本路径格式和原硬编码完全一致,原有JMeter执行、结果上报、报告生成的逻辑不需要做任何改动
内容的提问来源于stack exchange,提问作者Anie
相关产品推荐
相关产品推荐

