migrate-to-e2e
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMigrate a suite to e2e
将测试套件迁移到 e2e
A migration is never one change. Each session ports one slice, proves it,
and leaves both suites green: the old runner keeps every test it had, and
the new e2e tests pass beside it. A progress file, , records
what moved, what is left, and why, so the next session, yours or another
agent's, starts from it instead of from scratch. The user decides when an old test goes.
MIGRATION.mdTwo references do most of the work. Read them; do not restate them.
- The e2e skill for everything the runner does: once
.agents/skills/e2e/SKILL.mdornpx e2e initran, ornpx skills add tester-army/e2efrom the installed package. Topics named below (npx e2e guide <topic>,setup,writing-tests,agent,mcp,running) are its reference files.debugging - The migration guide for the source runner, and the engine page it ports
to. The guide maps the runner's config, commands, and API to e2e, and
says what e2e does not have yet (marked or "No equivalent") with today's workaround. Both ship in the installed package under
missingwith the same paths asnode_modules/e2e/docs/files..mdx
Detect the source runner, then read both docs in its row in full, before
the inventory and before writing any code. Each later step leans on them.
| Source | Detect it by | Migration guide | Engine |
|---|---|---|---|
| Playwright | | migrate/playwright | web |
| Cypress | | migrate/cypress | web |
| Selenium | | migrate/selenium | web |
| Detox | | migrate/detox | mobile |
| Maestro | YAML flows opening with | migrate/maestro | mobile |
WebdriverIO and Appium have no guide. Map their WebDriver calls with the
Selenium guide; map Appium's device commands with the Detox and Maestro
guides, on the mobile engine. Tell the user the mapping is partial. A
project with two source runners migrates one at a time, one section of the
progress file each.
迁移从来不是靠一次改动完成的。每次会话移植一个切片、加以证明,并让两套测试都保持全绿:旧运行器保留原有的每个测试,新的 e2e 测试也在旁边通过。进度文件 记录已迁移的内容、剩余内容及其原因,使下一个会话——无论是你还是另一个 Agent——都能从该文件继续,而不是从头开始。何时移除旧测试由用户决定。
MIGRATION.md两份参考资料承担了大部分工作。阅读它们,不要复述它们。
- e2e skill 涵盖运行器执行的一切:运行 或
npx e2e init后读取npx skills add tester-army/e2e,或者从已安装的包中运行.agents/skills/e2e/SKILL.md。下列主题(npx e2e guide <topic>、setup、writing-tests、agent、mcp、running)是它的参考文件。debugging - 源运行器的迁移指南,以及它要移植到的引擎页面。指南会将运行器的配置、命令和 API 映射到 e2e,并说明 e2e 目前尚不具备哪些功能(标记为 或“No equivalent”),以及当前的临时解决方案。两者都随已安装的包一起提供,位于
missing下,路径与node_modules/e2e/docs/文件相同。.mdx
先检测源运行器,然后在清点测试套件和编写任何代码之前,完整阅读表格中对应行的两份文档。后续每个步骤都依赖它们。
| 来源 | 检测依据 | 迁移指南 | 引擎 |
|---|---|---|---|
| Playwright | | migrate/playwright | web |
| Cypress | | migrate/cypress | web |
| Selenium | | migrate/selenium | web |
| Detox | | migrate/detox | mobile |
| Maestro | 以 | migrate/maestro | mobile |
WebdriverIO 和 Appium 没有迁移指南。使用 Selenium 指南映射它们的 WebDriver 调用;在 mobile 引擎上使用 Detox 和 Maestro 指南映射 Appium 的设备命令。告知用户此映射并不完整。一个项目存在两个源运行器时,一次迁移一个,并在进度文件中分别使用一个章节。
1. Resume or start
1. 恢复或开始
Look for beside the e2e config, then at the repo root. When
one exists, this is a later session:
MIGRATION.md- Read it, then the migration guide and engine page its line names. Its
Sourcesection names the slice this session takes, unless the user names another.Next - Check it against the repo before trusting it: every test still exists in both suites, every source file or test it lists still exists (except
portedones, deleted on purpose), and no new source file or test is missing from it (add those asretired). Notodoline: ask as in step 2. A planted bug noted underDefect check:: revert it first (step 6).Next - Run the file's command once. A ported test that fails now is the first thing to fix, before any new slice.
Run new - Unless the progress file's line says
Harness:, go to step 3, Build the harness. Otherwise go to step 4, Pick the slice.done
No progress file means a first session: steps 2 and 3, then the rest.
先在 e2e 配置旁查找 ,然后在仓库根目录查找。找到该文件表示这是后续会话:
MIGRATION.md- 读取它,然后读取其 行指定的迁移指南和引擎页面。其
Source章节指定本次会话要处理的切片,除非用户指定了另一个切片。Next - 根据仓库核验后再信任它:每个标为 的测试仍应同时存在于两套测试中;它列出的每个源文件或测试仍然存在(
ported的除外,这些是有意删除的);任何新的源文件或测试都不得遗漏(将其添加为retired)。如果没有todo行:按步骤 2 的方式询问。若Defect check:下记录了植入的 bug:先撤销它(步骤 6)。Next - 运行文件中的 命令一次。此时失败的已移植测试是首要修复对象,必须先于任何新切片处理。
Run new - 除非进度文件的 行显示为
Harness:,否则转到步骤 3“构建 harness”;否则转到步骤 4“选择切片”。done
没有进度文件表示这是首次会话:执行步骤 2 和 3,然后继续其余步骤。
2. Inventory the suite (first session)
2. 清点测试套件(首次会话)
Answer these from the repo; ask the user only what you cannot observe.
| Question | Where the answer is | What it decides |
|---|---|---|
| Source runner | The detection table above | The two docs read before this table |
| Tests | Every spec, flow, or test file, with its titles, tags, and per-platform or per-browser branches. Count tests with the runner's own list or dry-run mode, not by grepping, which misses tests made in a loop. | The progress file's rows, one per source file. Count each file's assertions now so a port can be checked against the count: explicit ones ( |
| Shared code | Page objects, custom commands, subflows ( | Helpers to port once, before the first test that needs each |
| How it runs | The CI job that runs the suite and the scripts it calls: the build, the services and mock servers it starts, seed and reset calls, env files, devices or browsers, ports | The e2e harness. The CI job is usually the only complete description; read it line by line |
| Where e2e lives | A JavaScript or TypeScript project with a | The e2e config's location and the progress file's. The two runners must not collect each other's files: when the patterns overlap, narrow one of them. Playwright suites often name files |
| Can the old suite run here | The source runner installed, the build it needs, the services | Whether parity is checked against a live old run (step 6) or only against the source text |
Write now (format in step 8), every source file .
MIGRATION.mdtodoAsk whether each slice should also run against a planted defect (step 6)
and record the answer as or .
Defect check: onoff根据仓库回答以下问题;只有无法观察到的信息才询问用户。
| 问题 | 从哪里获取答案 | 决定什么 |
|---|---|---|
| 源运行器 | 上方检测表格 | 清点表格之前需要阅读的两份文档 |
| 测试 | 每个 spec、flow 或测试文件,包括其标题、标签以及按平台或浏览器分支的测试。使用运行器自身的 list 或 dry-run 模式统计测试,不要使用 grep,否则会漏掉在循环中生成的测试。 | 进度文件中的行,每个源文件一行。立即统计每个文件当前的断言数,以便移植后进行核对:显式断言( |
| 共享代码 | Page objects、自定义命令、subflow( | 需要在首个依赖它们的测试之前各移植一次的辅助代码 |
| 运行方式 | 运行该套件的 CI job 及其调用的脚本:构建、启动的服务和 mock servers、seed 与 reset 调用、env 文件、设备或浏览器、端口 | e2e harness。CI job 通常是唯一完整的描述;应逐行阅读 |
| e2e 的位置 | 带有 | e2e 配置和进度文件的位置。两个运行器不能收集彼此的文件:模式重叠时应收窄其中一个模式。Playwright 套件通常已将文件命名为 |
| 旧套件能否在当前环境运行 | 已安装的源运行器、所需构建和服务 | 对等性是针对实时运行旧套件进行验证(步骤 6),还是仅根据源文本进行验证 |
立即编写 (格式见步骤 8),将每个源文件标为 。
MIGRATION.mdtodo询问每个切片是否还应针对植入的缺陷运行(步骤 6),并将答案记录为 或 。
Defect check: onoff3. Build the harness (once)
3. 构建 harness(仅一次)
The harness is the config, the app launch, and one green test. It is done
once and the progress file says so; later sessions skip this step.
- No e2e config: (topic
npx e2e init --yes). On a device project, swapsetupfor@e2e-dev/weband delete or rewrite the example test. One target per platform or browser the source suite covers.@e2e-dev/mobile - Ask the user which model agent steps use, and configure it (topic
). A literal port needs none: every test can be deterministic, and a config without a model runs those.
agent - Port the orchestration the CI job does, reusing the repo's own scripts
rather than writing new ones:
- The one process that serves the app (a dev server, Metro for an Expo dev
client) becomes the target's with
app.command(topicreadyUrl). The command gets onlysetup,PATH, the temp-directory variables, andHOME, not the shell's environment, so pass what the server read from the old runner's environment incommand.env.command.env - e2e has no key. Databases, queues, and mock servers start before the run with the command the CI job uses, or
servicesruns a script that brings them up and then serves the app. Name the command in the progress file.app.command - A reset or seed the source ran per test (with
runScript,http.post, an API call incy.task('db:reset')) becomesbeforeEachin afetchor a fixture, so each test still starts from known data.beforeEach - A seed helper that imports the app's own code (an ORM factory, a
server module) is reused, not rewritten. The old runner may have
compiled it to CommonJS; e2e loads every file as an ES module. Importing it into a test can then fail with
.ts, with "does not provide an export named" for a CommonJS package, or with__dirname is not defined. When it does, run the helper unchanged in a child process with the repo's own TypeScript runner (ERR_UNSUPPORTED_DIR_IMPORT,ts-node) and call it from a fixture. Do not edit the app's modules to make them load.tsx - Env values become module constants; passwords and tokens go under
or
credentials(topicsecrets). When the old config loaded an env file (setup), load it the same way in the e2e config, so tests and helpers see the same values.dotenv.config()does not see them; pass the ones the server needs inapp.command.command.env
- The one process that serves the app (a dev server, Metro for an Expo dev
client) becomes the target's
- Port the simplest source test, often the sign-in or the launch, as the smoke test. It must pass on every target before any other port. When it cannot, the harness is wrong, not the test: fix the harness.
- adds a
initscript (test:e2e) unless a script already has that name. When the name was taken, ore2e rundid not run, add one under a free name. Keep the old suite's scripts as they were.init - Mark the harness done in the progress file, with the commands that start the dependencies, run the old suite, and run the new one.
harness 包括配置、应用启动和一个通过的测试。它只需构建一次,进度文件会标明这一点;后续会话跳过此步骤。
- 没有 e2e 配置:运行 (主题
npx e2e init --yes)。在设备项目中,将setup换成@e2e-dev/web,并删除或重写示例测试。为源套件覆盖的每个平台或浏览器设置一个目标。@e2e-dev/mobile - 询问用户步骤使用哪种模型 Agent,并进行配置(主题 )。直接移植不需要模型:每个测试都可以是确定性的,不带模型的配置也能运行这些测试。
agent - 移植 CI job 所做的编排工作,优先复用仓库现有脚本,而不是新写脚本:
- 提供应用的单个进程(dev server、Expo dev client 的 Metro)成为目标的 ,并配合
app.command(主题readyUrl)。该命令只获得setup、PATH、临时目录相关变量和HOME,不会继承 shell 的环境,因此应通过command.env传入服务器从旧运行器环境读取的值。command.env - e2e 没有 键。数据库、队列和 mock servers 应在运行前使用 CI job 所用的命令启动,或由
services运行一个脚本,先启动它们再提供应用。将该命令记录在进度文件中。app.command - 源测试每次运行的 reset 或 seed(中的
runScript、http.post、cy.task('db:reset')中的 API 调用)变成beforeEach或 fixture 中的beforeEach,确保每个测试仍从已知数据开始。fetch - 导入应用自身代码的 seed helper(例如 ORM factory、server module)应复用,而不是重写。旧运行器可能已将其编译为 CommonJS;e2e 会将每个 文件作为 ES module 加载。此时,将其导入测试可能失败并出现
.ts、CommonJS package “does not provide an export named”或__dirname is not defined。出现这些情况时,使用仓库自己的 TypeScript 运行器(ERR_UNSUPPORTED_DIR_IMPORT、ts-node)在子进程中原样运行该 helper,并从 fixture 调用它。不要修改应用的模块来使其可加载。tsx - 环境变量值成为模块常量;密码和 token 放入 或
credentials(主题secrets)。旧配置加载 env 文件(setup)时,在 e2e 配置中以相同方式加载,使测试和 helper 看到相同的值。dotenv.config()看不到这些变量;服务器需要的值通过app.command传入。command.env
- 提供应用的单个进程(dev server、Expo dev client 的 Metro)成为目标的
- 移植最简单的源测试,通常是登录或启动测试,作为 smoke test。它必须先在每个目标上通过,之后才能移植其他测试。若无法通过,问题出在 harness 而非测试:修复 harness。
- 会添加
init脚本(test:e2e),除非已有同名脚本。名称已被占用或未运行e2e run时,使用一个未占用的名称添加脚本。旧套件的脚本保持原样。init - 在进度文件中标记 harness 已完成,并记录启动依赖项、运行旧套件和运行新套件的命令。
4. Pick the slice
4. 选择切片
A slice is what this session can finish green: one file, one folder, one
tag, or one feature area, usually one to five tests. Ask the user which.
When they leave it to you, suggest in this order:
- Tests whose shared helpers are already ported.
- Tests that break often in the old runner: retries, flaky history in CI, comments explaining a workaround for the runner. They gain the most.
- Tests that need a capability the guide marks or "No equivalent", last.
missing
Write the slice into the progress file's section before starting, so an
interrupted session leaves a trail.
Next切片是本次会话能够完成并保持全绿的范围:一个文件、一个文件夹、一个标签或一个功能区域,通常包含一到五个测试。询问用户选择哪一个。如果交由你决定,按以下顺序建议:
- 共享辅助代码已经移植完成的测试。
- 在旧运行器中经常失败的测试:需要重试、在 CI 中有 flaky 历史,或注释中说明了针对该运行器的 workaround。这些测试的收益最大。
- 需要指南中标记为 或“No equivalent”的能力的测试,放在最后。
missing
开始前先把切片写入进度文件的 章节,这样即使会话中断也能留下记录。
Next5. Port the slice
5. 移植切片
Port the slice's shared helpers first, once, as plain files (not
, so the runner does not collect them), for example under
. A subflow
becomes a function or a fixture; a page object becomes a
fixture (topic ). Record each in the progress file.
.ts.e2e.tstests/support/test.extendwriting-testsThen each test, one at a time:
- Keep its title, and open the file with a comment naming the source
(), so reports and reviewers map one to the other.
// Ported from __e2e__/flows/login.yml - Translate literally first with the guide's tables, one awaited call per
source step. Each source assertion maps to its own e2e assertion. A wait
that fails on timeout () becomes one more, so the e2e count is at least the inventory's.
waitForFunction - A test the source skips is ported in full and stays skipped, with the source's reason, so it can be turned back on in either suite. Its row says so; when the reason allows, run it unskipped once and note the result.
- Learn exact names before writing a locator: with
e2e mcp,open_session, andobserve(topiclocate). When your client has nomcpMCP tools, run the test and read the screen listed on its trace page (topice2e); do not build a bridge. The guide's notes on selectors list the edits most ports need: e2e matches whole strings and fails on several matches where the old runner took the first. When a query also matches a hidden copy (another layout's), adddebugging. When two visible nodes match, such as a second toast over the first, pick the one the step means.{ visible: true } - A sleep or fixed wait becomes an assertion on the state it waited for.
- A per-platform branch becomes on a test, or an
{ platforms: [...] }on theiffixture inside one.platform - A workaround the source comments explain (a flaky , a coordinate tap, a retry loop around a picker) is a workaround for the old runner. Try the plain step first; keep a workaround only when e2e needs it too, with its own comment saying why.
hideKeyboard - Where the guide marks a step or "No equivalent", use its workaround. When there is none, the test stays in the old runner: mark it
missingwith the reason and offer to sendstaysonce: preview it withnpx e2e feedback --type feature -m "<the gap>"and send it only when the user agrees (the e2e skill, Feedback).--dry-run - Do not change app code. A test that needs a test id the app lacks gets
or a different locator; propose the app change to the user instead of making it. A defect check's planted bug (step 6) is the exception, reverted the same session.
agent.act
agent.actagent先一次性移植切片的共享辅助代码,并写成普通 文件(不要使用 ,以免运行器收集它们),例如放在 下。subflow 变为函数或 fixture;page object 变为 fixture(主题 )。将每一项记录在进度文件中。
.ts.e2e.tstests/support/test.extendwriting-tests然后逐个移植每个测试:
- 保留其标题,并以一条注明来源的注释打开文件(),以便报告和评审人员一一对应。
// Ported from __e2e__/flows/login.yml - 先使用指南中的表格逐字翻译,每个源步骤对应一个 awaited 调用。每个源断言都映射到自己的 e2e 断言。因超时而失败的等待()要再增加一个断言,因此 e2e 断言数至少应达到清点结果。
waitForFunction - 源中跳过的测试也要完整移植并保持跳过状态,同时保留源中的原因,以便之后在任一套测试中重新启用。该行需注明这一点;如果原因允许,则取消跳过一次运行并记录结果。
- 编写 locator 前先了解精确名称:使用 配合
e2e mcp、open_session和observe(主题locate)。如果客户端没有mcpMCP 工具,则运行测试并读取 trace page 上列出的屏幕(主题e2e);不要构建 bridge。指南中关于 selector 的说明列出了大多数移植需要的调整:e2e 匹配完整字符串,并且当存在多个匹配项时会失败,而旧运行器会选择第一个。如果查询还匹配到一个隐藏副本(另一种布局),添加debugging。如果两个可见节点都匹配,例如第二个 toast 覆盖第一个,则选择该步骤所指的节点。{ visible: true } - sleep 或固定等待应改为对所等待状态的断言。
- 按平台分支的逻辑变为测试上的 ,或在一个测试内对
{ platforms: [...] }fixture 使用platform。if - 源代码注释所解释的 workaround(不稳定的 、坐标点击、picker 周围的 retry loop)通常是针对旧运行器的 workaround。先尝试普通步骤;仅当 e2e 同样需要时才保留 workaround,并另加注释说明原因。
hideKeyboard - 如果指南将某个步骤标记为 或“No equivalent”,则使用其 workaround。如果没有 workaround,则该测试留在旧运行器中:标记为
missing并说明原因,同时提出可以发送一次stays;先用npx e2e feedback --type feature -m "<the gap>"预览,只有用户同意后才发送(e2e skill,Feedback)。--dry-run - 不要修改应用代码。如果测试需要应用中不存在的 test id,则使用 或其他 locator;向用户提出应用变更建议,而不是直接实施。缺陷检查中植入的 bug(步骤 6)是例外,但必须在同一会话中撤销。
agent.act
agent.actagent6. Prove each port
6. 证明每次移植
A port is done when it is as strict as the source and passes every time.
- Run it on every target the source covered:
, plus
npx e2e run <file> --repeat-each 3when it has agent steps. Three of three on each target, or it is not done (topic--no-cache).running - When the old suite can run here, run the source test on the same build. A failure both runners show is an app or environment bug: report it, do not port around it. A failure only e2e shows is the port's.
- Check strictness against the source: an e2e assertion for every source
assertion, so the count is at least the inventory's, and every end
state the source checked is checked. Never
weaken an assertion, widen a timeout without a reason, or drop a step to
go green. A test that cannot pass honestly stays with what failed.
blocked - Read the trace page of any failure before changing the test
(topic ).
debugging
当移植与源测试同样严格且每次都能通过时,才算完成。
- 在源测试覆盖的每个目标上运行:,包含 agent 步骤时再加上
npx e2e run <file> --repeat-each 3。每个目标都必须三次通过三次,否则尚未完成(主题--no-cache)。running - 如果旧套件能在当前环境运行,则在同一构建上运行源测试。两个运行器都出现的失败是应用或环境 bug:报告它,不要绕过它进行移植。只有 e2e 出现的失败则属于移植问题。
- 对照源测试检查严格性:每个源断言都要有对应的 e2e 断言,因此断言数至少应达到清点结果,并且源测试检查的每个最终状态都必须被检查。绝不要弱化断言、无故延长超时,或为了变绿而删除步骤。无法诚实通过的测试应标为 ,并记录失败原因。
blocked - 修改测试前,先阅读任何失败对应的 trace page(主题 )。
debugging
Defect check (optional)
缺陷检查(可选)
With , show both suites fail on the same bug:
Defect check: on- With the user's agreement, plant a small bug in an end state the source
asserts (a checkout showing the wrong total), in a file with no
uncommitted changes. Note the file under until it is reverted.
Next - Rebuild, confirm the app shows the bug, then run on the slice (when it runs here) and
Run old.npx e2e run <files> --no-cache - Revert only that file (), rebuild, and confirm
git checkout -- <file>is empty.git diff -- <file> - Both fail at the step that checks the planted state: record it. Only the old suite passes: record that the source was weaker. Only e2e passes: the port lost an assertion, so it is not done. Neither fails: pick another bug. A failure before that step is not a catch.
- Fill the row's cell, for example
Defect check, ortotal +1: both failwhen the old suite cannot run here.old not run
当 时,证明两个套件会在同一个 bug 上失败:
Defect check: on- 经用户同意,在源测试断言的某个最终状态中植入一个小 bug(例如结账时显示错误总额),并选择没有未提交改动的文件。在撤销之前,在 下记录该文件。
Next - 重新构建,确认应用显示该 bug,然后在切片上运行 (当它能在当前环境运行时),并运行
Run old。npx e2e run <files> --no-cache - 仅撤销该文件(),重新构建,并确认
git checkout -- <file>为空。git diff -- <file> - 两个套件都在检查植入状态的步骤处失败:记录下来。只有旧套件通过:记录源测试较弱。只有 e2e 通过:移植丢失了断言,因此尚未完成。两者都未失败:换一个 bug。在该步骤之前发生的失败不算捕获。
- 填写该行的 单元格,例如
Defect check,或total +1: both fail(旧套件无法在当前环境运行)。old not run
7. Run both suites
7. 运行两套测试
Until the user retires a source test, both runners keep it.
- Ported tests stay in the old suite too. Delete a source test only when the
user confirms, then mark it . Once neither a remaining source test nor e2e code uses a source helper, propose deleting it, and delete it when the user confirms.
retired - CI: propose adding the e2e suite beside the old job once a few ports are
green, and make the change only when the user agrees, since it edits the
old runner's workflow. Reuse its build, services, and devices. Two
runners never drive one device or simulator at the same time; run them one after the other in the same job, or give each its own
device. The e2e job runs every ported test, so a later change that breaks
one fails the pull request (topic , Continuous integration).
running - When the last source test is retired or marked , the progress file says the migration is complete and which tests, if any, stay behind.
stays
在用户确认移除源测试之前,两个运行器都保留它。
- 已移植的测试也保留在旧套件中。只有用户确认后才删除源测试,然后标记为 。当剩余的源测试和 e2e 代码都不再使用某个源 helper 时,提出删除建议,并在用户确认后删除。
retired - CI:完成若干移植并变绿后,提出在旧 job 旁添加 e2e suite,并且只有在用户同意时才进行更改,因为这会修改旧运行器的 workflow。复用其构建、服务和设备。两个运行器绝不能同时驱动同一设备或模拟器;在同一个 job 中依次运行,或为每个运行器分配各自的设备。e2e job 会运行每个已移植的测试,因此后续更改若破坏其中一个测试,就会使 pull request 失败(主题 ,Continuous integration)。
running - 当最后一个源测试被标记为 或
retired时,进度文件应说明迁移已完成,以及仍保留哪些测试(如有)。stays
8. Keep the progress file
8. 维护进度文件
MIGRATION.mdmd
undefined位于 e2e 配置旁的 是迁移状态。持续更新它,而不是等到最后;会话中断时,文件必须反映真实状态。
MIGRATION.mdmd
undefinedMigration to e2e
Migration to e2e
Source: Maestro, (guide: https://e2e.tester.army/docs/migrate/maestro.md, engine: https://e2e.tester.army/docs/mobile.md)
e2e: , tests
Start dependencies:
Run old:
Run new:
Harness: done, smoke on ios and android
Defect check: on
__e2e__/flows/**e2e.config.tstests/**/*.e2e.tspnpm e2e:mock-servermaestro test __e2e__npx e2e runtests/login.e2e.ts| Source | e2e | Status | Assertions (source → e2e) | Passing | Defect check | Notes |
|---|---|---|---|---|---|---|
| flows/login.yml | tests/login.e2e.ts | ported | 3 → 3 | ios 3/3, android 3/3 | wrong screen: both fail | |
| flows/create-account.yml | blocked | 6 → | date picker spin fails on android, trace in .e2e/results | |||
| flows/search-screen.yml | todo | 4 → |
Source: Maestro, (guide: https://e2e.tester.army/docs/migrate/maestro.md, engine: https://e2e.tester.army/docs/mobile.md)
e2e: , tests
Start dependencies:
Run old:
Run new:
Harness: done, smoke on ios and android
Defect check: on
__e2e__/flows/**e2e.config.tstests/**/*.e2e.tspnpm e2e:mock-servermaestro test __e2e__npx e2e runtests/login.e2e.ts| Source | e2e | Status | Assertions (source → e2e) | Passing | Defect check | Notes |
|---|---|---|---|---|---|---|
| flows/login.yml | tests/login.e2e.ts | ported | 3 → 3 | ios 3/3, android 3/3 | wrong screen: both fail | |
| flows/create-account.yml | blocked | 6 → | date picker spin fails on android, trace in .e2e/results | |||
| flows/search-screen.yml | todo | 4 → |
Shared helpers
Shared helpers
| Source | e2e | Used by |
|---|---|---|
| setupApp.yml | tests/support/app.ts | login, create-account |
| Source | e2e | Used by |
|---|---|---|
| setupApp.yml | tests/support/app.ts | login, create-account |
Gaps
Gaps
- has no e2e equivalent (guide: missing); feedback sent.
addMedia
- has no e2e equivalent (guide: missing); feedback sent.
addMedia
Next
Next
flows/composer.yml and flows/composer-self-label.yml (both need ).
signInAlice()
One row per source file. A file whose tests end in different statuses
gets one row per test, each with its own assertion count. A suite with
hundreds of tests keeps file rows: the table is read at the start of
every session.
Statuses: `todo`; `ported` (green in e2e, the source test still runs);
`retired` (the user confirmed, the source test is deleted); `blocked`
(tried, does not pass yet, with what failed); `stays` (stays in the old
runner on purpose, with why).flows/composer.yml and flows/composer-self-label.yml (both need ).
signInAlice()
每个源文件一行。如果一个文件中的测试最终状态不同,则每个测试各占一行,并拥有各自的断言计数。包含数百个测试的套件仍保留文件行:每次会话开始时都会读取该表。
状态包括:`todo`;`ported`(在 e2e 中为绿色,源测试仍会运行);`retired`(用户已确认,源测试已删除);`blocked`(已尝试但尚未通过,并记录失败原因);`stays`(有意留在旧运行器中,并记录原因)。9. Hand over
9. 交接
Tell the user what this session moved and what it proved: the tests ported
and their pass counts per target, defect check results, the helpers ported,
what is blocked or stays and why, the gaps reported, and the next slice.
Ask which source tests may be retired. List every file you created or changed.
ported告诉用户本次会话迁移了什么、证明了什么:已移植的测试及其在每个目标上的通过次数、缺陷检查结果、已移植的 helper、被阻塞或保留的项目及原因、已报告的缺口,以及下一个切片。询问哪些 源测试可以移除。列出创建或修改的每个文件。
portedRules
规则
- One slice per session. Leave both suites green: the old suite passes as it
did, and every test passes.
ported - Never delete or edit a source test, helper, or the old runner's config without the user's confirmation.
- Port from what the repo shows. Run every command you put in the progress file at least once; one that cannot run here (the old runner not installed) says so in the progress file.
- A source step whose meaning is unclear, such as a tap on a disabled control or a coordinate tap that may miss, keeps its intent in the port. Note your reading in the progress file and ask the user.
- One sentence from the e2e skill or the guide beats a paragraph of your own. Name the topic or the guide's section.
- Never put a secret in a test, the config, or the progress file. Name the
credential (topic ).
setup - Do not commit on the user's behalf.
- 每个会话只处理一个切片。让两套测试都保持全绿:旧套件保持原有的通过状态,每个 测试也都通过。
ported - 未经用户确认,绝不删除或编辑源测试、helper 或旧运行器配置。
- 根据仓库显示的内容进行移植。进度文件中写入的每条命令至少运行一次;无法在当前环境运行的命令(例如未安装旧运行器)应在进度文件中注明。
- 对于含义不明确的源步骤,例如点击禁用控件,或可能落空的坐标点击,应在移植中保留其意图。在进度文件中记录你的理解并询问用户。
- e2e skill 或指南中的一句话胜过你自己写的一大段。注明主题或指南章节。
- 绝不要把 secret 放入测试、配置或进度文件。注明凭据名称(主题 )。
setup - 不要代替用户执行 commit。