Playwright Agent 实战教程:用 Healer 自动修复报错用例
Оригинальный заголовок: Playwright Agent 实战教程:AI修报错用例
Заголовок и краткое изложение на выбранном языке ожидают перевода.
Playwright Agent 的 Healer 能完成跑测试、诊故障、改代码、重跑一整轮,在 VS Code 的 Copilot Chat 里切到 Agent Mode、选 @playwright-test-healer 并贴一句 Run and fix failing tests 即可触发。
Полный текст на выбранном языке ожидает перевода. Пока показан оригинал.
用例一改版就红?半夜被 CI 叫醒改断言?Playwright Agent 官方 Healer 实战演示:跑测试、诊故障、改代码、重跑,一条龙。手把手教程 + 一套可迁移的故障判断法,看完就能用在自己项目上。
一、测试的成本不在写,在养
写自动化测试的小伙伴有体会,修改用例成本比单独写用例高多了。Playwright Agent有个Healer 干的就是这活:跑测试 → 诊故障 → 改代码 → 重跑。
说下我的心得:它修不动时,会标记 test.fixme()停下来说"这是产品 Bug",人工再介入而不会只是删断言让测试变绿。
二、跟着做完,你能拿到
让 Healer 跑完「跑 → 修 → 重跑」完整一轮
- 一套故障判断法
拿到红灯先问哪 3 个问题,才知道该改测试还是报 Bug
三类故障的修法对照(断言过期 / 异步时序 / 产品 Bug)
一套敢落地的安全护栏(本地修 + 人审 diff + 不自动 push)
三、准备:先给项目造一条红灯
Healer 要有东西可修,不用另找项目——你自己的用例库就是最好的素材。
按下面任一种方式造一条,跑一遍确认能稳定复现:
① 造「断言过期」(最常见)
把某条断言的期望值,改成一个已经被改掉的旧文案:
typescript
// 页面现在写的是「小观察价」,断言还停在旧的「观察价」
awaitexpect(page.getByText('观察价', { exact: true })).toBeVisible();
② 造「异步时序」
在产品数据加载完之前就断言,不给等待:
typescript
await page.goto('/your-page');
const text = await page.locator('body').innerText(); // 拍一张快照立刻断言
expect(text).toContain('已加载');
③ 造「功能未实现」
挑一条还没做的产品需求,先把用例写上:
typescript
awaitexpect(page.getByRole('button', { name: /导出 CSV/ })).toBeVisible();
跑一遍,记住它红在哪一行,第五节要对照:
bash
npx playwright test your-broken.spec.ts --reporter=list
✘ 1 … 结果区应显示观察价 (5.0s)
✘ 2 … 快照列表应在打开后可见 (2.0s)
2 failed💡 macOS 12 / 13 装不上 Chromium → 加
PW_CHANNEL=chrome驱动本机 Chrome(见第 1 篇)。
四、关键动作:一句"跑并修好"
四步走:
VS Code 打开项目,Copilot Chat切到 Agent Mode
选代理
@playwright-test-healer把红灯的用例文件加进上下文
贴这句(可直接复制)
Runand fix failing tests它随后自行跑完一整轮。终端里你会看到它是边取证边判断的:
[跑] ✘ 结果区应显示观察价 → getByText('观察价') 找不到元素
[取证] 打开失败快照 → 结果区实际文案是「小观察价 / 大观察价」
[归因] 文案改版导致断言过期,不是产品 Bug
[改] 断言更新到当前文案,保留校验语义
[重跑] ✓ passed中间那个「归因」才是重点——它凭什么判断"这是断言过期"而不是"产品坏了"?这就是下面要讲透的东西。
五、先分诊,再动手(本篇最值钱)
第一件事不是改代码,是先定位问题:
问自己 3 个问题,答案直接决定改法:
- 页面上实际是什么?
—— 打开 trace / 失败快照,看真实文案与真实元素
- 它是稳定红还是偶发红?
—— 连跑 3 次:次次红=断言错,偶发红=时序问题
- 产品到底有没有这个功能?
—— 全页搜一遍,没有就是功能没做
拿到答案,再对号入座:
实际内容变了 → A 断言过期→ 更新断言
时红时绿 → B 异步时序→ 改成等条件
功能压根没有 → C 产品 Bug→ fixme 转人工
下面三种,就是这套分诊的完整落地。
A|断言过期 → 更新到当前文案,但不许删断言
typescript
// ❌ 修复前:文案已从「观察价」改成「小观察价 / 大观察价」
awaitexpect(page.getByText('观察价', { exact: true })).toBeVisible();
// ✅ 修复后:跟上当前页面,校验语义一点没丢
awaitexpect(page.getByText('小观察价', { exact: true })).toBeVisible();
awaitexpect(page.getByText('大观察价', { exact: true })).toBeVisible();
审这个 diff 的标准:断言跟上了当前文案,而且"结果区必须给出观察价"这个校验意图还在。
如果它只是把断言删掉让测试变绿——这个 diff 不合格,打回去重修。这是 Healer 最容易滑过去的地方,也是你审 diff 的第一优先级。
B|异步时序 → 等条件,不要等时间
typescript
// ❌ 修复前:innerText 拍一张快照就断言,数据还没回来
const text = await page.locator('body').innerText();
expect(text).toContain('已加载');
// ✅ 修复后:等条件出现
awaitexpect(page.getByText(/已加载 \d+ 条/)).toBeVisible({ timeout: 20_000 });
区别只有一句话:
waitForTimeout(2000)—— 睡死。机器快时白等,机器慢时照挂,是毒药
expect(...).toBeVisible()—— 自带轮询重试,条件成立就过,快慢机器都稳
验收标准:改完连跑 3 次全绿才算修好(--repeat-each=3),一次绿不算数。
C|产品 Bug → test.fixme(),不是硬改成能过
typescript
// ✅ 修复后:测试逻辑不动,声明"功能没做,先排队"
test.fixme(true, '站点暂未提供「导出 CSV」按钮,已转产品确认(2026-09)');
awaitexpect(page.getByRole('button', { name: /导出 CSV/ })).toBeVisible();
fixme不等于跳过。跳过是"假装没看见",fixme 是"测试没错,功能有问题,先排队等开发"——报告里明确显示为待修复项。
每次看到 fixme,你先做的事:确认它到底是产品 Bug,还是测试理解错了。后者就自己改回来重跑,别让它躺在报告里长蘑菇。
三类修完,最终交付长这样:
2 passed, 1 skipped。那条 skipped 不是失败,是你亲手签过字的待办。
六、敢不敢用?三道护栏
这是收官篇最该带走的。AI 改代码可以,但人类絮语把关。
- 本地修 + 人工审 diff
— CI 红了,本地(或人工触发)跑 Healer,修完
git diff一条条看,再合入。不要让 Agent 自动 push。 - 禁区优先审
— 金额、价格、业务公式相关的断言,review 优先级最高。这类断言被"改绿"的代价最大。
- fixme 必须转人
— 每个 fixme 都要有人确认是产品 Bug 还是测试写错,不能自动消失。
接进 CI:只让它跑,不让它改
CI 的职责是跑 + 留证据,修复留给人 / Agent 在本地做:
yaml
-name:RunPlaywrighttests
run:npxplaywrighttest--reporter=html,list
-name:UploadPlaywrightReport(含trace/截图/视频,供Healer取证)
if:always()
uses:actions/upload-artifact@v4
with:
name:playwright-report
path:|
output/html-report/
test-results/
retention-days:7
红了 → 拉 trace / 视频 → 本地跑 Healer → 审 diff → 合入。
七、3 条心法,照做少踩坑
- 修完必看 diff
— 重点看它有没有"删断言换绿",这是唯一的红线
- 偶发红要连跑 3 次
— 一次绿不算绿
- fixme 是待办不是垃圾桶
— 每个 fixme 都要有归属
八、新手最常问的 3 个问题
Q1:它会把产品 Bug 误判成测试问题、硬修掉吗?岗位说明书里写死了流程:先复现 → 取证(快照/控制台/网络)→ 归因 → 只改该改的 → 重跑验证,修不动且有把握测试正确时用 fixme 停下。再加你人工审 diff,双重保险。
Q2:Python / .NET 项目能用吗?目前官方围绕 TypeScript(@playwright/test)提供得最完整。但"计划 → 生成 → 修复"这套思路不绑语言,先用 TS 工程把流程跑通验证价值。
Q3:fixme和"跳过"有什么区别?test.fixme()= "测试本身正确,但功能有问题,先不跑",报告里明确标为待修复项;跳过是"假装没看见"。fixme 会一直提醒你,跳过不会。
九、小结 & 系列收官
Healer = 跑 → 诊 → 修 → 重跑,把"养测试"自动化
分诊三问:实际是什么 / 稳定还是偶发 / 功能有没有→ 对应三种改法
你的角色没变,只是从"改代码"变成"审 diff"
三篇走完,Planner 定测什么 → Generator 写代码 → Healer 保不腐,闭环成立。
回头看这套东西真正改变的不是效率,是角色:你不用再一行行敲用例,但"测什么"和"这样改对不对"这两道闸,永远在你手里。
AI 能替你写一百条用例,替不了你判断哪条值得写。这就是测试架构师在 AI 时代的位置。
Источник: Playwright实战教程 · mp.weixin.qq.com