首页
/ Playwright AI Agent 之 playwright-test-generator:基于实时浏览器交互的端到端测试自动生成指南

Playwright AI Agent 之 playwright-test-generator:基于实时浏览器交互的端到端测试自动生成指南

2026-09-06 18:19:11作者:庞队千Virginia

导读

playwright-test-generator 是 Playwright 仓库中为“AI 驱动测试生成”设计的专用 Agent(智能体)。它的核心思路不是让模型凭空写断言,而是让模型先通过真实浏览器一步步执行测试场景,再依据执行日志回放生成稳定、可运行、符合最佳实践的 Playwright 测试代码。阅读本文后,你将理解该 Agent 的系统提示词设计、其挂载的浏览器工具清单、generator_setup_page → 逐步执行 → generator_read_loggenerator_write_test 的完整工作流,以及它在仓库源码(MCP test 服务层)中的底层实现与对应测试验证。

本文以 playwright-test-generator.agent.md 为骨架展开,并结合其实现源码 generatorTools.tstestContext.tsseed.ts 及测试用例 generator.spec.ts 进行纵深剖析。

Agent 概览:一个“会动手操作浏览器”的测试生成器

playwright-test-generator.agent.md 是标准的 Agent 声明文件(frontmatter + 系统提示词),其 frontmatter 明确定义了 Agent 的身份与能力边界:

name: playwright-test-generator
description: Use this agent when you need to create automated browser tests using Playwright
model: sonnet
color: blue
tools:
  - search
  - playwright-test/browser_click
  - playwright-test/browser_drag
  - playwright-test/browser_evaluate
  - playwright-test/browser_file_upload
  - playwright-test/browser_handle_dialog
  - playwright-test/browser_hover
  - playwright-test/browser_navigate
  - playwright-test/browser_press_key
  - playwright-test/browser_select_option
  - playwright-test/browser_snapshot
  - playwright-test/browser_type
  - playwright-test/browser_verify_element_visible
  - playwright-test/browser_verify_list_visible
  - playwright-test/browser_verify_text_visible
  - playwright-test/browser_verify_value
  - playwright-test/browser_wait_for
  - playwright-test/generator_read_log
  - playwright-test/generator_setup_page
  - playwright-test/generator_write_test

几点值得注意的设计信息:

  • 模型与主题色model: sonnetcolor: blue 用于在 Agent 管理/展示层区分身份(同目录下的 planner 使用 model: sonnet, color: green,见 playwright-test-planner.agent.md),提示词中不含具体模型指令。
  • 工具命名空间:所有工具都挂载在 playwright-test/ 命名空间下,由 MCP test 服务端暴露。其中 browser_* 系列是“动作工具”,负责在真实页面执行点击、拖拽、输入、悬停、文件上传、对话框处理、键盘按键、选项选择、导航、取值等操作;browser_snapshot 负责读取当前页面可访问性快照(yaml 格式的 ref 树);browser_verify_*browser_wait_for 负责可见性/文本/数值的验证与等待。
  • 三个生成专用工具generator_setup_page(初始化场景页面)、generator_read_log(读取执行日志)、generator_write_test(写出测试文件),它们是本 Agent 工作流的“脚手架”。

该 Agent 与上游的 playwright-test-planner.agent.md 形成流水线:planner 通过 planner_setup_page + planner_save_plan 产出带编号步骤与验证规格的测试计划(Test Plan);generator 则消费该计划,把每一条步骤真实执行一遍并沉淀为测试代码。

生成每个测试必须遵循的工作流

系统提示词为 Agent 规定了固定的执行顺序,这是保证生成质量的关键约束:

  1. 获取测试计划:拿到包含全部步骤与验证规格(verification specification)的测试计划;
  2. 初始化场景:调用 generator_setup_page 工具为当前场景准备好页面;
  3. 逐条执行并回放:对场景中的每一步与每一项验证:
    • 使用某个 Playwright 浏览器工具在实时页面上手动执行该步骤;
    • 将该步骤的文字描述作为每次工具调用的 intent(意图)参数传入
  4. 读取生成日志:通过 generator_read_log 获取生成器日志;
  5. 立即写测试:读取日志后立刻调用 generator_write_test,把生成的源码写入测试文件。

这里的核心机制是 intent 驱动 + 执行日志回放:Agent 在执行 browser_clickbrowser_type 等动作时,附带描述性 intent 字符串(如 “Click submit button”),底层后端在执行成功后会返回对应的可执行代码,并连同 intent 一并记录进“生成日志”;generator_read_log 返回的正是这份结构化日志,供模型在写测试时引用真实使用过的可靠定位器而非凭空臆造。

日志的四个组成部分

testContext.tsGeneratorJournal.journal() 的实现可以看到,generator_read_log 返回的日志严格包含四部分:

  • # Plan:本次测试计划全文;
  • # Seed file: <path>:seed 文件相对路径及其源码(```ts 代码块);
  • # Steps:按序排列的每个步骤,格式为 ### <intent> + 对应可执行代码块;
  • # Best practices:从日志中应遵循的最佳实践清单。

