voidmatcha/e2e-skills
GitHub: voidmatcha/e2e-skills
面向 Playwright 和 Cypress 的 E2E 测试全生命周期 Agent 技能集,覆盖测试生成、19 种反模式审查和失败根因诊断,解决「测试总通过却漏掉真实 bug」的核心痛点。
Stars: 1 | Forks: 0
# e2e-skills — E2E 测试生成、审查与调试
总是通过的 E2E 测试比没有测试更糟糕——它们会带来虚假的自信,而真正的 bug 却会溜走。这是由 [@voidmatcha](https://github.com/voidmatcha) 为 [Claude Code](https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview)、Codex 和 OpenCode 提供的 Agent Skills 捆绑包,专门捕获 CI 容易遗漏的问题:**通过却没有任何证明力的测试**,以及**难以追踪的失败**。
涵盖整个 E2E 生命周期的四个互补技能:
1. **`playwright-test-generator`** — 从零开始生成 Playwright E2E 测试,涵盖从覆盖率差距分析到通过审查的完整流程
2. **`e2e-reviewer`** — 对现有的 Playwright 和 Cypress spec 进行静态分析;标记 19 种反模式(P0 静默总是通过,P1 诊断性差,P2 维护成本高),这些反模式可能导致测试通过 CI 却遗漏了真实的回归
3. **`playwright-debugger`** — 从 `playwright-report/` 诊断失败原因,并对根本原因进行分类(不稳定的时序、选择器偏移、身份验证、环境不匹配等)
4. **`cypress-debugger`** — 针对 Cypress 报告文件执行相同的操作
### 目录
- [工作流](#workflow) · [独立扫描器](#standalone-scanner) · [开源证明](#proven-in-open-source) · [安装](#installation)
- 技能:[生成器](#skill-1-playwright-test-generator--test-generation) · [审查器](#skill-2-e2e-reviewer--quality-review) · [playwright-debugger](#skill-3-playwright-debugger--playwright-failure-debugger) · [cypress-debugger](#skill-4-cypress-debugger--cypress-failure-debugger)
- [与其他工具的对比](#comparison-with-other-tools) · [常见问题](#faq) · [兼容性](#compatibility)
### 工作流
1. 运行 `playwright-test-generator` → 生成并批准 → 由 `e2e-reviewer` 自动审查
2. 生成的测试失败 → 尝试 3 次修复后自动调用 `playwright-debugger`
3. 现有测试:`e2e-reviewer` → 修复 → 重新运行
4. 测试失败 → `playwright-debugger` 或 `cypress-debugger` → 修复 → 重新运行
### 独立扫描器
无需 agent 即可运行机械化的代码坏味道检查:
```
./scripts/e2e-smell-scan.sh path/to/tests
# 仅报告,永不导致 CI 失败
E2E_SMELL_FAIL_ON=none ./scripts/e2e-smell-scan.sh .
# 任何发现都视为失败,而不仅仅是 P0
E2E_SMELL_FAIL_ON=any ./scripts/e2e-smell-scan.sh .
```
该扫描器在第一遍时有意保持保守:它负责捕获明显的 P0/P1 级别的坏味道,然后由 `e2e-reviewer` 处理语义审查和误报判断。它也会报告合理的模式;请使用 `// JUSTIFIED:` 来解释意图,以便于人类和 agent 审查,而不是为了隐藏发现的问题。
### 在开源中得到验证
该检查清单基于真实的已合并开源工作,而不仅仅是合成示例:
| 代码库 | 已合并的 PR | 修复内容 |
|------------|-----------|---------------|
| Cal.com | [calcom/cal.diy#28486](https://github.com/calcom/cal.diy/pull/28486) | 将虚假通过的 Playwright 断言、空操作的状态检查以及硬编码的等待,替换为 web-first 断言和条件等待 |
| Storybook | [storybookjs/storybook#34141](https://github.com/storybookjs/storybook/pull/34141) | 修复了未等待的 Playwright 操作和被丢弃的 `isVisible()` 调用,这些问题使得 E2E 检查在悄无声息中变得形同虚设 |
| Element Web | [element-hq/element-web#32801](https://github.com/element-hq/element-web/pull/32801) | 移除了总是通过的断言、未等待的检查、`toBeAttached()` 的误用以及调试残留代码 |
有关这些 PR 中简短的经验教训(修改前/后对比),请参阅[开源案例研究](docs/case-studies.md)。
### 开源资产
| 资产 | 用途 |
|-------|---------|
| [E2E 测试坏味道分类法](docs/e2e-test-smells.md) | P0/P1/P2 坏味道模型的可共享参考 |
| [`scripts/e2e-smell-scan.sh`](scripts/e2e-smell-scan.sh) | 无需 Agent 的明显 E2E 坏味道模式扫描器 |
| [`scripts/ci/ci-local.sh`](scripts/ci/ci-local.sh) | 用于约定、安全性、评估、扫描器以及模式/描述对等性检查的本地镜像 |
| [GitHub Action](.github/workflows/e2e-smell-scan.yml) | CI 示例,运行约定/安全检查、扫描器检查并上传报告 |
| [评估](docs/evals.md) | 如何验证和扩展 skill 评估定义 |
| [框架范围](docs/framework-scope.md) | 明确的 Playwright/Cypress 支持边界 |
| [Agent 兼容性](docs/agent-compatibility.md) | Claude Code、Codex 和 OpenCode 的设置说明 |
## 安装
```
# Claude Code / Codex / OpenCode 快速安装:安装全部四项 skill
npx skills add voidmatcha/e2e-skills --skill '*' -g -a claude-code -a codex -a opencode
# 如果 skills CLI 已安装,跳过 npx:
skills add voidmatcha/e2e-skills --skill '*' -g -a claude-code -a codex -a opencode
# 安装到每个受支持的 agent:
npx skills add voidmatcha/e2e-skills --skill '*' -g --agent '*'
# Alternative: Claude Code 插件市场
/plugin marketplace add voidmatcha/e2e-skills
/plugin install e2e-skills@voidmatcha
# Codex 插件(通过 Codex 市场 UI 注册;读取 .codex-plugin/plugin.json)
# Claude Code 手动克隆
mkdir -p ~/.claude/skills
git clone https://github.com/voidmatcha/e2e-skills.git ~/.claude/skills/e2e-skills
```
## Skill 1: `playwright-test-generator` — 测试生成
为任何项目从零开始生成 Playwright E2E 测试。从覆盖率差距分析开始,通过 agent-browser 工具探索线上应用,在您批准后设计场景,并使用 `e2e-reviewer` 自动审查生成的测试。
### 适用场景
- 您有一个没有 E2E 覆盖的页面或功能
- 您想为现有应用引导建立一套测试用例
- 您需要在发布前快速添加测试
### 用法
```
Generate playwright tests
Generate playwright tests for the login page
Write e2e tests for the settings page
Add playwright coverage for checkout flow
```
### 流程
```
Step 1: Detect environment (config, baseURL, test dir, POM structure)
Step 2: Coverage gap analysis → user picks target
Step 3: Live browser exploration via agent-browser tools
Step 4: Scenario design → approval gate → user approves
Step 5: Code generation (POM + spec or flat spec, auto-detected)
Step 6: YAGNI audit + e2e-reviewer quality gate
Step 7: TS compile + test run → playwright-debugger on failure
```
### 关键行为
- **结构感知**:检测 POM 模式并匹配项目约定
- **无幻觉选择器**:在编写任何代码之前先探索真实的 DOM
- **批准关卡**:在生成代码之前展示场景计划和定位器表格
- **质量循环**:YAGNI 审计移除未使用的定位器;`e2e-reviewer` 在您真正运行测试之前捕获 P0 级别的问题
- **自我修复**:失败时进行 3 次自动修复尝试,然后移交给 `playwright-debugger`
## Skill 2: `e2e-reviewer` — 质量审查
捕获那些能通过 CI 却未能捕获真实回归的 E2E 测试中的问题。
### 适用场景
- 您的测试总是通过,但 bug 依然会溜进生产环境
- 测试通过了 CI,但您怀疑它们遗漏了真实的回归
- 您的测试套件非常脆弱——每次 UI 变更都会导致测试中断
- 您想在发布或代码审查之前审计测试质量
- 您正在审查 Playwright 或 Cypress 的 spec
### 用法
```
Review my E2E tests
Audit the spec files in tests/
Find weak tests in my test suite
My tests always pass but miss bugs
Tests pass CI but miss regressions
My tests are fragile and break on every UI change
We have coverage but bugs still slip through
```
### 检测到的 19 种模式 — 按严重程度分组
#### P0 — 必须修复 (静默总是通过)
当功能损坏时测试仍然通过。没有发生真正的验证。
| # | 模式 | 修改前 | 修改后 |
|---|---------|--------|-------|
| 1 | **名称与断言不匹配** | 名称写着 "status" 但只检查了 `toBeVisible()` | 为状态内容添加断言,或重命名以匹配实际检查 |
| 2 | **缺少 Then** | 取消操作,验证文本已恢复 —— 但输入框仍然可见? | 同时验证恢复的状态和已消失的状态 |
| 3 | **错误被吞没** | spec 中的 `try/catch`,POM 中的 `.catch(() => {})` | 让错误直接失败;从 POM 方法中移除静默捕获 |
| 3b | **Cypress `uncaught:exception` 抑制** | `cy.on('uncaught:exception', () => false)` 全局屏蔽了应用错误 | 将处理程序的作用域限定为特定的已知错误;重新抛出未知错误 |
| 4 | **总是通过的断言** | `toBeGreaterThanOrEqual(0)`;无注释的 `toBeAttached()`;`expect(await el.isVisible()).toBe(true)` (单次);`expect(await el.textContent()).toBe(x)` (单次);`expect(locator).toBeTruthy()` (Locator 总为真);断言上的 `{ timeout: 0 }` (禁用重试) | `toBeGreaterThan(0)`;`toBeVisible()`;具有自动重试功能的 web-first 断言 |
| 5 | **绕过模式** (5a P0, 5b P1) | `if (await el.isVisible()) { expect(...) }`;无注释的 `{ force: true }` | 必须总是进行断言;将环境检查移至 `beforeEach`;为 force:true 添加 `// JUSTIFIED:` |
| 7 | **聚焦测试泄漏** | 提交了 `test.only(...)` —— CI 只运行一个测试,静默跳过了其余测试 | 删除 `.only`;在本地聚焦时使用 `--grep` 或 `--spec` |
| 8 | **缺少断言** | `await page.locator('.x');` (被丢弃);`await el.isVisible();` (布尔值被丢弃) | 添加 `await expect(locator).toBeVisible()` 或删除该行 |
| 12 | **缺少身份验证设置** | 受保护路由的 spec 导航到 `/dashboard` 而没有 login/`storageState`/auth fixture | 添加 `beforeEach` 登录,配置 `storageState`,或使用 auth fixture —— 否则测试将通过只检查登录页而通过 |
| 15 | **`expect()` 缺少 `await`** | `expect(page.locator('.toast')).toBeVisible()` 返回了一个未观察到的 Promise | 添加 `await` 以便断言实际运行 |
| 16 | **操作缺少 `await`** | `page.locator('#submit').click()` 可能在下一行之前未执行 | 添加 `await` 以便操作完成 |
#### P1 — 应该修复 (诊断性差 / 浪费 CI 时间)
测试虽然工作,但会误导开发者、浪费 CI 时间,或为未来的回归埋下隐患。
| # | 模式 | 修改前 | 修改后 |
|---|---------|--------|-------|
| 6 | **原始 DOM 查询** | `evaluate()` 中的 `document.querySelector` | 使用框架 locator/query API (`locator` / `cy.get`) |
| 9 | **硬编码休眠** | `waitForTimeout(2000)` / `cy.wait(2000)` | 依赖框架自动等待;使用基于条件的等待 |
| 10 | **不稳定的测试模式** | 无注释的 `items.nth(2)`;`test.describe.serial()` | 使用 `data-testid` 或角色选择器;用独立的测试替换 serial |
| 13 | **POM 使用不一致** | 导入了 POM,但 spec 对 POM 拥有的操作使用了原始的 `page.fill`/`page.click` | 将所有交互路由通过 POM,以便 UI 更改只需在一处更新 |
| 14 | **硬编码凭据** | 测试代码中的 `loginPage.login('admin', 'password123')` | 使用 `process.env.TEST_USER`、Playwright config 的 secrets,或测试数据 fixture |
| 17 | **直接使用 `page.click(selector)` API** | `page.click('#submit')` / `page.fill('#input', 'text')` 绕过了 Locator 层 | 使用 `page.locator(selector).click()` 以获得自动等待和更好的错误消息 |
| 18 | **`expect.soft()` 过度使用** | 测试中的所有断言都是 `expect.soft()` —— 测试永远不会提前失败 | 确保每个测试至少有一个硬 `expect()` 关卡;仅将 `soft` 用于独立的细节 |
#### P2 — 最好修复 (维护性 / 鲁棒性)
较弱但并非错误 —— 在重构时处理。
| # | 模式 | 修改前 | 修改后 |
|---|---------|--------|-------|
| 11 | **YAGNI + 僵尸 Spec** | `clickEdit()` 从未被调用;空包装类;单次使用的 Util;整个 spec 被另一个重复 | 删除未使用的成员;内联单次使用的 Util 方法;删除僵尸 spec 文件 |
### 完整审查面
在进行了 grep 和 LLM 检查之后,在场景级别审查该测试套件:
| 领域 | 审查问题 |
|------|------------------|
| 用户意图 | 测试名称是否与实际的断言相匹配?场景中的每个重要名词是否都得到了验证? |
| 选择器策略 | 定位器是否基于角色、标签、可访问名称或稳定的测试 ID,而不是 CSS 类、XPath 或 DOM 位置? |
| 等待模型 | 测试是否在等待真实的 UI、URL 或网络信号,而不是休眠?Playwright 的 `waitForResponse()` promise 是否在触发操作之前就已创建? |
| 隔离与状态 | 每个测试能否独立运行并并行?状态是否在 `beforeEach` 或 fixtures 中创建,而不是从先前的测试中继承? |
| 网络边界 | 第三方服务和不稳定/缓慢的 API 是否被 mock 或路由?路由/拦截处理程序是否在导航或触发请求的操作之前就已注册 |
| 身份验证与权限 | 受保护的页面是否使用了 `storageState`、auth fixture 或显式登录?是否涵盖了过期会话和角色边界状态? |
| 可访问性 | 流程是否涵盖了键盘导航、对话框后的焦点转移、控件的标签/名称以及关键的 ARIA 状态? |
| 视觉信心 | 如果测试主要检查布局或样式,是否应该使用视觉差异对比而不是许多脆弱的 CSS 断言? |
| CI 诊断 | Playwright trace 是否在第一次重试时被捕获,Cypress 的屏幕截图/视频或 Test Replay 是否可用,并且报告是否作为 artifacts 上传? |
| 测试范围 | 这真的是一个 E2E 关注点吗,还是逻辑密集的分支应该移至 unit/component/API 测试中?冒烟和回归路径是否已分离开来? |
### 参考资料
- [Playwright 最佳实践](https://playwright.dev/docs/best-practices)
- [Playwright 定位器](https://playwright.dev/docs/locators)
- [Playwright 自动等待与可操作性](https://playwright.dev/docs/actionability)
- [Playwright 测试隔离](https://playwright.dev/docs/browser-contexts)
- [Playwright 身份验证](https://playwright.dev/docs/auth)
- [Playwright 网络 Mock](https://playwright.dev/docs/network)
- [Playwright 可访问性测试](https://playwright.dev/docs/accessibility-testing)
- [Playwright Trace 查看器](https://playwright.dev/docs/trace-viewer)
- [Cypress 最佳实践](https://docs.cypress.io/app/core-concepts/best-practices)
- [Cypress 测试隔离](https://docs.cypress.io/guides/core-concepts/test-isolation)
- [Cypress 会话](https://docs.cypress.io/api/commands/session)
- [Cypress 重试能力](https://docs.cypress.io/guides/core-concepts/retry-ability)
- [Cypress 拦截](https://docs.cypress.io/api/commands/intercept)
- [Cypress 屏幕截图和视频](https://docs.cypress.io/app/guides/screenshots-and-videos)
- [Cypress 视觉测试](https://docs.cypress.io/guides/tooling/visual-testing)
- [Testing Library 指导原则](https://testing-library.com/docs/guiding-principles)
### 审查工作流
具有 P0/P1/P2 严重程度的三阶段审查:
1. **阶段 1:自动化 grep** —— 机械地检测 #3 (POM `.catch()`)、#3b (Cypress `uncaught:exception`)、#4 (总是通过)、#5 (绕过模式)、#6 (原始 DOM 查询)、#7 (聚焦测试泄漏)、#8 (缺少断言)、#9 (硬编码休眠)、#10 部分 (位置选择器、describe.serial)、#14 (硬编码凭据)、#15 (expect 缺少 await)、#16 (操作缺少 await)、#17 (直接使用 page 操作 API) 以及 #18 (`expect.soft()`)
2. **阶段 2:LLM 分析** —— #1 名称-断言对齐、#2 缺少 Then、#3 spec 中的 `try/catch` (上下文相关)、#4 `.toBeTruthy()` Locator 主题确认、#8 Cypress 悬空选择器、#10 不稳定模式判断、#11 YAGNI + 僵尸 spec、#12 身份验证设置、#13 POM 一致性、#15 缺少-await-on-expect Locator 确认、#16 缺少-await-on-action 确认,以及 #18 `expect.soft()` 过度使用确认
3. **阶段 3:覆盖缺口** —— 建议补充缺失的错误路径、边缘情况、可访问性、auth 边界、网络故障状态、视觉回归以及 CI 可观测性缺口
## Skill 3: `playwright-debugger` — Playwright 失败调试器
从 `playwright-report/` 目录诊断 Playwright 测试失败原因 —— 无论失败发生在本地还是 CI 中。对根本原因进行分类并提供具体的修复方案。
### 适用场景
- 您有一个包含待理解失败的 `playwright-report/` 目录(本地或从 CI 下载)
- 测试在本地通过但在 CI 中失败
- 您正在处理不稳定或间歇性的测试失败
- 您遇到了 `TimeoutError` 或 `locator not found`,但没有明确的原因
### 用法
```
Debug these failing tests
Why did these tests fail?
Tests pass locally but fail in CI
```
### 14 种根本原因分类
| # | 类别 | 信号 |
|---|----------|---------|
| F1 | **不稳定 / 时序** | `TimeoutError`,重试后通过 |
| F2 | **选择器损坏** | `locator not found`,strict mode 违规 |
| F3 | **网络依赖** | `net::ERR_*`,意外的 API 响应 |
| F4 | **断言不匹配** | `Expected X to equal Y`,主题倒置 |
| F5 | **缺少 Then** | 操作完成但保留了错误的状态 |
| F6 | **缺少条件分支** | 元素有条件地出现,断言总是运行 |
| F7 | **测试隔离失败** | 单独运行通过,在套件中失败 |
| F8 | **环境不匹配** | 仅在 CI 与本地出现;viewport、OS、时区 |
| F9 | **数据依赖** | 缺少种子数据,硬编码的 ID |
| F10 | **身份验证 / 会话** | 会话过期,基于角色的 UI 未渲染 |
| F11 | **异步顺序假设** | `Promise.all` 顺序,并行竞争 |
| F12 | **POM / Locator 偏移** | DOM 结构已更改,POM 未更新 |
| F13 | **错误被吞没** | `.catch(() => {})` 隐藏了实际的失败 |
| F14 | **动画竞争** | 元素可见但内容尚未渲染 |
### 调试工作流
1. **提取** —— 解析 `results.json` 以获取失败的测试、错误消息、持续时间
2. **分类** —— 使用错误信号将每个失败映射到 F1–F14(大多数失败在此步骤解决)
3. **追踪** —— 如果仍不清楚,则提取 `trace.zip` 并逐步检查:失败的操作、DOM 快照、网络错误、JS 控制台错误
4. **修复** —— 针对每个失败提供具体的代码建议,按 P0/P1/P2 优先级排序
## Skill 4: `cypress-debugger` — Cypress 失败调试器
从 mochawesome 或 JUnit 报告文件诊断 Cypress 测试失败原因。对根本原因进行分类并提供具体的修复方案。
### 适用场景
- 您有一个包含待理解失败的 `cypress/reports/` 目录(本地或从 CI 下载)
- Cypress 测试在本地通过但在 CI 中失败
- 您正在处理不稳定或间歇性的 Cypress 失败
- 您遇到了 `Timed out retrying` 或 `Expected to find element`,但没有明确的原因
### 用法
```
Debug these failing Cypress tests
Why did these Cypress tests fail?
Analyze cypress/reports/
Cypress tests pass locally but fail in CI
```
### 14 种根本原因分类
| # | 类别 | 信号 |
|---|----------|---------|
| F1 | **不稳定 / 时序** | `Timed out retrying`,重试后通过 |
| F2 | **选择器损坏** | `Expected to find element`,`cy.get() failed` |
| F3 | **网络依赖** | `cy.intercept()` 未匹配,`XHR failed` |
| F4 | **断言不匹配** | `expected X to equal Y`,`AssertionError` |
| F5 | **缺少 Then** | 操作完成但保留了错误的状态 |
| F6 | **缺少条件分支** | 元素有条件地出现,断言总是运行 |
| F7 | **测试隔离失败** | 单独运行通过,在套件中失败 |
| F8 | **环境不匹配** | 仅在 CI 与本地出现;baseUrl、viewport、OS |
| F9 | **数据依赖** | 缺少种子数据,`cy.fixture()` 不匹配 |
| F10 | **身份验证 / 会话** | `cy.session()` 过期,基于角色的 UI 未渲染 |
| F11 | **异步顺序假设** | `.then()` 链式顺序,并行 `cy.request()` 竞争 |
| F12 | **选择器偏移** | DOM 已更改,自定义命令或 POM 选择器未更新 |
| F13 | **错误被吞没** | `cy.on('uncaught:exception', () => false)` 隐藏了失败 |
| F14 | **动画竞争** | 元素可见但内容尚未渲染 |
### 调试工作流
1. **提取** —— 解析 `mochawesome.json` 或 JUnit XML 以获取失败的测试、错误消息、持续时间
2. **分类** —— 使用错误信号将每个失败映射到 F1–F14(大多数失败在此步骤解决)
3. **屏幕截图/视频** —— 如果仍不清楚,检查 `cypress/screenshots/` 和 `cypress/videos/`
4. **修复** —— 针对每个失败提供具体的代码建议,按 P0/P1/P2 优先级排序
## 与其他工具的对比
| 工具 | 它是什么 | 捕获内容 | 局限性 |
|------|------------|---------|--------|
| **`e2e-reviewer`** (此 skill) | Agent skill:grep + LLM 语义审查 | 所有 19 种反模式,包括名称-断言不匹配、缺少 Then、YAGNI/僵尸 spec | 需要 agent 运行时 (Claude Code、Codex 或 OpenCode) |
| **`e2e-smell-scan.sh`** (此代码库) | 独立的 shell 扫描器 | 可通过 grep 检测到的 P0/P1 子集 (总是通过、`force: true`、`.only`、缺少 await、硬编码休眠) | 遗漏了语义检查 (#1 名称-断言、#2 缺少 Then、#11 僵尸 spec) |
| [`eslint-plugin-playwright`](https://github.com/playwright-community/eslint-plugin-playwright) | ESLint 插件 | Playwright lint 规则:缺少 await、no-focused-test、no-conditional-in-test | 仅限 Playwright;不支持 Cypress;无语义的名称-断言检查 |
| [Playwright 最佳实践文档](https://playwright.dev/docs/best-practices) | 参考指南 | 官方指南 —— 定位器、web-first 断言、隔离 | 未强制执行;需要审查器/扫描器来捕获偏差 |
| 原始 `grep` 模式 | DIY | 取决于您编写的内容 | 如果没有 `// JUSTIFIED:` 约定,误报率很高 |
`e2e-reviewer` 在理念上最接近 `eslint-plugin-playwright`,但它涵盖了这两个框架,并增加了 ESLint 无法推断的语义检查(名称-断言对齐、缺少 Then 状态恢复、僵尸 spec)。
## 常见问题
**这与 `eslint-plugin-playwright` 有何不同?**
ESLint 捕获语法模式(缺少 await、聚焦测试、测试中的条件语句)。`e2e-reviewer` 增加了 LLM 可以执行的语义检查 —— 测试名称是否与断言的内容匹配,操作是否同时验证了新状态和已消失的先前状态,POM 成员是否实际被使用。它还支持 Cypress。
**我需要同时使用 `e2e-reviewer` 和独立扫描器吗?**
不需要。独立扫描器是面向没有 agent 运行时的项目的、兼容 CI 的子集。如果您使用 Claude Code / Codex / OpenCode,`e2e-reviewer` 会完成扫描器所做的一切,外加仅限 LLM 的检查。
**为什么我的测试通过了 CI 却仍然遗漏了 bug?**
最常见的原因是名称-断言不匹配 (#1)、总是通过的断言如 `toBeAttached()` 或 `toBeGreaterThanOrEqual(0)` (#4)、缺少 `await` (#15, #16),以及缺少身份验证设置导致测试在仅触及登录页时就通过 (#12)。`e2e-reviewer` 会标记所有这些问题。
**这需要修改我现有的测试吗?**
不需要 —— `e2e-reviewer` 和调试器默认都是只读的。它们负责产出发现的问题;由您决定修复什么。`playwright-test-generator` 会编写新的测试文件(需要在场景关卡处获得您的批准)。
**它适用于仅限 TypeScript 的代码库吗?**
是的。Playwright 和 Cypress 项目均通过配置文件(`playwright.config.{ts,js}`、`cypress.config.{ts,js}`)和常规报告目录(`playwright-report/`、`cypress/reports/`)进行检测。
**我可以抑制误报吗?**
可以 —— 在模式上一行(或在封闭块/多行链上方)添加 `// JUSTIFIED: `。扫描器和审查器都会遵循此规则。用它来向下一位审查者解释意图,而不是为了静默隐藏发现的问题。
**它支持其他 E2E 框架吗?**
不支持。范围很明确:仅限 Playwright 和 Cypress。有关超出范围的框架的完整列表及其理由,请参阅[框架范围](docs/framework-scope.md)。
## 兼容性
**`playwright-test-generator`** — 仅限 Playwright。为任何具有 `playwright.config.ts` 的项目生成测试。使用 agent-browser 工具进行实时探索;回退到 `npx playwright codegen` 进行手动选择器发现。
**`e2e-reviewer`** — 涵盖 [Playwright](https://playwright.dev/) 和 [Cypress](https://www.cypress.io/),提供完整的 grep + LLM。通用原则(名称-断言对齐、缺少 Then、YAGNI)适用于任何框架。
**`playwright-debugger`** — 仅限 Playwright。解析 `playwright-report/` 中的 `results.json` 和 `trace.zip`。
**`cypress-debugger`** — 仅限 Cypress。解析 `cypress/reports/` 中的 `mochawesome.json` 或 JUnit XML。
## 许可证
Apache-2.0 — 与 [anthropics/skills](https://github.com/anthropics/skills) 相同。
标签:AI编程助手, Anchore, Bug调试, Claude Code, Codex, Cutter, Cypress, E2E测试, Flaky测试处理, OpenCode, Playwright, SOC Prime, 云安全监控, 代码审查, 前端测试, 反模式检测, 大语言模型应用, 开发工具, 数据管道, 测试报告分析, 测试生成, 测试维护, 测试覆盖率, 测试质量, 特征检测, 端到端测试, 自动修复, 自动化安全运营, 软件工程, 静态分析