SuperAPI AI 工具集

cypress-flake-fixer

测试与质量

查看项目

更新于 10-26 08:50

技能介绍

用途

Cypress Flake Fixer 用于审计现有 Cypress 测试套件中导致间歇性失败的代码模式,并在不借助重试、延长超时或 force: true 掩盖问题的前提下进行修复。它适合以下场景:

  • 某个 Cypress 规格在本地通过但在 CI 中失败,或每隔几次运行就失败一次
  • 套件中包含 cy.wait(<数字>)、{ force: true } 或仅在特定顺序下通过的测试
  • 错误信息提及 "detached from the DOM"、"timed out retrying" 或 "is no longer attached"
  • 项目正在跨大版本升级 Cypress(12 至 16)
  • 需要对 Cypress 测试代码进行审查

若需从零编写新的 Cypress 测试,编码规范即可满足;本技能专注于诊断和修复现有套件。

主要能力

  • 零依赖扫描器:通过 Node.js 18 或更高版本运行,无需安装 Cypress。扫描器从最近的 package.json 读取 Cypress 版本,对已移除的 API 根据当前主版本判定为 error 或 warn。
  • 规则分级:扫描结果按规则编号(如 CY001、CY002 等)分级,并给出修复优先级顺序。
  • 修复指导:针对每条规则提供前后代码对比(references/anti-patterns.md),以及已移除 API 的迁移代码(references/removed-apis.md)。
  • 验证流程:强调在修改前记录基线失败率,修改后重复运行足够次数以确认修复有效。

使用方式

  1. 扫描:

    node ./scripts/scan-cypress.mjs <project-root>
    node ./scripts/scan-cypress.mjs <project-root> --json
    node ./scripts/scan-cypress.mjs <project-root> --strict
    node ./scripts/scan-cypress.mjs cypress/e2e/checkout.cy.ts
    

    使用 --list-rules 查看规则目录。扫描结果为启发式,需逐条确认后再修改。

  2. 修改前测量:记录目标规格的失败频率作为基线。例如:

    for i in $(seq 1 20); do npx cypress run --spec "cypress/e2e/checkout.cy.ts" --quiet || echo "FAIL $i"; done
    

    若规格每 10 次失败 1 次,修复后需约 30 次干净运行才能确认修复可信。

  3. 按顺序修复:

    • 优先级 1:CY002、CY003、CY007(error 级)——测试本身错误或已损坏
    • 优先级 2:CY001、intercept 顺序——基于时间的等待是 flake 最大来源
    • 优先级 3:CY005、CY006——重试能力损坏导致 detached-DOM 和一次性断言失败
    • 优先级 4:CY004——force: true 掩盖真实的重叠、动画或禁用状态
    • 优先级 5:CY008、CY010、CY012——状态泄漏和顺序依赖
    • 优先级 6:CY013、CY101、CY102——选择器和断言卫生
  4. 将每个固定等待替换为其所代表的真实条件:

    • 网络请求 → 在触发前注册 cy.intercept(...).as('x'),然后 cy.wait('@x')
    • 请求或状态变化后的渲染 → 对结果 DOM 使用 .should()
    • 防抖、节流、轮询间隔或 toast 超时 → 在 cy.visit() 前使用 cy.clock(),然后 cy.tick(ms)
    • CSS 动画或过渡 → 对最终状态断言
    • 服务端渲染 HTML 的客户端水合 → 应用在水合完成时设置的信号
    • 未知 → 在 npx cypress open 中运行,选中等待,查看期间发生的请求和 DOM 变化
  5. 验证:单独运行修改后的规格,重复至少与基线相同的次数;重新运行扫描器比较各规则计数;运行完整套件以捕获顺序依赖。

修复原则

  • 仅修改测试代码。若测试暴露了应用缺陷(重复提交、缺少加载状态、UI 竞态),应报告而非绕过。
  • 不要提高 defaultCommandTimeout、添加重试或添加 { force: true } 来让测试通过。
  • 不要将 cy.wait(2000) 替换为 cy.wait(5000),或对已存在的元素使用 .should('exist')。
  • 每次提交只包含一个规则类别,便于二分定位回归。
  • 优先修复 cypress/support 中的共享自定义命令。

适用场景与限制

  • 适用于诊断和修复现有 Cypress 套件中的 flake 问题,以及跨大版本升级时的 API 迁移。
  • 扫描器结果为启发式,需人工确认,可能存在误报;可通过 // cy-scan-ignore CY0xx 注释忽略。
  • 需要 Node.js 18 或更高版本运行扫描器,但扫描器本身不依赖 Cypress。
  • 修复效果需通过足够次数的重复运行验证,单次通过不足以证明修复有效。
  • 若配置中 testIsolation: false,顺序依赖失败属于预期行为而非 flake。
  • 重试会隐藏 flake,除非配置为报告模式(如 experimentalStrategy: 'detect-flake-but-always-fail')。
  • 部分规则(如 CY005)需根据具体场景判断,并非所有链式调用都需要拆分。

报告格式

技能提供标准报告模板,包含 Cypress 版本、扫描文件数、基线失败率、各规则修复前后计数、未修复项及原因、发现的应用问题、验证结果等。

故障排除

  • 扫描器报告 "No Cypress files found":传入包含 cypress/ 或 .cy. 文件的文件夹,或显式传入文件路径。
  • 误报:在同行或上一行添加 // cy-scan-ignore CY0xx 并注明原因。
  • 版本显示 "not detected":传入 --cypress-major <n>;在 monorepo 中从依赖 Cypress 的包运行扫描器。
  • 修复后仅在 CI 失败:比较视口、浏览器和 CPU,使用 CI 浏览器本地运行并限制 CPU。
  • cy.wait('@alias') 超时:检查 intercept 是否在请求后注册、URL 模式是否遗漏查询字符串(添加 *)、或请求是否来自缓存。

参考资料

  • references/anti-patterns.md:每条扫描规则的前后代码对比
  • references/removed-apis.md:按 Cypress 主版本列出的已移除 API 及迁移代码
  • Cypress retry-ability 文档
  • Cypress 迁移指南