关于 e2e
e2e 是用于构建和运行端到端 UI 测试的技能,将 AI Agent 目标与精确检查结合,支持 Web 和移动端目标。
主要功能
- 01Agent 驱动的 UI 目标
- 02精确操作与断言
- 03Web 和移动端目标
- 04通过轨迹调试测试
- 05重放已通过目标的缓存
适用场景
- 01测试 Web 应用中的用户流程
- 02检查 iOS 或 Android 上的 UI 行为
- 03探索流程时编写测试
- 04根据轨迹诊断失败测试
MCP 相关
该技能介绍使用项目的 `e2e mcp` 服务,在编写或修复测试时实时探索应用、观察界面并定位元素。测试通过命令行编写和运行。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ tester-army/ e2e --skill e2e安装后在 Claude Code 中输入/e2e确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/agent.mdbug-bash.mddebugging.mdexplore.mdmcp.mdrunning.mdsetup.mdwriting-tests.md详细介绍
e2e:Agent 端到端测试
e2e 运行将 Agent 目标与精确步骤相结合的 UI 测试。agent.act 驱动一个目标;agent.assert、agent.waitFor 和 agent.extract 用于判断屏幕状态;screen、app、browser 和 expect 用于执行操作和精确检查。UI 目标使用 @e2e-dev/web 操作浏览器,或使用 @e2e-dev/mobile 操作 iOS 模拟器、Android 模拟器和已连接的手机。
从这里开始:根据任务选择参考文档
开始前,请先阅读与请求对应的参考文档。每篇文档都可独立阅读;文档仅会在需要补充阅读时提及其他主题。npx e2e guide <topic> 会输出已安装软件包中的对应版本参考文档;如果它与本副本不同,请优先采用该版本。
以下“规则”和“反馈”部分仍然适用。
| 当你需要 | 主题 | 阅读 |
|---|---|---|
为项目添加 e2e、编写 e2e.config.ts、从配置中启动应用、登录模型、设置移动端目标 | setup | references/setup.md |
查看正在运行的应用、检查 UI 变更、截取屏幕截图或录制视频、尝试定位器,或在编写测试时走查流程;通过 e2e mcp 操作 | mcp | references/mcp.md |
编写或修复测试:测试夹具、定位器、操作、匹配器、登录会话、browser 夹具、仅 API 测试 | writing-tests | references/writing-tests.md |
添加 agent.* 步骤、选择模型、降低成本、设置预算、使用回放缓存 | agent | references/agent.md |
运行测试:CLI 标志、CI、报告器、跟踪页面、供脚本使用的 report.json、退出代码 | running | references/running.md |
处理失败的运行:错误代码及其修复方法、--headed、--debug、--ai-trace | debugging | references/debugging.md |
不使用测试文件,围绕某个目标探索应用:e2e explore、其预算和判定结果 | explore | references/explore.md |
| 受托进行缺陷突击测试、QA,或在整个应用或某个分支中查找缺陷 | bug-bash | references/bug-bash.md |
对于参考文档未涵盖的内容,已安装的 e2e 软件包中的 docs/ 目录提供完整文档(单软件包项目中位于 node_modules/e2e/docs);像 /reference/cli 这样的链接对应 docs/reference/cli.mdx。Vite、Next.js、Astro、Angular、Expo、SwiftUI、Jetpack Compose、Kotlin Multiplatform、Flutter 和 .NET MAUI 的完整项目示例位于 https://github.com/tester-army/e2e/tree/main/examples。
快速开始
包含一个 Web 目标和一个模型的配置,以及一个用于驱动单个目标并锁定结果的测试:
// e2e.config.ts
import type { E2EConfig } from 'e2e';
import { web } from '@e2e-dev/web';
import { gateway } from 'ai';
export default {
targets: [
{
engine: web(),
app: {
url: 'http://127.0.0.1:3000',
command: { executable: 'pnpm', args: ['dev'], log: '.e2e/logs/app.log' },
},
},
],
// The model behind every agent.* step: an AI SDK instance; gateway() from 'ai' reads AI_GATEWAY_API_KEY or a Vercel OIDC token.
agents: {
default: {
model: gateway('openai/gpt-6-luna-fast'),
system: 'You are a thorough QA agent. Verify every outcome on screen.',
},
},
} satisfies E2EConfig;
// tests/billing.e2e.ts
import { test } from '@e2e-dev/web';
import { expect } from 'e2e';
test('a member upgrades to Pro', async ({ app, agent, screen, browser }) => {
await app.open('/settings/billing');
await agent.act('upgrade the workspace to the Pro plan');
await expect(screen.getByRole('status')).toContainText('Pro');
await expect(browser).toHaveURL('/settings/billing');
});
工作流:编写测试
- 查看现有内容:
e2e.config.ts、.mts、.js或.mjs、testsglob(默认为tests/**/*.e2e.ts),以及package.json中的e2e。如果这些都没有:当用户要求进行 e2e 测试时,按setup操作(见 Rules)。 - 连接了
e2e mcp服务(主题mcp)时,边走流程边编写测试,不要走完流程后凭记忆编写。之后再写的测试,每次运行都会因为你弄错的名称或步骤而失败,一次只暴露一个问题。在open_session之前,先创建tests/<feature>.e2e.ts,并从它覆盖的屏幕开始(第 3 步)。然后在会话中执行每一步时,将其添加到文件中。在走对应路径之前,先写入act目标;路径中的操作不要写入测试。screen行就是操作打印出的Test line:,照原样复制。显示结果后,用locate定位,并添加expect。流程走完时,测试也就写好了。没有服务时,从组件或--headed运行中了解应用呈现的可访问名称。 - 一步指一个
agent.act目标或screen行。使用agent.act驱动流程,每次调用只设一个原子目标,并在操作后立即用expect或agent.assert固定每个结果。有三个目标的测试需要调用三次。测试应从其覆盖的屏幕开始,因为每次重跑都要为此前的步骤付出成本:浏览器中使用已保存会话,而不是登录表单,并让app.open打开该屏幕的路径;设备上使用device.openLink;数据则来自应用的 API(主题writing-tests)。精确值应通过screen获取:设置测试中的登录表单、必须接收某个特定字符串的字段,以及必须为某个数字的计数。 - 只运行正在处理的测试:
npx e2e run tests/<feature>.e2e.ts:<line>,其中行号是test(所在的行,并添加下文“修复测试时重新运行”中的标志。Agent 步骤需要在配置中指定模型,并完成对应提供商的身份验证(已保存的订阅登录、API 密钥);本地端点可能不需要身份验证。不含 Agent 步骤的测试不需要模型。 - 测试失败时,根据运行记录进行修复(见下一节)。
工作流:修复失败的测试
运行记录已经包含失败前看到的所有屏幕。根据记录进行修复;绝不要为了查看屏幕而再次通过 MCP 从头走一遍流程。
- 阅读终端中的失败信息块:失败行及其代码上下文、消息(断言中的
expected和observed)、屏幕所在位置(❯ at:Web 上的 URL,设备上的应用和屏幕标题),以及失败定位器附近的节点(❯ on screen)。然后阅读其中提到的跟踪页面(❯ trace .e2e/results/<test>/trace.md):其中记录了每一步执行的操作、应用日志、Agent 的各轮交互,以及## Screen at failure,也就是每行一个节点的屏幕内容(主题debugging)。 - 修复证据能够佐证的所有行,而不只是失败的那一行:失败时的屏幕会显示该屏幕其余行所需的名称。修复定位器、预期值或应用。绝不要添加休眠或固定延迟(
setTimeout、waitForTimeout):改用agent.waitFor('<that state>')等待所需状态(主题agent;需要模型)。 - 测试会在第一个失败步骤处停止(
expect.soft会让它继续运行),每个后续的错误行都会导致再次运行。重新运行前,尽可能根据失败时的屏幕、应用源代码或实时会话检查后续行。 - 对于证据和源代码都未涵盖的屏幕,实时查看(主题
mcp):打开或复用会话,直接前往该屏幕,然后执行observe和locate。在 Web 上,使用navigate前往❯ atURL 的路径或屏幕路由;只有当 URL 无法打开所需状态时才点击。在设备上,会话从应用启动屏幕开始:从那里选择最短路径。 - 按下一节所述只重新运行该测试(主题
mcp会说明何时必须先关闭会话)。重复以上步骤,处理下一个失败。
修复测试时重新运行
每次运行失败的测试,都要等它失败后才能结束;每次实时运行 agent.act,都会消耗模型调用。每次重新运行都只针对一个测试和你修改的代码行:
- 按
file:line运行,而不是运行整个文件或测试套件。在测试上方编辑代码后,重新查找其test(行:行号过时会导致运行另一个测试,或失败并以NO_TESTS列出各测试的起始行号。 - 添加
--action-timeout 5000:未匹配到任何内容的定位器会在 5 秒后失败,而不是等待默认的 30 秒。它还会限制 Agent 步骤中的每个操作,因此设置的时间应长于屏幕加载所需的最长时间。screen调用自身的{ timeout }仍然优先。 expect默认会在 5 秒后放弃(assertionTimeout)。- 保持重放缓存开启。运行失败时,会保留所有检查通过的目标对应的录制;下次运行会重放这些目标,不调用模型。新目标、已更改目标和失败目标会实时运行;追踪页面显示已移交的重放也会实时运行。
agent.assert、agent.waitFor和agent.extract始终会调用模型。不要启用--no-cache:它会再次将每个目标都发送给模型。只有read-write缓存会进行录制:这是本地默认模式,但在设置了CI且配置中未指定缓存模式时,以及严格模式下,都不会进行录制。中止的运行(Ctrl-C、被工具的超时终止的命令、--max-duration)不会保存任何内容,因此命令的超时时间应长于测试运行时间。 - 不要重命名测试、其
describe或文件,也不要改写目标、修改其参数,或在目标通过后更改 Agent 的context或测试的agentContext。这些都是录制键的一部分,因此它们涉及的每个目标都会再次实时录制。修复定位器或断言则会保留录制。 - 启用重试时,添加
--retries 0(配置中的retries,或设置了CI时,默认值为 1);测试或其describe上的retries选项优先于此标志。在严格模式(--strict-cache、cache.strict)之外,重试永远不会重放:它会实时运行每个目标,并再次等待失败。 - 测试通过后,移除
--action-timeout,并使用--no-cache运行一次:每个目标都会按配置的超时时间实时运行,以此确认 Agent 即使没有录制也能完成测试。
规则
- 如果项目没有端到端测试,而用户要求添加,就进行设置。否则,在添加测试框架前先询问,并说明已有的框架。
- 实时 MCP 工具需要在客户端注册项目自己的
e2e mcp服务(主题mcp);编写和运行测试时直接使用 CLI。编写或修复 Web 测试时,要在多次运行之间保持会话开启;主题mcp会说明何时可以在该会话旁运行,以及遇到APP_ALREADY_RUNNING时该怎么做。 - 以
npx e2e ...(或pnpm exec e2e ...)运行 CLI。 - 配置采用
export default { ... } satisfies E2EConfig,并使用import type { E2EConfig } from 'e2e'。必须设置targets;UI 目标要指定引擎,并在其旁声明应用:{ engine: web(), app: { url, command } }。仅含工具的目标可以省略引擎并设置platform。 - 从
e2e导入test、describe、钩子、expect、credentials和secrets。使用browserfixture 的测试要从@e2e-dev/web导入test、describe和钩子:这些是相同的运行时函数,但类型中包含browser。 - 无论
package.json将type设置为何值,配置和测试都是 ES 模块。 - 定位器在使用时解析。操作会等待就绪,
expect会重试断言。textContent()等读取操作会等待,直到找到一个匹配项或达到操作超时时间,然后返回当前值;count()和isVisible()则根据当前屏幕作答。没有任何操作会等待值发生变化,因此值需要稳定下来时,请使用匹配器。 - 如果定位器匹配到两个节点,就会报错
LOCATOR_AMBIGUOUS;请缩小匹配范围(主题writing-tests)。 - 密钥不得出现在测试代码中。在配置的
credentials下声明账户,在secrets下声明所有其他敏感值;通过credentials.user(name).password或secrets.get(name)获取(两个命名空间相互独立:secrets.get永远不会返回密码),并且只将不透明的Secret传给fill()或agent.act参数。 - Agent 指令:每次
act只设一个目标,使用屏幕上的措辞,并在参数中提供实际值。目标必须是原子性的:一次检查能够确认的一个结果。值得检查的两个结果就是两个目标,因此要拆成两次act调用(主题agent)。错误示例:'add a todo and mark it done'。正确示例:'add a todo',进行检查,然后执行'mark the todo as done',再进行检查。应判断含义,而非措辞:使用toContain('Pro'),不要要求模型生成完全匹配的句子。 - 检查每个 Agent 目标是否达成。带有已记录检查的
act即使通过,也可以缓存并重放,而无需调用模型(主题agent)。 - 根据应用调整 Agent:用
context提供屏幕使用的词汇,用system说明其工作方式,用工具提供测试 API,并在agents下定义命名角色。步骤失败时,先收紧目标,再调整上下文,最后调整 Agent。 .e2e/是输出目录(包含report.json、results/、cache/、logs/;配置中的output会移动报告和产物,但不会移动cache/或应用日志)。读取其中的内容,但绝不编辑。
反馈
当 e2e 本身妨碍你工作时,可以提出告知 e2e 团队:出问题的命令或 API(bug)、误导你的文档或此技能(docs),或你需要但未找到的功能(feature)。每个问题只报告一次,在你找到绕过办法或放弃之后再报告。切勿报告:
- 被测应用的故障或其自身行为;
- 只遇到一次、之后无法复现的问题;
- 过时的 e2e 中出现的任何问题:该命令会拒绝运行,因此请升级(
npx e2e@latest upgrade),并先确认问题仍然存在。
先搜索现有问题(gh issue list -R tester-army/e2e --search "<words>");如果有匹配项,请在该问题下评论,而不要提交新报告。
bug 需要提供 --repro,并附上不包含应用内容、每次都能复现问题的步骤。如果没有此类步骤,或者复现问题需要展示你的应用,请省略 --repro:此时命令会打印一份预填好的 GitHub 问题,但不会发送任何内容;请向用户展示链接,并告知他们添加最小复现示例后提交。切勿自行提交问题。
先使用 --dry-run 运行,向用户展示将要发送的内容,并且只有在他们同意后才发送。
npx e2e feedback --type bug -m "<one or two sentences>" \
--repro "<steps that reproduce it every time>" --error-code LOCATOR_AMBIGUOUS \
--task "<what you were doing>" --expected "<...>" --actual "<error message>" \
--approach "<what you tried>" --command "<e2e command>" --agent "<agent / model>"
简要描述 e2e 的行为即可:切勿粘贴应用内容、页面文本、测试文件、私有应用的 URL 或凭据。名称中含有 secret 的环境变量和常见令牌格式会被编辑,但不要依赖此机制。发送后,请向用户提供它打印的参考 ID。