测试文件的生成规范

提示词对 generator_write_test 产出的文件提出了明确的格式要求:

  • 文件只含单个测试(single test);
  • 文件名必须是文件系统友好的场景名(fs-friendly scenario name,例如 add-valid-todo.spec.ts);
  • 测试必须放进一个与“顶层测试计划条目”同名的 test.describe 分组中;
  • 测试标题必须与场景名一致
  • 每个步骤执行前要写入包含步骤原文的注释;若一个步骤需要多个动作,则不要重复注释;
  • 写测试时始终采用日志中的最佳实践

提示词中的 example-generation 给出了计划到代码的映射示例:计划顶层标题 1. Adding New Todos 映射为 test.describe('Adding New Todos'),场景 1.1 Add Valid Todo 映射为 test('Add Valid Todo'),步骤 “Click in the ...” 映射为文件内 // 1. Click in the ... 注释下的真实点击代码;文件头还保留了来源溯源注释 // spec: specs/plan.md// seed: tests/seed.spec.ts

随后给出的 XML 风格 example 则是给下游生成/组装层传递测试套件名(test-suite)、测试名(test-name)、目标测试文件(test-file)、seed 文件(seed-file)与测试体(body)的接口示意。

关键工具深度解读(源码级)

三个 generator 专用工具在 generatorTools.ts 中逐一实现,均通过 defineTestTool 注册,属于 type: 'readOnly' 类别(不修改被测应用,只产出测试文件)。

generator_setup_page —— 建立场景并启动“暂停态”测试运行器

inputSchema: {
  plan:      z.string()   // 必填:完整测试计划(含所有步骤)
  project:   z.string()   // 可选:使用的项目,例如 "chromium";缺省取配置中第一个项目
  seedFile:  z.string()   // 可选:用于搭建测试页面的 seed 文件,如 "tests/seed.spec.ts";缺省自动创建默认 seed
}

其内部实现逻辑(setupPage.handle)分为三步:

  1. context.getOrCreateSeedFile(params.seedFile, params.project):解析出 seed 文件路径与项目;
  2. 用该 plan + seed 创建 GeneratorJournal 并挂到上下文;
  3. context.runSeedTest(...) 启动一次带 globalSetup、单 worker、无超时、pauseAtEnd: true 的测试运行,等待 TestPaused 事件,从而让页面停留在可交互状态。

status !== 'paused' 时该工具返回 isError: true。seed 文件解析规则(seed.tsgetOrCreateSeedFile)为:先在项目的 testDir 下解析,再回退到 config 目录与客户端工作目录;均不存在则报错 seed test not found。若未传 seedFile,则查找 testDir 下文件名含 seed 的既有文件;找不到就自动创建 testDir/seed.spec.ts,内容为内置模板:

import { test, expect } from '@playwright/test';

test.describe('Test group', () => {
  test('seed', async ({ page }) => {
    // generate code here.
  });
});

默认项目选择逻辑见 seedProject():未指定 project 时取第一个顶层项目,否则按 project.name 精确匹配,找不到会抛出 Project ... not found

generator.spec.ts 中,seed 文件可以是携带 test.beforeEach 的自定义夹具(例如先 page.setContent('<button>Submit</button>')),运行后返回的 pause 消息形如:

### Paused at end of test. ready for interaction
### Page state
- Page URL: about:blank
- Page Title:
- Page Snapshot:
```yaml
- button "Submit" [ref=e2]

### browser_* 动作工具 —— intent 是日志记录的关键

任何带 `intent` 参数的动作工具在成功执行后,其返回的响应中会携带真实的 `code`(如 `await page.getByRole('button', { name: 'Submit' }).click();`)与最新页面快照。这正是“先执行、后生成”的关键点:**代码不是模型写出来的,而是真实操作回放出来的**。

底层机制位于 [testContext.ts](https://gitcode.com/GitHub_Trending/pl/playwright/blob/46cd5008d12d4e1297793d921e6cc3b595e388da/packages/playwright/src/mcp/test/testContext.ts?utm_source=gitcode_repo_files) 的 `sendMessageToPausedTest`:当请求参数里存在字符串类型的 `intent` 时,后端调用 `tools.parseResponse` 解析动作结果,若响应无错误且含 `code`,就调用 `generatorJournal.logStep(intent, code)`,把“意图标题 + 可执行代码”追加进日志。换言之,**日志只收录真实执行成功、能够稳定产出的步骤**,天然排除了模型幻觉。

从 [generator.spec.ts](https://gitcode.com/GitHub_Trending/pl/playwright/blob/46cd5008d12d4e1297793d921e6cc3b595e388da/tests/mcp/generator.spec.ts?utm_source=gitcode_repo_files) 的断言可见,browser 工具还会尊重项目配置中的 `testIdAttribute`(例如自定义 `data-tid`),此时生成代码会自动使用 `page.getByTestId('submit')`,说明测试代码是**在用户项目真实配置语境下生成**的。

### generator_read_log —— 读取执行日志

```ts
generator_read_log: 输入为空;返回 GeneratorJournal.journal()

