用 BMAD 框架打造能自我修复的 E2E 测试大师
阶段模型名称核心特征应用场景工程缺陷1提示即代码 (Prompt-as-Code)一次性、非结构化提示,直接生成代码执行。快速原型设计、简单数据查询。鲁棒性极低,无法处理复杂环境。2工具调用 (Tool-as-Function)Agent 能调用预定义工具(Function Calling),但工具逻辑在外部。外部 API 集成、简单系统操作。Agent 仍是执行者,缺乏对复杂流程的控制能力。3A
Opening Statement Hook: 你是否厌倦了那些“运行一次就抛弃”的 AI 脚本?在追求智能自动化的道路上,我们常常忽略了一个最基本的问题:AI 代码是否足够健壮,能否像人类工程师编写的代码一样,具备参数化、错误处理、环境预检和资源回收的能力? 本文将带你深入一个顶级 AI Agent 任务的内部结构,揭示如何将一个简单的 “Ping Test” 升级为一套具备交互式修复能力、CI/CD 兼容性、且能安全管理系统资源的专业级“AI 技能”。我们的目标是:从“Prompting”阶段,彻底迈向“Programming” AI Agent 的工程化实践。
Part I: 范式转变:从简单提示到工程化 AI Agent 技能
1.1. 导言:AI 自动化中的“工程化”缺失
在过去的一年里,大语言模型(LLM)驱动的 AI Agent 已经从科幻走进了工程实践。但当前大多数 Agent 的应用场景仍停留在“一次性脚本”的层面:用户给出一个自然语言提示,Agent 生成并执行一段代码(通常是 Python 或 Shell),完成任务后便退出。
这种模式存在致命的工程缺陷:
- 缺乏鲁棒性(Fragility):代码没有错误处理,环境稍有变化即失败。
- 不可重用性(Non-Reusability):每次任务都需要重新提示,浪费 LLM 资源。
- 资源泄露(Resource Leakage):没有原子级的清理机制,容易在后台留下僵尸进程或未释放的资源。
- 非交互性(Non-Interactive):CI/CD 模式和本地调试模式无法兼容。
真正的工程实践要求自动化工具像人类工程师一样:预先检查环境、安全启动和终止进程、处理异常情况,并能根据环境(本地调试或 CI)自动切换模式。这正是“AI 技能工程化”的核心价值。
1.2. 什么是“AI 技能”?AI Agent 自动化模型的三个进化阶段
我们将 AI Agent 的自动化能力进化划分为三个阶段:
| 阶段 | 模型名称 | 核心特征 | 应用场景 | 工程缺陷 |
|---|---|---|---|---|
| 1 | 提示即代码 (Prompt-as-Code) | 一次性、非结构化提示,直接生成代码执行。 | 快速原型设计、简单数据查询。 | 鲁棒性极低,无法处理复杂环境。 |
| 2 | 工具调用 (Tool-as-Function) | Agent 能调用预定义工具(Function Calling),但工具逻辑在外部。 | 外部 API 集成、简单系统操作。 | Agent 仍是执行者,缺乏对复杂流程的控制能力。 |
| 3 | AI 技能工程化 (Engineered AI Skill) | 将复杂流程封装成结构化、参数化、自带鲁棒逻辑的“技能文件”。 | 复杂的 Dev/Ops、QA 自动化、高可靠性任务。 | - |
AI 技能(AI Skill):一个可版本控制、参数化、具备明确输入、输出、执行流程、以及内置错误处理和清理逻辑的结构化任务定义文件。它将 Agent 从一个临时的代码生成器,提升为能够执行复杂、多步骤、高可靠性流程的专业化角色。
1.3. 引入 BMAD 技能管理框架:一个面向生产环境的 Agent 治理体系
为了有效地管理这些复杂的“AI 技能”,我们引入一个概念性的组织和治理框架:BMAD。
- B - Build (构建):定义和编写技能文件(如
.md或.yaml格式),明确输入、输出和执行步骤。 - M - Manage (管理):通过 Git 或其他版本控制系统进行管理,并以层级目录结构组织(如
.claude/commands/BMad/tasks/...)。 - A - Agent-Execute (Agent 执行):Agent 解析技能文件,结合 LLM 的规划能力,在沙盒环境中执行流程。
- D - Deploy (部署):将技能集成到 CI/CD 流程或开发者 CLI 中,实现大规模应用。
我们提供的 run-e2e-ping-test.md 文件正是 BMAD 框架下,一个面向 qa 代理的高度工程化的 B - Build 阶段的杰出产物。
Part II: 蓝图剖析:深度解析 E2E Ping 测试任务
2.1. 任务的宏观目标与价值
任务文件: .claude/commands/BMad/tasks/run-e2e-ping-test.md
该任务的核心目标是自动化一个完整的、模拟用户行为的端到端(E2E)测试,以验证前后端服务的联通性。
传统 E2E 测试 vs. Agent 驱动 E2E 测试
| 特征 | 传统脚本 (e.g., Playwright/Cypress) | Agent 驱动任务 (BMAD Skill) |
|---|---|---|
| 测试目标 | 关注业务逻辑或 UI 交互。 | 关注环境准备、进程管理、原子清理。 |
| 执行载体 | 预编写的 JS/TS 代码。 | AI 动态生成、结合系统工具、执行流程。 |
| 健壮性 | 依赖工程师编写的错误捕获。 | 内置预检逻辑、交互式用户决策回路。 |
| 启动方式 | 需手动或外部 CI 脚本启动服务。 | 将服务启动/停止纳入任务流程内,实现自包含。 |
Agent 任务将环境准备和清理视为测试本身不可分割的一部分,从而极大提高了测试的可靠性和隔离性。
2.2. Agents and Delegation: 为什么是 qa 代理?
负责人:qa 代理
在 BMAD 框架下,我们倡导“代理角色专业化”。就像人类团队中的 Dev、Ops、QA 一样,Agent 也应具备专业职能边界:
developer代理:专注于功能代码的编写、重构和单元测试。devops代理:专注于基础设施、部署脚本、CI/CD 流程。qa代理:专注于系统联通性、集成测试、E2E 流程,并对测试环境的隔离性负责。
将 E2E 测试指派给 qa 代理,意味着:
- 职责分离:确保测试的独立性和客观性。
- 专业工具集:
qa代理将默认配备 Playwright MCP、Chrome DevTools MCP、系统端口工具等,无需在核心developer代理中冗余。 - 权限控制:可以对
qa代理施加更严格的系统资源(进程管理、网络访问)使用权限限制。
2.3. Parameters and NL-CLI: 如何将自然语言转化为结构化指令?
任务定义清晰地列出了三个输入参数:backendPort、frontendPort 和 ciMode。这赋予了任务高度的灵活性和可重用性。
深度解析:NL-CLI (Natural Language Command Line Interface)
这是 Agent 工程化中最具颠覆性的机制之一。它解决了传统 CLI 的两大痛点:难以记忆和输入繁琐。
传统 CLI: run-e2e-ping-test --backendPort 8080 --frontendPort 3000
NL-CLI: 运行端到端 ping 测试,但后端使用 8080 端口,前端使用 3000 端口。
AI Agent 内部必须执行以下关键步骤:
- 意图识别: 识别用户请求的核心任务是“运行端到端 ping 测试”。
- 参数提取:
- 通过自然语言处理和槽位填充(Slot Filling)技术,从句子中提取数值:“8080”、“3000”。
- 识别关键词“后端使用”和“前端使用”,将其与任务定义的参数
backendPort和frontendPort进行语义匹配。
- 模式推断: 根据语句中未提及“交互”或“CI”,判断
ciMode为默认值false。 - 结构化输出: 将结果转化为内部执行环境可识别的 JSON 结构:
{ "task": "run-e2e-ping-test", "backendPort": 8080, "frontendPort": 3000, "ciMode": false }。
Pro-Tip: NL-CLI 的鲁棒性要求 Agent 能够处理同义表达(如“后端使用 8080 端口”与“服务在 8080 上跑”)和不完整信息(只指定一个端口)。
Part III: 鲁棒性支柱 (I):预检和交互式修复
3.1. 自动化任务的致命弱点:环境依赖与资源冲突
E2E 测试最常见的失败原因不是代码 Bug,而是环境问题。特别是端口冲突,如果测试脚本无法处理,CI/CD 流水线将立即中断,耗费宝贵的构建时间。
run-e2e-ping-test 任务通过 第 1 步:预检 - 端口验证 机制,将环境问题从“致命错误”降级为“可修复异常”,是工程化 Agent 的一个核心标志。
3.2. 核心机制 1: 预检 - 端口可用性验证
技术细节:跨平台端口检测的抽象与执行
Agent 在执行预检时,不能简单地尝试连接端口,而必须使用操作系统级的命令来确定端口被占用的具体原因(即哪个进程 ID 占用)。
| 操作系统 | 端口检查命令 (抽象前) | 抽象目标 |
|---|---|---|
| Linux/macOS | lsof -i :<端口> |
检查并返回 PID |
| Windows | netstat -ano | findstr :<端口> |
检查并返回 PID |
Agent 的执行逻辑:LLM 会首先识别当前操作系统,然后选择正确的系统工具,并封装成一个原子工具调用,其输出必须包含 端口状态(可用/占用) 和 占用进程 PID。
错误处理架构:可恢复性设计
预检流程体现了分层错误处理的高级架构:
- 一级检查: 端口占用。
- 二级决策: 根据
ciMode决定处理方式。
3.3. 交互式修复与人机协作 (ciMode=false 流程解析)
当在本地开发环境 (ciMode=false) 运行时,Agent 并不急于失败,而是进入一个“用户决策回路”,寻求人类的帮助以修复环境。这极大地提升了开发体验。
用户决策回路:[K]ill - 强制终止
如果用户选择 [K]ill - 终止,Agent 的执行流程将是:
- 解析 PID: 从预检结果中提取冲突进程的 PID。
- 系统级终止: 执行
kill -9 <PID>(或 Windows 对应命令taskkill /F /PID <PID>)。 - 二次验证: 重新回到预检流程的第 1 步,再次检查端口是否已释放。

