资讯动态

基于Agent与大模型的JMeter性能测试脚本自动化生成实践

发布时间:2026/9/20 17:21:40 来源:尧图企业网站定制
1. 性能测试脚本自动化生成的背景与核心思路性能测试脚本的编写长期处在一个尴尬的位置它技术含量不低但重复度极高。一个中等规模的系统接口动辄上百个每个接口都要构造请求、提取关联参数、设置断言、配置线程组和监听器。纯手工写JMeter脚本一个熟练的测试工程师一天能产出十五到二十个接口的脚本就算不错了而且一旦接口定义变更维护成本几乎等于重写。这个项目要解决的核心问题就是能不能让机器去干那些重复的、有固定模式的脚本编写工作人只负责审核和调优。我最初的想法很朴素——用模板引擎批量生成JMX文件。试了一段时间发现模板方案对接口结构的规整度要求太高稍微遇到嵌套JSON、动态签名、文件上传这类场景模板就写不下去了。后来转向大模型方案让模型理解接口文档直接输出JMeter的JMX结构。这个思路可行但纯靠大模型一次性生成整个脚本错误率很高尤其是元件之间的引用关系经常搞错。最终落地的方案是Agent加大模型的分工协作Agent负责流程编排、工具调用和结果校验大模型负责语义理解和代码片段生成。两者结合既发挥了大模型对自然语言接口文档的理解能力又通过Agent的确定性逻辑保证了生成结果的可靠性。这个实践适合几类人参考一是手里维护着大量JMeter脚本、被维护成本困扰的测试工程师二是正在探索Agent落地场景、想找一个有明确输入输出边界的项目的开发者三是对大模型应用感兴趣、想了解如何把模型能力嵌入到具体工程流程里的技术管理者。不管你是哪种角色下面的内容都会从设计思路到实操细节完整展开你可以直接参考复现。2. 整体架构设计与技术选型考量2.1 为什么选择Agent加JMeter的组合JMeter作为性能测试工具它的脚本文件JMX本质上是一个XML文档结构清晰、元件类型固定、属性命名规范。这意味着它非常适合作为大模型的生成目标——模型不需要发明新的语法只需要按照既有的XML结构去填充内容。相比让模型直接生成Python压测脚本或者Gatling的Scala代码JMX的容错空间更大因为即使模型生成的某个属性值有偏差只要XML结构正确JMeter仍然能加载脚本后续人工修正的成本很低。Agent在这个架构里的角色是“调度员加质检员”。它不直接生成脚本内容而是负责几件事第一解析接口文档把非结构化的描述拆解成结构化的接口清单第二为每个接口调用大模型生成对应的JMeter元件片段第三校验生成片段之间的引用关系是否正确比如正则提取器的变量名是否和后续请求的参数名匹配第四把校验通过的片段组装成完整的JMX文件。这种分工的好处是大模型只负责它擅长的语义理解部分而流程控制、依赖检查这些确定性任务交给Agent的代码逻辑来处理避免了让模型去做它不擅长的事情。2.2 大模型选型与部署方式大模型的选择上我实测下来有几个方案可以参考。如果团队有GPU资源本地部署开源模型是首选推荐用vLLM做推理加速模型方面Qwen2.5-14B-Instruct或者DeepSeek-Coder-V2-Lite都是不错的选择前者对中文接口文档的理解更好后者在代码生成任务上表现更稳。如果不想折腾部署直接用云端API也可以但要注意接口文档里可能包含内部系统信息需要做脱敏处理。本地部署的具体配置我用的是单卡A100 40GvLLM启动命令大致如下python -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-14B-Instruct \ --tensor-parallel-size 1 \ --max-model-len 8192 \ --gpu-memory-utilization 0.85 \ --port 8000这里有几个参数值得说明。max-model-len设为8192是因为接口文档加上生成的JMX片段token消耗比较大设太小会导致截断。gpu-memory-utilization设0.85是留出显存给KV Cache的动态增长设太高容易OOM。如果你用的是消费级显卡可以考虑用Ollama部署量化版本7B级别的模型在脚本生成任务上也能用只是复杂接口的准确率会下降一些。2.3 Agent框架的选择与核心模块划分Agent框架我用的是LangChain加自定义Tool的组合。LangChain的好处是生态成熟各种文档加载器、输出解析器开箱即用自定义Tool则是为了处理JMeter特有的逻辑比如JMX片段的校验、变量引用的检查等。整个Agent划分为四个核心模块文档解析模块接收Swagger/OpenAPI文档或者Markdown格式的接口说明输出结构化的接口列表每个接口包含路径、方法、请求头、请求体、响应示例等字段。脚本生成模块对每个接口调用大模型生成对应的HTTP Sampler、Header Manager、断言、提取器等JMeter元件。依赖校验模块检查接口之间的参数传递关系确保提取器生成的变量被后续请求正确引用。组装输出模块把所有元件按照JMeter的XML规范组装成完整的JMX文件并做基本的格式校验。这种模块化设计的好处是每个部分可以独立测试和替换。比如文档解析模块今天用Swagger明天换成YApi的导出格式只需要改这一个模块其他部分不受影响。3. 核心细节解析与实操要点3.1 接口文档的结构化解析接口文档的质量直接决定了后续生成脚本的准确率。我处理过的文档大概分三类Swagger/OpenAPI标准文档、YApi导出的JSON、以及手写的Markdown表格。Swagger最好处理因为字段定义明确直接用Python的json库解析就行。YApi的导出格式和Swagger类似但字段命名有差异需要做一层映射。最麻烦的是手写Markdown格式不统一需要先用大模型做一轮结构化提取。以Swagger为例解析的核心代码如下import json def parse_swagger(file_path): with open(file_path, r, encodingutf-8) as f: spec json.load(f) interfaces [] base_url spec.get(servers, [{}])[0].get(url, ) for path, methods in spec.get(paths, {}).items(): for method, detail in methods.items(): if method not in [get, post, put, delete]: continue interface { path: path, method: method.upper(), base_url: base_url, summary: detail.get(summary, ), parameters: detail.get(parameters, []), request_body: detail.get(requestBody, {}), responses: detail.get(responses, {}) } interfaces.append(interface) return interfaces这段代码的关键在于提取base_url和每个接口的完整路径。很多新手会忽略servers字段导致生成的JMeter脚本里HTTP Request的路径不完整。另外要注意Swagger里parameters和requestBody是分开的GET请求的参数在parameters里POST请求的body在requestBody里生成JMeter元件时需要分别处理。注意如果接口文档里有文件上传的接口requestBody的content-type会是multipart/form-data这种接口在JMeter里需要用HTTP Request的“Files Upload”面板来配置不能简单地用参数传递。我在第一次处理这类接口时没注意生成的脚本一直报400错误排查了半天才发现是文件上传的配置方式不对。3.2 大模型生成JMeter元件的提示词设计提示词的质量决定了模型输出的稳定性。我试过几种不同的提示词结构最终稳定下来的版本包含四个部分角色设定、任务描述、输出格式约束、示例参考。角色设定让模型知道自己是JMeter专家任务描述说清楚要生成什么元件输出格式约束用XML Schema的方式限定结构示例参考给一个完整的输入输出对。具体的提示词模板如下你是一名JMeter脚本生成专家。根据以下接口信息生成对应的JMeter HTTP Sampler元件。 接口信息 - 路径{path} - 方法{method} - 请求头{headers} - 请求参数{params} - 请求体{body} 输出要求 1. 生成一个HTTPSamplerProxy元件包含正确的testname、path、method属性 2. 如果有请求头生成HeaderManager元件 3. 如果有JSON请求体生成对应的参数配置 4. 输出格式为合法的XML片段不要包含其他解释文字 示例 输入路径/api/login方法POST请求体{username:test,password:123456} 输出 HTTPSamplerProxy guiclassHttpTestSampleGui testclassHTTPSamplerProxy testnamelogin enabledtrue stringProp nameHTTPSampler.path/api/login/stringProp stringProp nameHTTPSampler.methodPOST/stringProp boolProp nameHTTPSampler.postBodyRawtrue/boolProp elementProp nameHTTPsampler.Arguments elementTypeArguments collectionProp nameArguments.arguments elementProp name elementTypeHTTPArgument boolProp nameHTTPArgument.always_encodefalse/boolProp stringProp nameArgument.value{username:test,password:123456}/stringProp stringProp nameArgument.metadata/stringProp /elementProp /collectionProp /elementProp /HTTPSamplerProxy这个提示词里最关键的约束是“输出格式为合法的XML片段不要包含其他解释文字”。如果不加这一句模型经常会在XML前后加上“好的以下是生成的脚本”之类的废话导致后续解析失败。另外示例的选择也很重要我特意选了一个POST请求带JSON body的例子因为这是最常见的场景模型看到示例后对类似结构的生成准确率明显提升。3.3 参数关联与变量提取的处理性能测试脚本里最复杂的部分就是参数关联。比如登录接口返回的token需要提取出来作为后续接口的请求头列表接口返回的ID需要提取出来作为详情接口的路径参数。这部分如果让大模型直接生成它经常会把变量名搞混或者忘记在后续请求里引用。我的做法是让Agent先分析接口之间的依赖关系生成一个依赖图然后按照依赖顺序逐个生成脚本片段。依赖关系的识别靠的是接口文档里的字段匹配——如果接口A的响应示例里有一个字段叫token接口B的请求头里有一个参数也叫token那它们之间就存在依赖关系。识别到依赖关系后Agent会做两件事第一在接口A的脚本片段里插入一个JSON Extractor元件提取token字段到变量${token}第二在接口B的脚本片段里把请求头的值设为${token}。JSON Extractor的配置如下JSONPostProcessor guiclassJSONPostProcessorGui testclassJSONPostProcessor testnameextract_token enabledtrue stringProp nameJSONPostProcessor.referenceNamestoken/stringProp stringProp nameJSONPostProcessor.jsonPathExprs$.data.token/stringProp stringProp nameJSONPostProcessor.match_numbers1/stringProp stringProp nameJSONPostProcessor.defaultValuesNOT_FOUND/stringProp /JSONPostProcessor这里jsonPathExprs的写法需要根据实际的响应结构来调整。如果响应是{code:0,data:{token:abc}}那路径就是$.data.token如果响应是{token:abc}路径就是$.token。我遇到过一种情况响应里token字段在数组里路径要写成$.data[0].token这种细节模型有时候会搞错需要Agent在生成后做一轮校验。提示JSON Extractor的defaultValues建议设为NOT_FOUND而不是留空。这样当提取失败时后续请求会带着NOT_FOUND去发你能在结果树里一眼看出是哪个接口的提取出了问题比空值好排查得多。4. 完整实操流程与关键环节实现4.1 环境准备与依赖安装整个项目的运行环境需要Python 3.10以上、JMeter 5.6以上、以及一个大模型服务。Python依赖主要包括langchain、openai用于调用兼容OpenAI接口的本地模型、lxml用于XML解析和校验、requests用于接口文档的获取。安装命令如下pip install langchain openai lxml requestsJMeter的安装比较简单从官网下载二进制包解压即可。需要注意的是JMeter的运行需要Java 8以上环境建议用Java 17性能和兼容性都更好。安装完成后把JMeter的bin目录加到系统PATH里方便后续用命令行调用。大模型服务这边如果用的是vLLM本地部署启动后默认监听8000端口接口格式兼容OpenAI。在代码里这样初始化客户端from openai import OpenAI client OpenAI( base_urlhttp://localhost:8000/v1, api_keynot-needed )api_key随便填一个非空字符串就行vLLM默认不校验。如果你用的是其他推理框架只要接口兼容OpenAI格式改一下base_url即可。4.2 从接口文档到JMX文件的完整流程整个流程分五步走。第一步读取接口文档调用parse_swagger函数得到结构化的接口列表。第二步遍历接口列表对每个接口构造提示词调用大模型生成JMeter元件片段。第三步分析接口间的依赖关系在相应的片段里插入提取器和变量引用。第四步把所有片段按照JMeter的JMX规范组装成完整的测试计划。第五步用JMeter的命令行模式做一次空跑校验确认脚本能正常加载。第三步的依赖分析是整个过程里最需要仔细处理的地方。我的做法是维护一个变量池记录每个接口能提取出哪些变量以及每个接口需要消费哪些变量。遍历接口列表时先检查当前接口需要的变量是否已经在变量池里如果在就把对应的参数值替换成${变量名}如果不在就跳过这个接口等后续轮次再处理。这样多轮遍历下来所有能解析的依赖都会被正确处理。组装JMX文件时需要注意JMeter的XML命名空间和元素层级。一个最小的JMX结构如下?xml version1.0 encodingUTF-8? jmeterTestPlan version1.2 properties5.0 jmeter5.6.3 hashTree TestPlan guiclassTestPlanGui testclassTestPlan testname自动生成测试计划 elementProp nameTestPlan.user_defined_variables elementTypeArguments collectionProp nameArguments.arguments/ /elementProp /TestPlan hashTree ThreadGroup guiclassThreadGroupGui testclassThreadGroup testname线程组 stringProp nameThreadGroup.num_threads10/stringProp stringProp nameThreadGroup.ramp_time5/stringProp boolProp nameThreadGroup.schedulerfalse/boolProp /ThreadGroup hashTree !-- 这里插入各个接口的Sampler元件 -- /hashTree /hashTree /hashTree /jmeterTestPlan每个Sampler元件都必须放在hashTree里而且hashTree的层级要和元件的层级对应。这个结构如果搞错了JMeter加载时会报错。我建议在组装完成后用lxml做一次XML Schema校验确保结构合法。4.3 生成结果的校验与修正大模型生成的内容不可能百分之百正确所以校验环节必不可少。我的校验分三层第一层是XML格式校验用lxml.etree.fromstring尝试解析每个片段解析失败的直接打回重生成。第二层是元件属性校验检查每个Sampler是否包含必需的path和method属性HeaderManager的header字段是否完整。第三层是引用校验检查所有${变量名}形式的引用是否在变量池里有对应的提取器。第三层校验最容易发现问题。我遇到过模型生成的脚本里引用了${userId}但整个脚本里没有任何地方提取过这个变量。这种情况要么是模型幻觉要么是接口文档里确实没有定义这个参数的来源。Agent会把这类问题记录下来生成一份校验报告人工确认后再决定是补充提取逻辑还是修正引用。校验报告的格式如下接口路径问题类型问题描述建议处理/api/user/detail引用缺失引用了${userId}但无提取器检查是否需要从前置接口提取/api/order/list属性缺失缺少method属性根据文档补全为GET/api/login格式错误XML解析失败重新生成这份报告在实际使用中非常有用它把人工审核的焦点从“逐行检查脚本”变成了“确认问题列表”效率提升很明显。4.4 批量生成与增量更新实际项目里接口不是一次性全部定义好的而是分批上线。所以脚本生成也需要支持增量更新。我的做法是维护一个接口指纹库每个接口用“路径加方法”作为唯一标识记录它上次生成时的文档版本。每次运行生成流程时先对比指纹库只对新增的或者文档有变更的接口重新生成脚本片段未变更的接口直接复用已有片段。增量更新的实现依赖一个简单的哈希对比import hashlib def get_interface_fingerprint(interface): content f{interface[method]}:{interface[path]}:{str(interface[parameters])}:{str(interface[request_body])} return hashlib.md5(content.encode()).hexdigest()每次生成前计算当前接口的指纹和指纹库里存储的对比。不一致的才触发重新生成。这个机制在接口数量多、变更频繁的项目里能省下大量时间。我负责的一个项目有三百多个接口全量生成一次大概要二十分钟用了增量更新后日常变更只需要两三分钟就能完成。5. 常见问题与排查技巧实录5.1 模型生成内容不稳定怎么办这是最常见的问题。同一个接口两次生成的结果可能不一样有时候XML结构正确有时候就缺了某个属性。根本原因是大模型的输出本身带有随机性temperature参数设得越高越明显。我的经验是把temperature设到0.1到0.3之间既能保持一定的灵活性又不至于太发散。另外在提示词里加一句“请严格按照示例的XML结构输出不要省略任何属性”也能明显提升稳定性。如果调整参数后还是不稳定可以考虑用Few-shot的方式在提示词里放两到三个完整的输入输出示例覆盖GET、POST、文件上传等不同场景。模型看到更多示例后对输出格式的把握会更好。我实测下来加了三个示例后一次生成通过率从百分之六十左右提升到了百分之八十五以上。5.2 JMX文件加载报错怎么排查JMeter加载JMX报错原因通常集中在几个地方。一是XML结构不合法比如标签没有闭合、属性值没有加引号。这种情况用lxml解析一下就能定位到具体行号。二是元件层级错误比如把Sampler直接放在了jmeterTestPlan下面而不是hashTree里面。三是属性名拼写错误比如把HTTPSampler.path写成了HTTPSampler.PathJMeter对属性名大小写敏感。排查的时候我习惯先用JMeter的GUI模式打开JMX文件如果GUI能正常加载说明结构没问题如果GUI报错错误信息里通常会指出具体的元素和属性。另外一个技巧是用xmllint命令做格式校验xmllint --noout test_plan.jmx这个命令会输出XML的语法错误比JMeter的报错信息更详细。5.3 参数关联提取不到值怎么处理参数关联失败的表现是后续请求返回401或者参数校验错误。排查步骤分三步第一在JMeter的结果树里查看前置接口的响应内容确认要提取的字段确实存在第二检查JSON Extractor的JSON Path表达式是否正确可以用在线的JSON Path测试工具验证第三检查提取器的作用域如果提取器放在了错误的层级比如放在了Thread Group下面而不是Sampler下面它就不会生效。我踩过的一个坑是JSON Extractor的match_numbers设成了0导致提取不到任何值。这个参数的含义是“取第几个匹配项”设0表示随机取一个设1表示取第一个设-1表示取全部。大部分场景下设1就行如果你不确定设1比设0更可控。5.4 常见问题速查表问题现象可能原因排查方法解决方案JMX加载失败XML格式错误xmllint校验修复XML语法请求返回401token未提取或未引用查看结果树响应检查提取器和引用请求返回400请求体格式错误对比接口文档修正Content-Type和body提取器不生效作用域错误检查元件层级调整提取器位置生成内容缺属性模型输出不稳定对比多次生成结果降低temperature加示例文件上传失败配置方式错误检查Files Upload面板用multipart配置提示如果你在生成脚本时遇到了上面没列出的问题可以先检查接口文档本身是否完整。我遇到过好几次排查了半天发现是文档里漏写了某个必填的请求头模型自然也就生成不出来。6. 实操心得与后续扩展方向这套方案跑通之后我在三个项目里做了实际应用累计生成了超过八百个接口的JMeter脚本。最直观的感受是脚本编写的时间从原来的平均每个接口十五分钟压缩到了三分钟左右而且这三分子里大部分时间花在审核和微调上纯粹的重复劳动基本消失了。当然它也不是万能的对于那种请求体结构极其复杂、包含多层嵌套和动态签名的接口模型生成的准确率会明显下降还是需要人工介入。后续可以扩展的方向有几个。一是把断言生成也纳入自动化范围目前断言还是手工配置的可以根据接口文档里的响应示例自动生成JSON断言和响应码断言。二是接入CI流程每次接口文档更新后自动触发脚本重新生成和冒烟测试形成闭环。三是把生成结果和JMeter的分布式压测配置结合起来自动生成master-slave的配置文件和启动脚本。最后分享一个我在使用中总结的小技巧在提示词里加上“如果接口信息不完整请在生成的XML中用注释标注缺失的字段”这样模型遇到信息不足的情况时不会瞎编而是明确告诉你哪里缺信息。这个改动让校验环节的效率又提升了一截因为问题从“脚本跑不通”变成了“注释里写了缺什么”排查方向清晰多了。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价