若 Agent 在未执行 generator_setup_page 前就调用本工具,后端会直接抛错:

Error: Please setup page using "generator_setup_page" first.

对应测试 'generator_setup_page is required'generator.spec.ts 中验证了这一前置约束对 generator_read_loggenerator_write_test 均生效。

generator_write_test —— 安全写出测试文件

inputSchema: {
  fileName: z.string()  // 测试要写入的文件
  code:     z.string()  // 生成的测试代码
}

写入逻辑带有多重安全与一致性校验:

  • 前置条件:必须先 setup page 且存在活跃的 test runner,否则抛错;
  • 路径安全:通过 resolveWithinRoot(rootPath, fileName) 将目标文件解析限定在项目根内;
  • 目录匹配:遍历 playwright.config 中所有项目的 testDir,只有当目标文件 isPathInside(projectTestDir, resolvedFile)(即落在某个项目的测试目录内)时才会 mkdir -pwriteFile;否则抛出错误 Test file did not match any of the test dirs: <dirs>,其中会列出所有可用的测试目录,帮助 Agent 下次选择正确路径。

成功时返回 ### Result\nTest written to <fileName>

写入日志的最佳实践清单

generator_read_log 返回内容的尾部固定附有 # Best practices 清单(定义于 testContext.tsbestPracticesMarkdown),系统提示词也要求 Agent “始终采用日志中的最佳实践”。完整原文为:

  • 不要即兴发挥,不要添加未被要求的指令;
  • 使用清晰、描述性的断言来验证期望行为;
  • 使用本日志中的可靠定位器(reliable locators);
  • 对多次使用的定位器使用局部变量保存;
  • 采用日志中的 Playwright 自动等待断言与最佳实践;
  • 绝不使用 page.waitForLoadState()
  • 绝不使用 page.waitForNavigation()
  • 绝不使用 page.waitForTimeout()
  • 绝不使用 page.evaluate()

这四条“绝不”与 Playwright 推荐的“自动等待 + 可重试断言 + 优先用 locator”理念一致:依赖自动等待而非手动等待 API,能让生成出的测试具备更强的健壮性。

与 Plannner/Healer Agent 的协作关系

playwright-test-generator.agent.md 并不是孤立文件。在 packages/playwright/src/agents 目录下,还并存着:

  • playwright-test-planner.agent.md:负责探索应用、产出结构化测试计划(场景含标题、逐步指令、预期结果、起始状态假设与成功/失败标准),经 planner_save_plan 保存为 markdown 计划文件;
  • playwright-test-healer.agent.md:负责在测试失败时自我修复;
  • 配套的 prompt 模板:playwright-test-plan.prompt.mdplaywright-test-generate.prompt.mdplaywright-test-coverage.prompt.mdplaywright-test-heal.prompt.md,以及 generateAgents.ts(将 agent 声明批量生成为正式 Agent 配置的构建脚本)与 agentParser.ts(frontmatter 解析器)。

可见本项目把“规划 → 生成 → 覆盖率评估 → 修复”拆解为多个专职 Agent,playwright-test-generator 是其中负责“将计划落成测试代码”的执行者,其输入(测试计划、seed 文件)与输出(.spec.ts 测试文件)均与前后端 Agent 强耦合。

如何在仓库中验证与体验

由于该 Agent 依赖 MCP test 服务端能力(BrowserMCP/TestMCP),仓库中与之直接对应的自动化测试集中在 tests/mcp/generator.spec.ts,它通过 mcpServerType: 'test-mcp' 启动真实服务端,并覆盖以下行为:

  • 所有 browser_* 动作工具都具备 intent 参数('generator tools intent');
  • generator_setup_page 返回 “Paused at end of test” 暂停消息与页面 yaml 快照;
  • 动作执行后 generator_read_log 能回放出 # Plan# Seed file# Steps### <intent> + 真实代码;
  • 未 setup 先读日志/写文件会得到前置错误;
  • generator_write_test 会真实写出文件内容;
  • 自定义 testIdAttribute 会被生成的代码正确采用。

如需阅读完整链路,可按下列路径继续深入本仓库源码:

小结

playwright-test-generator 的设计精髓可归纳为三点:真实执行优先于凭空生成(所有代码来自真实操作回放);intent 贯穿执行与日志(步骤文字描述与可执行代码一一对应,保证可追溯性);强约束的输出规范(单测试单文件、describe 对齐计划顶层条目、注释对齐步骤原文、仅落盘于合法 testDir)。这套“planner 出计划、generator 用浏览器跑一遍再回放成代码”的机制,正是 Playwright 仓库在 AI 原生测试生成方向上的落地形态,也解释了为何生成的测试能够直接使用项目中真实的定位器策略与 testId 配置。

登录后查看全文
热门项目推荐
相关项目推荐