先说说这次实战的背景。最近在测试团队内部尝试把大模型接入日常流程,最早只是想解放一部分写用例的时间,后来发现 LangChain 在串联“需求理解—用例设计—结果分析”这条链路上比想象中顺手。调研了目前各家用 AI 辅助测试的方案之后,决定自己搭一个基于 LangChain 的 Agent 原型,把测试用例生成、接口测试脚本生成、性能测试结果分析报告输出这几个高频场景全部串起来。动手之后才发现,LangChain 真正值钱的地方不只是“能调用模型”,而是它能把工具调用、上下文管理、多步骤执行这些逻辑组织成一个稳定的框架,帮助我们把测试工作的结构化思维固化到代码里。
本文将围绕这套测试用例生成 Agent 的设计思路与完整实现展开,从环境准备、核心链路拆解、关键代码示例、运行效果到常见排错、工程化落地建议,一次讲清楚。如果你对 LangChain Agent 开发、AI 测试提效、测试用例自动化生成、性能测试报告自动输出这几个方向感兴趣,这篇文章应该能给你一套可以直接参考的完整方案。
1. 为什么我们要自研一个测试用例生成 Agent
1.1 AI 测试常见的痛点
传统测试用例设计高度依赖测试工程师的个人经验和业务熟悉度,新人写出来的用例经常覆盖不全,老手写用例质量虽高但耗时很长。引入 AI 辅助之后,最常见的做法是把需求描述扔给 ChatGPT,让它“帮我写测试用例”,然后复制粘贴到 Excel。这样做确实快,但问题也很明显:
- 上下文太短,模型只能根据一段孤立的需求文本生成用例,缺少对项目背景、接口数据结构、历史缺陷信息的理解。
- 输出不稳定,换一个 Prompt 表述,结果差异很大。
- 后续无法自动化,生成的结果是自然语言文本,没有结构化的 JSON 或测试步骤,不能直接接入测试管理平台。
- 多样例之间用例重复率高、优先级设计不合理,边界条件经常漏。
这些痛点的根源在于:大模型本质上是一个“文本生成器”,它不具备主动查询接口定义、分析历史缺陷、检查数据库字段这些能力。如果想要 AI 真正辅助测试,就需要给它装上“手和眼睛”,让它能够调用工具、访问外部数据源,并按测试设计的逻辑一步步执行。这正好是 LangChain Agent 擅长的领域。
1.2 LangChain Agent 能做什么
LangChain 是一个面向大语言模型应用的开发框架,核心抽象包括模型封装、Prompt 管理、记忆、工具调用、Agent 编排。在测试场景里,我们可以把 Agent 理解为“一个会使用工具的 AI 助手”,它不仅能回答问题,还能按照你设定的流程去执行任务。
对于测试用例生成这个场景,Agent 可以做以下几件事:
- 接收输入的需求描述,自动理解业务功能点。
- 调用接口文档解析工具,拉取真实的请求参数、响应字段、边界约束。
- 调用历史缺陷查询工具,找到过去容易出问题的模块和场景。
- 按照等价类划分、边界值分析、场景法等测试设计方法生成用例。
- 对生成的用例进行去重、补充、排序,输出结构化 JSON。
- 将结果以指定格式写入测试管理平台或导出为文件。
这已经不是简单的“套 Prompt”,而是一套可以复用的测试辅助工具。多个 Agent 组合使用,还能完成从需求解析、用例生成、脚本编写到性能报告输出的完整链路。
1.3 为什么选择 LangChain 而不是直接调 API
可能有同学会问,直接写代码调用大模型 API 不也能完成吗?为什么还要引入 LangChain?
直接调用 API 的方式适合一次性脚本,但一旦我们要实现“多步骤任务、工具选择、记忆保持、结果结构化输出”,就会发现自己重写一套框架非常繁琐。LangChain 提供了几个非常省事的能力:
- 标准化的模型调用接口,切换模型厂商时只需改少量配置。
- 内置 Agent 执行框架,支持 ReAct、Plan-and-Execute 等常见 Agent 模式。
- 丰富的工具集成,也可以自定义函数作为 Tool。
- 输出解析器,可以强制模型按指定 JSON 结构输出。
- 消息记忆机制,多轮交互中保持上下文。
更重要的是,LangChain 的生态足够大,网上资料多,团队成员接手成本低。如果你只是做几个 demo,直接调 API 没问题;但如果你要搭建一套可持续维护的 AI 测试基础设施,LangChain 这类框架可以帮你省下不少基建代码。
这里也顺便解答一个经常被问到的问题:LangChain 和 LangGraph 有什么区别?
简单来说,LangChain 提供了 Agent 的基础能力,适合流程相对简单、步骤不固定的场景;LangGraph 是 LangChain 团队推出的更底层的编排框架,适合需要精确控制状态流转、支持循环分支、可观测性要求较高的复杂 Agent 应用。用测试业务来类比:LangChain 像是“用例执行引擎”,LangGraph 则像“测试流程编排引擎”。对于本文中的测试用例生成 Agent,使用 LangChain 已经足够;如果后续要做跨团队的完整测试流水线,建议了解一下 LangGraph。
2. 环境准备与版本说明
2.1 基础运行环境
本文的示例代码基于 Python 3,操作系统不限,Windows、macOS、Linux 都可以跑。建议使用虚拟环境管理依赖,避免污染系统 Python。
需要安装的核心依赖如下:
pip install langchain pip install langchain-openai pip install langchain-community pip install openai pip install pandas pip install pydantic版本方面,LangChain 目前迭代速度较快,API 变化也比较大。本文示例基于 0.1.x 到 0.2.x 之间的常见 API 编写。在动手之前,建议先执行下列命令确认当前环境版本:
python --version pip show langchain pip show langchain-openai如果发现安装了更高版本导致 API 不兼容,有两种处理方式:一是按官方文档迁移到新写法;二是固定版本安装,例如pip install langchain==0.2.16。生产的项目建议锁版本。
2.2 模型选择说明
在示例代码中,默认使用 OpenAI 兼容接口,通过环境变量配置 API Key。如果你使用的是国内大模型服务商提供的 OpenAI 兼容网关,通常只需要修改base_url和api_key两个配置项,不需要改动业务逻辑。
这里需要特别说明的是,大模型的能力直接影响测试用例生成质量。在实际项目落地时,建议根据业务安全要求来选择模型部署方式。涉及敏感数据的项目,优先使用私有化部署模型;一般业务场景,可以使用云服务。无论选择哪种模型,都要在测试环境充分验证生成结果,并保留人工审核环节。
配置环境变量示例:
export OPENAI_API_KEY="sk-xxxxxxxxxxxx" export OPENAI_BASE_URL="https://api.xxx.com/v1"在 Windows PowerShell 下可以写成:
$env:OPENAI_API_KEY="sk-xxxxxxxxxxxx" $env:OPENAI_BASE_URL="https://api.xxx.com/v1"2.3 项目整体结构
为了方便管理,我们新建一个名为ai_test_agent的项目目录:
ai_test_agent/ ├── requirements.txt ├── .env ├── agents/ │ ├── __init__.py │ ├── requirement_agent.py │ ├── testcase_agent.py │ └── perf_agent.py ├── tools/ │ ├── __init__.py │ ├── api_schema_tool.py │ └── history_bug_tool.py ├── models/ │ ├── __init__.py │ ├── testcase_schema.py │ └── perf_report_schema.py ├── output/ │ ├── testcases/ │ └── reports/ ├── main.py └── utils.py目录职责说明:
agents/存放不同的 Agent 定义。tools/存放自定义工具,例如接口文档解析工具、历史缺陷查询工具。models/存放输出数据模型,也就是我们期望大模型输出的结构化 JSON 结构。output/存放生成的测试用例文件和测试报告。main.py是主入口,负责串联整个流程。
3. 测试用例生成 Agent 的核心设计
3.1 整体流程设计
在开始写代码之前,先梳理一下整个 Agent 的工作流程。我们的目标是从一段需求描述出发,自动生成一份结构化的测试用例集。
流程可以拆成以下步骤:
第一步:需求解析
Agent 先读取需求描述,提取出功能模块、用户角色、核心业务流程、业务规则、输入输出等关键信息。如果需求文本中提到了接口,就调用接口文档解析工具,获取接口的请求参数和响应字段。
第二步:测试点提取
基于需求解析结果,Agent 按照功能列表和业务规则生成测试点。例如一个登录功能,测试点可能包括:正确用户名密码登录、错误密码登录、账号不存在、密码为空、账号被锁定、验证码过期、并发登录等。
第三步:测试用例生成
对每个测试点,Agent 按照测试设计方法来补充用例详情,包括前置条件、测试步骤、输入数据、预期结果、优先级、用例类型。
第四步:用例规则套用与去重
Agent 套用用例规范规则,从覆盖度、重复度、边界条件、异常场景几个维度对生成结果进行优化。这里可以调用一个“测试用例规范检查工具”,自动把不满足要求的用例打回重写。
第五步:结构化输出
最终结果通过输出解析器转换成 JSON 格式,写入文件。
3.2 Agent 输入输出设计
为了让 Agent 的生成结果稳定、可复用,建议先定义好输入和输出的数据结构。
输入需求描述示例:
{ "requirement_id": "REQ-2025-001", "title": "用户登录功能", "description": "用户通过手机号和密码登录系统,登录成功后跳转到首页。密码连续错误5次后账号锁定30分钟。支持记住密码功能。", "related_api": [ { "name": "POST /api/login", "method": "POST", "request_params": "phone: string, password: string, remember: boolean", "response": "{ code: 0, message: 'success', data: { token: string } }" } ], "priority": "P0" }输出测试用例结构示例:
{ "requirement_id": "REQ-2025-001", "test_cases": [ { "case_id": "TC-001", "case_title": "正确手机号和密码登录成功", "precondition": "已注册用户,手机号13800000000,密码正确", "steps": [ "打开登录页面", "输入手机号13800000000", "输入正确密码", "点击登录按钮" ], "test_data": { "phone": "13800000000", "password": "correct_password" }, "expected_result": "登录成功,跳转首页,右上角显示用户名", "case_type": "功能测试", "priority": "P0" } ] }定义好结构之后,在代码中使用 Pydantic 模型来约束输出格式,这样大模型生成的结果即使缺少某些字段,也会被解析器修正。
3.3 核心工具设计
为了让 Agent 具备“动手能力”,我们需要自定义几个工具。
接口文档解析工具
很多测试项目中接口信息散落在 YAPI、Swagger 或者文档页面里。我们可以写一个工具函数,接收一个接口名称,返回该接口的详细信息。在实际演示中,先用一个 mock 字典代替。
历史缺陷工具
这个工具用于查询历史缺陷,帮助 Agent 在生成用例时重点关注曾出现问题的场景。比如某模块历史缺陷中“金额为0时前端校验通过但后端报错”的频率很高,那 Agent 在生成用例时会自动补充这个边界场景。
from langchain_core.tools import tool @tool def get_history_bug_count(module_name: str) -> str: """ 查询指定模块的历史缺陷数量与高频缺陷类型。 module_name: 模块名称,例如 '登录'、'支付' """ bug_db = { "登录": "历史缺陷共15个,高频类型:验证码过期、账号锁定逻辑错误、密码错误提示不明确", "支付": "历史缺陷共32个,高频类型:金额为0未拦截、重复支付、并发扣款超扣、回调顺序异常", "订单": "历史缺陷共28个,高频类型:订单状态流转错误、超时未关闭、分页丢失条件" } return bug_db.get(module_name, "暂未发现历史缺陷数据")这里只是示例,真实项目中可以将查询逻辑换成数据库查询或接口调用。关键点在于:工具函数最好带有清晰的 docstring,因为 LangChain 会把函数名称和介绍一并发送给模型,模型根据这个描述来判断何时调用该工具。
4. 完整实战:搭建测试用例生成 Agent
4.1 创建项目结构和安装依赖
先创建项目目录和虚拟环境:
mkdir ai_test_agent cd ai_test_agent python -m venv venv source venv/bin/activate # Windows 下使用 venv\Scripts\activate创建requirements.txt文件:
langchain>=0.1.0,<0.3.0 langchain-openai>=0.1.0 langchain-community>=0.2.0 openai>=1.0.0 pandas>=2.0.0 pydantic>=2.0.0 python-dotenv>=1.0.0安装依赖:
pip install -r requirements.txt4.2 自定义工具实现
创建tools/api_schema_tool.py,实现接口文档解析工具。这里先使用 mock 数据,演示如何定义 Tool。实际项目中,你可以替换为读取 YAPI 接口文档或数据库配置。
# 文件路径:tools/api_schema_tool.py from langchain_core.tools import tool @tool def get_api_schema(api_name: str) -> str: """ 根据接口名称查询接口的请求参数和响应结构。 api_name: 接口名称,例如 'login'、'create_order' """ api_docs = { "login": { "name": "POST /api/login", "method": "POST", "request_params": { "phone": "string, 手机号, 11位", "password": "string, 密码, 6-20位字母数字", "remember": "boolean, 是否记住密码" }, "response": { "code": "int, 0表示成功", "message": "string, 提示信息", "data": {"token": "string, 登录凭证"} }, "constraints": [ "phone 必须为11位有效手机号", "password 长度为6-20位", "连续5次错误密码锁定账号30分钟" ] }, "create_order": { "name": "POST /api/order/create", "method": "POST", "request_params": { "user_id": "string, 用户ID", "product_id": "string, 商品ID", "quantity": "int, 购买数量, 1-99", "coupon_id": "string, 优惠券ID, 可为空" }, "response": { "code": "int, 0表示成功", "message": "string, 提示信息", "data": {"order_id": "string, 订单号"} }, "constraints": [ "quantity 必须在1-99之间", "商品必须上架", "优惠券必须属于当前用户且未被使用" ] } } api = api_docs.get(api_name) if not api: return "未找到该接口文档,请确认接口名称。" import json return json.dumps(api, ensure_ascii=False, indent=2)同样,创建tools/history_bug_tool.py:
# 文件路径:tools/history_bug_tool.py from langchain_core.tools import tool @tool def get_history_bug(module_name: str) -> str: """ 查询指定模块的历史缺陷信息,帮助测试用例设计时重点关注高频缺陷场景。 module_name: 模块名称,例如 'login'、'order'、'payment' """ bug_db = { "login": "历史缺陷15个:密码连续错误后锁定逻辑异常、验证码过期后提示不友好、手机号校验不严格", "order": "历史缺陷22个:数量边界未校验、超时订单状态未流转、批量下单并发场景数据错乱", "payment": "历史缺陷30个:订单金额为0时未拦截、重复支付回调、并发扣款超扣、退款金额大于原订单" } return bug_db.get(module_name, "该模块暂无历史缺陷数据")4.3 定义输出数据模型
创建models/testcase_schema.py:
# 文件路径:models/testcase_schema.py from typing import List, Dict from pydantic import BaseModel, Field class TestCase(BaseModel): case_id: str = Field(description="用例编号") case_title: str = Field(description="用例标题") precondition: str = Field(description="前置条件") steps: List[str] = Field(description="测试步骤") test_data: Dict = Field(description="测试数据") expected_result: str = Field(description="预期结果") case_type: str = Field(description="用例类型,如功能测试、边界测试、异常测试") priority: str = Field(description="优先级,P0/P1/P2/P3") class TestCaseList(BaseModel): requirement_id: str = Field(description="需求编号") requirement_title: str = Field(description="需求标题") test_cases: List[TestCase] = Field(description="测试用例列表")这样做的目的是给大模型的输出加上一层约束,LangChain 会结合 Pydantic 模型生成JSON Schema,要求大模型输出的字段必须符合这个结构。
4.4 测试用例生成 Agent 实现
创建agents/testcase_agent.py。这个 Agent 是整个系统的核心,也是代码量最大的部分。
# 文件路径:agents/testcase_agent.py import json from typing import Any, Dict from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain.agents import AgentExecutor, create_openai_tools_agent from langchain_core.output_parsers import PydanticOutputParser from tools.api_schema_tool import get_api_schema from tools.history_bug_tool import get_history_bug from models.testcase_schema import TestCaseList class TestcaseGenerateAgent: def __init__(self, model_name: str = "gpt-4o", temperature: float = 0.2): self.llm = ChatOpenAI( model=model_name, temperature=temperature ) self.parser = PydanticOutputParser(pydantic_object=TestCaseList) self.tools = [get_api_schema, get_history_bug] self.prompt = ChatPromptTemplate.from_messages([ ("system", """ 你是一名资深测试工程师,擅长测试用例设计。 你的任务是根据需求描述,借助可用工具,生成一份完整、专业、可直接执行的测试用例集合。 要求如下: 1. 如果需求中涉及接口,必须调用 get_api_schema 工具获取接口定义,基于真实参数设计用例。 2. 必须调用 get_history_bug 工具查询相关模块历史缺陷,补充对应的高风险场景。 3. 测试用例必须覆盖:正常功能、边界值、异常场景、权限/安全、兼容性等维度。 4. 每个用例包含:用例编号、标题、前置条件、步骤、测试数据、预期结果、用例类型、优先级。 5. 生成结果必须符合指定 JSON 结构。 {format_instructions} """), ("human", "需求描述:\n{requirement_text}"), MessagesPlaceholder(variable_name="agent_scratchpad"), ]).partial(format_instructions=self.parser.get_format_instructions()) def build_agent(self) -> AgentExecutor: agent = create_openai_tools_agent( llm=self.llm, tools=self.tools, prompt=self.prompt ) executor = AgentExecutor( agent=agent, tools=self.tools, verbose=True, handle_parsing_errors=True ) return executor def generate(self, requirement_text: str) -> Dict[str, Any]: executor = self.build_agent() result = executor.invoke({ "requirement_text": requirement_text }) # 输出解析为结构化数据 parsed = self.parser.invoke(result["output"]) return parsed.dict()4.5 调用示例与运行
创建一个main.py,只保留最核心的调用逻辑:
# 文件路径:main.py import json from agents.testcase_agent import TestcaseGenerateAgent if __name__ == "__main__": requirement_text = """ 需求编号:REQ-2025-001 需求名称:用户登录功能 需求描述:用户通过手机号和密码登录系统,登录成功后跳转到首页。 密码连续错误5次后账号锁定30分钟。支持记住密码功能。 涉及接口:login """ agent = TestcaseGenerateAgent(model_name="gpt-4o") result = agent.generate(requirement_text) with open("output/testcases/testcase_REQ-2025-001.json", "w", encoding="utf-8") as f: json.dump(result, f, ensure_ascii=False, indent=2) print("========== 生成结果 ==========") for tc in result["test_cases"]: print(f"{tc['case_id']} | {tc['case_title']} | {tc['priority']}")运行前确保output/testcases目录存在:
mkdir -p output/testcases python main.py运行后,预期输出类似:
========== 生成结果 ========== TC-001 | 正确手机号和密码登录成功 | P0 TC-002 | 手机号格式不正确 | P1 TC-003 | 密码错误1次,提示重新输入 | P1 TC-004 | 密码连续错误5次,账号锁定30分钟 | P0 TC-005 | 锁定期间使用正确密码登录失败 | P0 TC-006 | 记住密码功能验证 | P2 TC-007 | 登录接口响应超时 | P2同时在output/testcases/testcase_REQ-2025-001.json中可以看到完整的 JSON 结构化结果。
4.6 结果说明
从结果中可以看出,Agent 已经自动完成了以下工作:
- 识别了“连续错误5次锁定”这个关键业务规则,并生成对应的正反向用例。
- 设置了 P0、P1、P2 优先级,区分核心功能和次要功能。
- 对手机号格式、密码错误次数、锁定时间等边界条件做了覆盖。
- 补充了记住密码、响应超时等容易被遗漏的非主路径测试点。
这就是把测试设计方法论“喂”给 Agent 的效果。它不是在瞎编测试步骤,而是像一个有经验的测试工程师那样,围绕功能点、边界条件、异常场景和业务规则展开用例设计。
5. 核心原理拆解与优化技巧
5.1 Prompt 设计为什么如此重要
在 Agent 应用中,Prompt 是最容易被低估的部分。同一个模型,Prompt 质量不同,生成用例的质量差异非常大。
结合测试场景,有几点经验可以参考:
- 角色限定:让模型充当“资深测试工程师”,而不是普通的“AI 助手”。角色设定的价值在于让模型调用更专业的思维方式。
- 明确输出约束:告诉模型必须覆盖功能、边界、异常等测试维度,而不是“写出你可能想到的测试场景”。
- 提供工具使用规则:明确要求模型在涉及接口时先调用 API 工具,而不是凭记忆输出。这能有效减少模型“幻觉”问题。
- 结构化要求:用 Pydantic 约束输出格式,并明确要求必须输出指定字段。
5.2 工具调用减少模型幻觉
在测试用例生成场景中,模型最容易编造的内容是接口参数和业务规则。比如它可能凭经验认为“登录密码重置后需要重新验证邮箱”,但你的业务并不需要这一步。
解决手段是让 Agent 在生成用例时强制调用接口文档工具和历史缺陷工具。工具返回的结果作为真实上下文注入到 Agent 的观测空间中,模型基于真实数据而不是训练记忆来设计用例。这比单纯依赖 Prompt 更可靠。
如果模型在推理过程中没有调用工具就直接输出,可以设置一个检查步骤,发现结果缺少接口参数字段时,将结果丢弃并重新触发生成,要求“必须调用 get_api_schema 工具后再生成”。
5.3 配置 LangChain 记忆提升多轮对话效果
如果你希望测试人员可以和 Agent 多轮对话,例如先让它生成登录模块的用例,再追问“再加几个并发登录的用例”,就需要为 Agent 配置 Memory。
在 LangChain 中,可以结合ConversationBufferMemory或MemorySaver来存储历史消息。配置方式需要结合你使用的 LangChain 版本,示例思路如下:
from langchain.memory import ConversationBufferMemory from langchain.agents import AgentExecutor memory = ConversationBufferMemory( memory_key="chat_history", return_messages=True ) executor = AgentExecutor( agent=agent, tools=self.tools, memory=memory, verbose=True )配置记忆之后,Agent 会记住之前的用例生成结果,你可以在后续对话中提出“把 TC-003 改成 P1 优先级并补充一个等价类用例”这类要求,Agent 能够理解上下文并执行修改。
注意:新版 LangChain 中 Memory API 可能有所调整,建议以官方文档为准。如果你的场景是一次性批量生成用例,不建议开启记忆,因为历史消息会占用大量 token,增加成本。
5.4 输出解析器与容错处理
在实际运行中,大模型偶尔会输出不完整的 JSON,或者字段缺失。handle_parsing_errors=True可以在解析失败时让 Agent 自动纠错并重试。另外,Pydantic 输出解析器会在字段缺失时抛错,此时 Agent 会将错误信息反馈给模型,要求它按格式重新输出。
为了提升成功率,建议在 Prompt 中明确给出 JSON 示例,而不只是依赖format_instructions。这样模型在生成时有一个更直观的参考。
6. 实战场景扩展:自动生成接口测试脚本
6.1 从测试用例到可执行脚本
如果生成的测试用例只是一份文档,价值仍然有限。更好的方案是让 Agent 继续往下走,根据接口测试用例自动生成可执行的 pytest 脚本。
设计思路如下:
- 使用另一个 Agent,输入是接口文档 JSON。
- Agent 生成一个 pytest 测试文件,包含正常场景、异常场景、边界场景的测试函数。
- 生成的脚本带有清晰的断言语句。
- 后续可直接通过 pytest 命令执行。
来看一个简化版的接口测试脚本生成 Agent:
# 文件路径:agents/api_test_script_agent.py from langchain_core.prompts import ChatPromptTemplate from langchain_openai import ChatOpenAI class ApiScriptGenerateAgent: def __init__(self, model_name="gpt-4o"): self.llm = ChatOpenAI(model=model_name, temperature=0) def generate(self, api_schema: str) -> str: prompt = ChatPromptTemplate.from_messages([ ("system", """ 你是一名测试开发工程师,请根据接口文档生成可直接运行的 pytest 测试脚本。 要求: 1. 使用 requests 库发送 HTTP 请求。 2. 覆盖正常场景、参数缺失、参数类型错误、边界值异常。 3. 使用 pytest.mark.parametrize 驱动多组测试数据。 4. 函数命名清晰,包含断言。 5. 直接输出 Python 代码,不要输出额外解释。 """), ("human", "接口文档:\n{api_schema}") ]) chain = prompt | self.llm return chain.invoke({"api_schema": api_schema}).content生成的脚本示例(预期输出):
import requests import pytest BASE_URL = "http://127.0.0.1:8000" def test_login_success(): resp = requests.post( f"{BASE_URL}/api/login", json={"phone": "13800000000", "password": "correct_password", "remember": False} ) assert resp.status_code == 200 assert resp.json()["code"] == 0 assert "token" in resp.json()["data"] @pytest.mark.parametrize("phone,password", [ ("12345", "abc123"), ("13800000000", ""), ("1380000000", "abc123"), ]) def test_login_invalid_params(phone, password): resp = requests.post( f"{BASE_URL}/api/login", json={"phone": phone, "password": password} ) assert resp.status_code == 200 assert resp.json()["code"] != 0生成脚本之后,还需要经过代码格式检查和人工审核,确认请求路径、断言逻辑符合实际项目要求。AI 生成的脚本只能作为基线,不能直接无脑用于生产。
7. 实战场景扩展:性能测试分析报告自动输出
7.1 性能测试报告生成的痛点
性能测试在测试体系中比较特殊,很多人觉得“数据太专业,报告很难写”。传统做法是先把 JMeter、LoadRunner 跑完,导出汇总数据,然后人工在 Word 或 PPT 里填表写结论。一次性能测试周期,报告撰写常常要占掉半天甚至一天的时间。
如果把性能测试结果数据交给 LangChain Agent 处理,就能自动完成以下工作:
- 读取性能测试汇总 CSV 或 JSON。
- 分析各接口的响应时间、TPS、错误率、资源使用情况。
- 对照性能需求阈值,判断是否达标。
- 输出包含结论、瓶颈分析、优化建议的 Markdown 报告。
7.2 性能数据分析 Agent 实现
创建agents/perf_agent.py:
# 文件路径:agents/perf_agent.py import json from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser class PerfAnalysisAgent: def __init__(self, model_name="gpt-4o"): self.llm = ChatOpenAI(model_name=model_name, temperature=0.2) def generate_report(self, perf_data: dict, requirement: str) -> str: prompt = ChatPromptTemplate.from_messages([ ("system", """ 你是一名资深性能测试工程师,请根据性能测试数据输出一份专业的性能测试分析报告。 报告必须包含: 1. 测试概况:测试目标、测试环境、压力策略。 2. 测试结果汇总:各接口的TPS、平均响应时间、P95响应时间、错误率。 3. 结果分析:与性能需求阈值对比,给出达标/未达标结论。 4. 瓶颈分析:根据数据判断可能存在的性能瓶颈。 5. 优化建议:给出具体可执行的优化方向。 6. 风险提示:说明本次测试的局限性。 使用 Markdown 格式输出,要求数据准确、结论明确。 """), ("human", "性能测试需求:{requirement}\n\n性能测试数据:\n{perf_data}") ]) chain = prompt | self.llm | StrOutputParser() return chain.invoke({ "requirement": requirement, "perf_data": json.dumps(perf_data, ensure_ascii=False, indent=2) })7.3 模拟性能数据演示
准备一份模拟的性能测试汇总数据:
{ "test_duration": "15min", "concurrency": 100, "apis": [ { "api_name": "POST /api/login", "tps": 245, "avg_rt": 356, "p95_rt": 720, "error_rate": 0.02, "cpu_usage": 68, "memory_usage": 72 }, { "api_name": "POST /api/order/create", "tps": 120, "avg_rt": 580, "p95_rt": 1100, "error_rate": 0.08, "cpu_usage": 85, "memory_usage": 80 }, { "api_name": "GET /api/order/list", "tps": 320, "avg_rt": 180, "p95_rt": 350, "error_rate": 0.01, "cpu_usage": 45, "memory_usage": 50 } ] }在main.py中追加调用代码:
from agents.perf_agent import PerfAnalysisAgent perf_agent = PerfAnalysisAgent(model_name="gpt-4o") report = perf_agent.generate_report( perf_data=perf_data, requirement="系统支持200并发用户,接口平均响应时间小于500ms,P95小于1000ms,错误率小于0.1%" ) with open("output/reports/perf_report.md", "w", encoding="utf-8") as f: f.write(report) print(report)生成报告的核心价值在于:Agent 不是简单复述数据,而是把“平均响应时间达标但 P95 偏高”这类深层数据规律识别出来,给出有价值的结论。例如,它可能会得出“order/create 接口 P95 为 1100ms,超出 1000ms 阈值,错误率 0.08% 接近上限,存在数据库连接池不足或慢 SQL 的嫌疑”这类分析,这个输出已经接近一位中级性能测试工程师的分析水平。
7.4 接入 JMeter 和 LoadRunner 测试结果
在实际项目中,性能测试数据通常来自 JMeter 的Summary Report或Aggregate Report导出 CSV,以及 LoadRunner 的 Analysis 报告。处理思路是:先用 Python 读取 CSV 文件并转换为 JSON 字典,再传给 Agent。
示例代码:
import pandas as pd # 读取 JMeter Aggregate Report 导出的 CSV df = pd.read_csv("jmeter_aggregate_report.csv") perf_data = { "apis": [ { "api_name": row["Label"], "samples": row["#Samples"], "avg_rt": row["Average"], "p95_rt": row["90% Line"], # 根据实际列名调整 "error_rate": row["Error %"], "tps": row["Throughput"] } for _, row in df.iterrows() ] }需要注意的是,不同版本的 JMeter 导出的列名略有差异,比如“90% Line”、“95% Line”、“Throughput”等,要以实际导出文件为准。LoadRunner 则通常需要先将 Analysis 结果导出为 Excel 或 CSV,再走同样的流程。
8. 如何让 Agent 更懂你的项目
8.1 沉淀项目专属知识和规范
测试用例生成 Agent 能不能真正落地,很大程度上取决于它是否“了解你的项目”。通用大模型知道“如何写测试用例”,但不知道你的项目叫“神策订单系统”,也不知道贵司要求“所有用例必须包含前置环境标识、数据准备 SQL、断言级别”等规范。
为了让 Agent 更懂项目,建议构建一个项目知识库,用 RAG(检索增强生成)的方式在运行时补充上下文。具体操作步骤:
- 收集项目文档:需求文档、接口文档、测试计划、历史用例、线上事故复盘文档。
- 将文档切片并向量化,存入向量数据库。
- Agent 在生成用例之前,先从知识库中检索与当前需求相关的资料片段。
- 将检索到的片段插入 Prompt 上下文,让 Agent 基于这些知识生成用例。
在 LangChain 中,可以通过RetrievalQA或create_retrieval_chain实现,也可以将检索结果封装成一个自定义工具。这里不过度展开,但需要明确一个思路:RAG 不是“标准配置”,而是项目复杂到一定程度后的必然选择。如果项目接口文档简单、业务规则清晰,直接用工具调用就足够了。
8.2 根据反馈持续迭代 Prompt
Agent 上线后,建议建立一个“生成结果反馈闭环”:
- 测试人员在使用过程中,对生成用例进行批注,标记“无用”“重复”“缺少场景”。
- 定期收集这些反馈,分析 Agent 的错误类型。
- 根据错误类型调整 Prompt,或增加工具约束。
- 将高频被修正的用例场景固化到 Prompt 中作为示例。
例如,如果 Agent 总是漏掉“金额为0”的边界用例,就可以在 Prompt 中加入一条规则:“涉及金额、数量等数值字段时,必须包含0值、负值、极大值、极小值四类边界用例。”这种迭代方式,比频繁更换模型更有效。
8.3 用 LangGraph 编排复杂流程
如果你的测试 Agent 要完成的任务链路越来越长,例如“需求解析 → 用例生成 → 测试数据准备 → 脚本生成 → 冒烟执行 → 报告输出”六步串联,且中间需要人工审批节点,建议从 LangChain Agent 切换到 LangGraph。
LangGraph 的优势在于:
- 可以精确控制每个节点的输入输出和跳转逻辑。
- 支持条件分支,例如用例评审不通过则返回修改。
- 支持全局状态管理,多个节点之间可以共享中间数据。
- 可以配合 LangSmith 做链路追踪,排查每一步的执行情况。
从 LangChain 迁移到 LangGraph 的学习成本不算特别高,核心是把原来的“Agent 一步到底”改成“节点 + 边的图结构”。对于初创团队或 POC 阶段,先用 LangChain 把流程跑通,后续再演进到 LangGraph 是性价比最高的方式。
9. 常见问题与排查思路
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| 调用 OpenAI 接口超时 | 网络不稳定或 Base URL 配置错误 | 检查环境变量,确认OPENAI_BASE_URL是否正确,尝试更换网络后重试 |
| Agent 不调用工具直接输出结果 | 工具描述不清晰或 Prompt 未强调必须调用工具 | 在 System Prompt 中明确“涉及接口必须调用 get_api_schema”,并给一个工具调用示例 |
| 生成的 JSON 解析失败 | 模型输出不完整或字段命名不匹配 | 开启handle_parsing_errors=True,同时在 Prompt 中给出 JSON 示例 |
| 生成的用例重复度高 | Prompt 没有去重要求 | 增加“删除语义重复用例”的规则,并在输出前增加去重过滤步骤 |
| 用例覆盖不到边界条件 | Prompt 缺少边界设计方法的约束 | 在 Prompt 中列出必须覆盖的边界值场景类型 |
| 性能报告结论和真实情况不符 | 数据预处理不完整或关键指标缺失 | 先检查输入数据是否包含错误率、TPS、P95 等必要指标 |
| 模型回答字数过多超出上下文 | 历史消息太长 | 使用摘要记忆替代完整记忆,或定期清空历史消息 |
| LangChain API 报错提示属性不存在 | 版本差异导致 API 变更 | 固定 LangChain 版本,查阅对应版本文档 |
| Agent 生成脚本不能运行 | 请求路径或断言与项目不符 | 生成后增加一次格式检查与人工 review 流程 |
10. AI 测试落地过程中的工程建议
10.1 安全与权限边界
在真实项目中接入 AI Agent,安全是最重要的一条线。有几个原则需要提前定好:
- 涉及生产环境的任何操作,都必须使用最小权限账号,且提前申请审批。
- 测试用例生成 Agent 只能读取内部测试环境的数据,不能访问生产数据库。
- 如果要让 Agent 操作测试管理平台,必须通过 API Token 授权,并限制 Token 的权限范围。
- 大模型生成的所有测试脚本,必须经过人工 Review 后才能执行。
- 禁止将敏感业务数据直接发送到外部模型 API,必要时采用私有化部署。
10.2 数据与结果管理
建议将 Agent 的输入输出全部记录到日志系统,方便事后审计。每一步的记录至少包含:
- 调用的模型名称和版本。
- 输入的 token 数量和消耗成本。
- 生成的中间结果和最终输出。
- 人工反馈信息和后续修改内容。
通过这样的日志,团队可以量化 AI 测试的投入产出比,也能在出现问题时快速定位是模型问题、Prompt 问题还是数据问题。
10.3 模型选型建议
在测试用例生成这个场景里,模型选择并不一定越贵越好。在实际对比中我们发现:
- 如果只是做初步用例头脑风暴,轻量级模型足够。
- 如果要生成高质量的多维度用例,建议使用能力较强的旗舰模型。
- 如果要做性能测试报告分析,模型的分析能力比代码生成能力更重要。
建议团队先拿 10 个典型需求做一次模型评测,对比不同模型的用例覆盖度、准确率和格式合规率,再决定正式环境用哪个模型。不要一上来就迷信“最大的模型”。
10.4 成本控制
Agent 应用的成本主要来自 token 消耗。工具返回的接口文档 JSON 很可能会在多轮推理中被反复发送给模型,尤其是使用 ReAct 模式时,模型每执行一步都会携带完整的对话历史。
控制成本的几个手段:
- 精简工具返回内容,只返回必要字段,而不是整个接口文档。
- 使用摘要记忆,而不是完整保存所有历史消息。
- 对简单任务,使用温度参数为 0,减少无效重试。
- 对重复任务做结果缓存,相同需求不重复调用模型。
- 设定单次任务的 token 上限,防止死循环。
11. 学习路线与下一步规划
如果你目前刚接触 LangChain Agent,建议按下面的路线走一遍:
第一阶段:入门 LangChain 基础 API,理解 ChatModel、Prompt、OutputParser 这三个核心抽象,尝试完成一个“调用模型生成一段文本”的最小示例。
第二阶段:掌握工具调用和 Agent 执行流程,学会使用@tool装饰器定义工具,并理解 Agent 是如何根据任务描述决定调用哪个工具的。
第三阶段:开发一个垂直领域 Agent,比如本文中的测试用例生成 Agent。不要追求功能复杂,先把一条链路走通,再逐步增加工具和约束。
第四阶段:引入 RAG 和记忆,让 Agent 能结合项目知识库和历史对话给出更精准的输出。
第五阶段:学习 LangGraph,理解状态机编排,将单一 Agent 升级为多 Agent 协作系统。
第六阶段:工程化落地,包括模型评测、成本监控、日志审计、人工审核闭环、私有化部署。
在实际项目中,我建议先选一个价值明确、流程标准化程度高、结果容易验证的测试场景切入,比如“接口测试用例生成”,不要一上来就要覆盖所有测试类型。先把单点做到可用,再逐步扩展,这是 AI 测试落地最稳的路径。
最后提醒一句,AI 测试的定位应该是“测试工程师的超级助手”,而不是“替代测试工程师”。工具能帮我们节省重复劳动时间,但测试策略的制定、关键业务的判断、上线风险的决策,仍然需要人来把握。把 Agent 当成一个能随叫随到、知识面极广但不一定了解你项目的实习生来看待,可能更贴近实际情况。你要做的是教会它你的规范、你的业务、你的坑,然后让它帮你干那些确定性高的脏活累活。