用户决策回路:[R]etry - 动态重试
如果用户选择 [R]etry - 重试:
- 参数重置: Agent 必须询问新的端口号,并通过内部机制动态更新任务的
backendPort或frontendPort参数。 - 流程回溯: 任务流程回溯到“预检 - 端口验证”的起点,使用新参数重新执行第 1 步。
这体现了 Agent 不仅是执行者,更是故障排除助手的价值,将原本需要人工执行的诊断、终止、重试流程自动化。
3.4. CI/CD 的 Fail-Fast 原则 (ciMode=true 流程解析)
当在 CI/CD 环境 (ciMode=true) 中运行时,环境修复的成本太高,人机交互是不允许的。因此,Agent 必须遵循 Fail-Fast 原则。
- 逻辑: 如果端口被占用,Agent 必须立即以非零状态码(表示失败)中止任务。
- 工程价值: 确保流水线快速失败,避免浪费后续的构建、部署或长时间测试时间。
Part IV: 执行引擎:并发、MCPs 与原子操作
一旦环境预检通过,Agent 即可进入高并发、高精度的执行阶段。
4.1. 并发启动与 PID 追踪的艺术
E2E 测试要求前后端服务同时运行。Agent 必须安全地将它们转为后台进程,并在 Shell 环境中实现并发。
关键挑战: 如何在后台运行进程的同时,捕获其 PID?
| 步骤 | 命令行(抽象) | 目的 |
|---|---|---|
| 1 | npm run dev:server -- --port ${backendPort} & echo $! > backend.pid |
启动后端服务,并立即将后台进程 ID 写入 backend.pid 文件。 |
| 2 | npm run dev:client -- --port ${frontendPort} & echo $! > frontend.pid |
启动前端服务,并将 PID 写入 frontend.pid 文件。 |
| 3 | wait <Time> |
暂停执行,确保服务完全初始化。 |
工程关键点:& 符号实现了后台运行,echo $! 在 POSIX Shell 中用于捕获上一个后台进程的 PID。**记录这些 PID(在第 2 步中被要求)**是确保任务原子性的生命线。
4.2. Playwright MCP: 浏览器控制与前端访问
一旦服务启动,Agent 必须使用其专有工具 Playwright Modular Control Plane (MCP) 来模拟用户行为。
- 浏览器启动:
const browser = await playwright.launch({ headless: true }) - 导航: 访问经过验证的
frontendPort上的 URL:await page.goto(http://localhost:${frontendPort})
无头模式(headless: true)是 CI/CD 和自动化任务的标准配置,它消除了对图形界面的依赖,提高了执行速度和稳定性。
4.3. Chrome DevTools MCP 与深度网络捕获
Agent 驱动测试的优势在于其超越表层 UI 的深度洞察力。通过 Chrome DevTools MCP 的能力(通常通过 Playwright 的底层 API 实现),Agent 可以进行网络级别的断言。
传统 E2E:可能只断言页面上显示了某些文本。
高级 E2E 任务:必须断言底层数据流是否正确。
执行流程:
- 激活网络监听:
await page.route('**/api/ping', route => { /* handler */ }) - 等待请求:
const [response] = await Promise.all([ page.waitForResponse(response => response.url().endsWith('/api/ping')), page.click('#pingButton') // 触发前端请求的动作 ]) - 捕获与验证: 在捕获到
/api/ping的响应后,Agent 对其执行严格的校验。
4.4. 原子断言 (Atomic Assertion):API 响应的精确校验
第 4 步要求满足三个原子条件:
- 存在性验证: 检查是否捕获到了
/api/ping的请求。 - 状态码验证: 响应状态码是否严格等于
200。 - 内容精确验证: JSON 响应体是否完全等于
{ "msg": "pong" }。
任何一个条件不满足,整个任务即告失败。这种精确度是高级测试的必备条件。
Part V: 产物管理与原子清理
5.1. Proof of Execution: 自动化产物的标准与价值
成功的 Agent 任务不仅仅是“代码能跑”,更重要的是能提供可审计、可追溯的执行证据。
test-report.json(结构化数据):- 价值: 供 CI/CD 报告系统或 Agent 自身的学习系统使用。它包含测试时间、持续时间、断言结果、以及 ping 请求和响应的详细元数据。
- Agent 行为: 必须在断言完成后,将捕获到的请求/响应对象结构化并序列化为 JSON 格式。
ping.png(视觉证据):- 价值: 提供测试瞬间的页面视觉状态,对于 UI 调试和非预期渲染场景至关重要。
5.2. 核心机制 2: 终局清理与资源回收 (Atomic Cleanup)
这是该任务中最能体现“工程化”精神的关键一步。一个不安全的自动化脚本执行后,可能在系统上留下:
- 孤立的后端服务进程(占用
backendPort) - 孤立的前端开发服务器进程(占用
frontendPort) - Playwright 启动的浏览器实例残留。
为什么必须使用 PID?
直接使用 killall node 是危险的,它会终止系统中所有的 Node.js 进程,包括开发者可能正在运行的其他项目。
原子清理 的核心原则是:只清理由本任务启动的进程。
- Agent 必须读取
backend.pid和frontend.pid文件,获取到在 4.1 节中记录的精确 PID。 - 然后,执行:
kill <backend_PID>和kill <frontend_PID>。
健壮性要求: 清理步骤必须被设计为无论任务成功还是失败,都必须执行(类似于编程中的 finally 块)。这保证了系统资源的绝对释放。
Part VI: 工程最佳实践和未来方向
6.1. 总结:AI Agent 技能工程化的五大核心原则
通过对 run-e2e-ping-test.md 任务的深度解析,我们提炼出 AI Agent 技能工程化的五大核心原则:
- PFC (Pre-flight Check) 原则: 在执行任何资源操作之前,必须执行全面的环境预检。
- Atomic (原子性) 原则: 任务必须是自包含的,要么完全成功,要么能安全回滚/清理,确保对系统状态的净影响为零(零资源泄露)。
- Parameterized (参数化) 原则: 任务的所有关键变量必须能够通过参数控制,以实现最大的重用性。
- Specialized (专业化) 原则: 任务必须被分配给具备专业工具集和职责的 Agent 角色(如
qa)。 - Managed (可管理性) 原则: 任务定义必须是结构化的、可版本控制的(BMAD 框架),而非一次性的非结构化提示。
6.2. 拓展应用:将此模型推广到更复杂的 Dev/Ops 任务
run-e2e-ping-test 只是一个起点。这套工程化方法论可以应用于任何复杂的 Dev/Ops 任务:
| 复杂任务 | 核心挑战 | Agent 技能工程化应用 |
|---|---|---|
| 数据库 Schema 迁移 | 1. 权限与连接性检查;2. 无法回滚的致命性。 | PFC 检查:连接性、备份状态。Atomic 清理:迁移失败时自动执行回滚脚本。 |
| 蓝绿部署 (Blue/Green) | 1. 并发启动新环境;2. 流量切换前的健康检查。 | PFC 检查:目标端口和路由可用性。并发启动:同时管理新旧环境 PID。中断逻辑:健康检查失败,终止新环境 PID,不切换流量。 |
| 依赖升级 (e.g., Node.js Major Version) | 1. 兼容性检查;2. 依赖安装与测试。 | PFC 检查:现有版本与目标版本兼容性报告。交互式:兼容性问题时,询问用户“忽略/降级/修复”。 |
6.3. 结论:自动化与智能的融合
“智能”的价值,最终要由“工程”的质量来衡量。一个能够解析复杂意图、执行环境预检、在 CI/CD 中保持静默、在本地调试时与用户交互、安全地管理系统进程、并最终清理所有残留的 AI Agent 任务,才是真正值得信赖、可以部署到生产环境的自动化资产。
run-e2e-ping-test 的蓝图不仅提供了一个 E2E 测试的解决方案,它更提供了一张通往 AI Agent 工程化时代的路线图。从今天起,让我们告别低效的“脚本”,开始构建专业的“AI 技能”。
附录:BMAD 任务文件——run-e2e-ping-test.md 完整结构
为了确保报告的完整独立性,再次附上作为本文核心案例的 BMAD 任务定义文件。
.claude/commands/BMad/tasks/run-e2e-ping-test.md
## 任务:运行端到端 Ping 测试
**负责人**:`qa` 代理
**描述**:自动化一个完整的前后端交互测试,包括启动服务、运行浏览器测试以验证 API 端点,并生成最终报告。该任务是交互式的,并包含预检步骤以确保环境就绪。
### 输入参数
此任务接受可选参数。如果未提供,将使用默认值。
| 参数 | 描述 | 默认值 |
| :------------- | :----------------------------------------------- | :------ |
| `backendPort` | 后端服务所需端口。 | `3001` |
| `frontendPort` | 前端开发服务器所需端口。 | `5173` |
| `ciMode` | 若为 `true`,则以非交互模式运行(例如在 CI/CD 中)。 | `false` |
---
### 执行流程
#### 第 1 步:预检 - 端口验证
在启动任何服务之前,你必须验证所需端口是否可用。
- **目标**:确定最终可用的 `backendPort` 和 `frontendPort`。
- **流程**:对每一个目标端口(先处理 `backendPort`,再处理 `frontendPort`)执行以下操作:
1. 执行系统级检查,确认端口当前是否被占用(例如,使用 `lsof -i :<端口>` 或 `netstat` 命令)。
2. **如果端口被占用**:
- 明确告知用户哪个端口被占用,以及(如果可能)是哪个进程在使用它。
- **当 `ciMode` 为 `true` 时**,立即以清晰的错误信息中止任务。
- **当 `ciMode` 为 `false` 时**,向用户提供两个明确的选项:
- **[K]ill - 终止**:强制终止占用端口的进程。
- **[R]etry - 重试**:指定一个新端口号重试。
- 如果用户选择**终止**,执行必要的系统命令来结束冲突进程,然后再次验证端口是否已释放。
- 如果用户选择**重试**,询问新的端口号,并使用新端口号回到本预检流程的第 1 步。
3. **如果端口可用**:
- 确认此端口为最终将要使用的端口。
- 继续验证下一个端口。
#### 第 2 步:并发启动服务
一旦所有端口都验证并确认无误:
- 启动后端服务,确保它在最终确定的 `backendPort` 上监听。你可能需要通过环境变量(`PORT=${backendPort} npm run dev:server`)或命令行参数(`npm run dev:server -- --port ${backendPort}`)来传递端口号。
- 启动前端开发服务器,确保它在最终确定的 `frontendPort` 上监听。
- 这两个进程必须在后台运行。**必须记录每个服务的进程 ID (PID),以便在清理步骤中使用。**
#### 第 3 步:等待并启动浏览器
- 等待一段足够的时间(例如 5-10 秒),以确保两个服务都已完全初始化并准备好接受连接。
- 使用 **Playwright MCP**,启动一个无头模式的 Chromium 浏览器实例。
- 访问 `http://localhost:${frontendPort}`。注意,这里使用的是经过验证的 `frontendPort`。
#### 第 4 步:网络捕获与断言
- 利用 **Chrome DevTools MCP** 的能力(通过 Playwright 的网络拦截功能),主动监控网络请求。
- 等待访问 `/api/ping` 端点的网络请求出现。
- **断言以下条件必须满足**:
- 存在对 `/api/ping` 的请求。
- 响应状态码为 `200`。
- JSON 响应体内容完全等于 `{ "msg": "pong" }`。
#### 第 5 步:生成产物(Artifacts)
- 将测试结果(成功/失败,以及 ping 请求/响应的详情)保存到一个名为 `test-report.json` 的文件中。
- 对最终的页面状态进行截图,并保存为 `ping.png`。
#### 第 6 步:清理环境
- 平稳地关闭 Playwright 浏览器实例。
- **使用在第 2 步中记录的 PID**,平稳地终止后端和前端服务进程,确保没有留下任何孤立进程。
更多推荐

所有评论(0)