| name | testcase-to-playwright-dsl |
| description | 将 XMind 风格 Markdown 测试用例转换为面向 Playwright UI 自动化流程的可执行 DSL YAML。适用于 Codex 读取交付目录中的 testcase/xmind-testcases.md,并生成 ui-dsl/ui-test.dsl.yaml;要求 selector 与 flow 分离、生成 TODO selector 占位、保留 source_case 可追溯信息,且只生成 UI DSL,不执行 Playwright、不生成 .spec.ts、不运行 npx playwright test。 |
测试用例转 Playwright UI DSL
目标
将 XMind 风格测试用例 Markdown 转换为稳定、可维护、可二次编辑的 UI 自动化 DSL 文件:
- 输入:
./<delivery-name>/testcase/xmind-testcases.md
- 输出:
./<delivery-name>/ui-dsl/ui-test.dsl.yaml
- 本 skill 只生成 UI DSL。
- 不执行 Playwright。
- 不生成
.spec.ts。
- 不运行
npx playwright test。
- 不要在对话中输出完整 DSL,只落盘文件。
- 完成后只输出:
[✓] UI DSL 生成完成
执行流程
- 确认项目根目录是包含
.codex 的目录。
- 根据用户请求定位交付目录;如果未指定,查找项目根目录下的
*/testcase/xmind-testcases.md。
- 如果找到多个
xmind-testcases.md,立即停止执行,并要求用户指定 delivery-name。
- 读取输入 Markdown,识别系统、版本、模块、用例标题、步骤、预期结果、优先级、前置条件。
- 必须保留 Markdown 缩进层级,通过缩进判断
tc、ts、ti、tp 与 expected 的父子关系。
ts 的直接子节点都是该步骤的 expected,不要求带有“预期结果”前缀。
- 不要把
ts 子节点误判为新的步骤,也不要把 ti、tp 当成 expected。
- 运行
scripts/convert_xmind_to_dsl.py 生成初始 DSL。
- 对照
references/dsl-schema.md 校验 YAML。若不符合,必须先修复再落盘;无法修复时,把原因写入 unsupported_steps,停止生成最终文件。
- 只写入
./<delivery-name>/ui-dsl/ 目录。
- 最终回复只输出
[✓] UI DSL 生成完成。
转换脚本
优先使用内置转换脚本:
python .codex/skills/testcase-to-playwright-dsl/scripts/convert_xmind_to_dsl.py \
--input ./<delivery-name>/testcase/xmind-testcases.md \
--output ./<delivery-name>/ui-dsl/ui-test.dsl.yaml
脚本采用保守策略:没有真实 DOM 时不把语义推断标记为 confirmed。当测试用例中无法确定真实 selector 时,生成 [data-testid="<selector_key>"] 占位、candidates 候选列表,并记录 selector TODO;点击 XXX、输入 XXX、看到 XXX 等语义线索只作为后续 selector enrichment 的候选来源。只有源测试用例明确给出 [data-testid="xxx"]、#id、.class 时,selector 才能标记为 confirmed。
如果未传入 --input,脚本会查找 */testcase/xmind-testcases.md;找到多个时会停止,并要求明确 delivery-name。
DSL 规则
- 使用
schema_version: "1.0"。
- 一个
tc 转换为一个 flow。
- 一个
ts 转换为一个 action step。
ts 的直接子节点转换为该步骤的 expected;一个 ts 可以有多个 expected 子节点。
- expected 子节点只在包含明确 UI 文案时转换为 assert 类 step,并写入
source_expected。
- 页面加载、页面展示、字段状态、业务状态、PRD/规则未说明等 expected 不生成 selector,转换为
optional: true 的 wait_for,并写入 TODO reason。
- 兼容旧格式
预期结果: xxx 和 预期结果, xxx。
ti 只解析为 P0、P1、P2、P3。
tp 解析为前置条件,保留多行内容。
- 每个 flow 必须包含
source_case.tc 和 source_case.tp。
- 可复用 selector 必须放在顶层
selectors 中。
- selector entry 必须包含
candidates;候选只用于 enrichment 校准,不代表 confirmed。
- 不确定的 selector 必须写入
todos。
- 无法转换的行为必须写入
unsupported_steps。
- 不允许凭空补充源测试用例中没有的业务规则。
- YAML 必须符合
references/dsl-schema.md 后才允许落盘。
- 本 skill 不负责执行自动化,不生成 Playwright 测试代码,不运行测试命令。
手动调整生成 YAML 前,先阅读 references/dsl-schema.md。
动作映射
打开 https://...、访问 https://... -> goto
点击、选择、勾选 -> click
输入、填写 -> fill
下拉选择 -> select
上传 -> upload
等待 -> wait_for
查看、校验可见 -> assert_visible
校验文案、提示、状态、结果 -> assert_text 或 assert_state
删除、移除 -> click;如果存在预期结果,再补充 assert
搜索、查询 -> fill + click;如果源文本足够明确,再补充 assert
进入页面、进入流程、点击后进入页面 等不允许自动转为 goto;若没有明确 URL 或可拆分原子动作,生成可选 wait_for 并记录 unsupported。
Selector 规则
- 使用英文
snake_case。
- 基于
description + source + action 提取通用 UI 语义词,不使用具体业务 PRD 或业务词表。
- 清理动作词:
点击、输入、填写、选择、勾选、查看、显示。
- 按动作推断类型后缀:
click -> button、fill -> input、select -> select、upload -> upload、勾选类 click -> checkbox。
- key 结构为
<semantic>_<type>;只有无法提取语义时才 fallback 到 element_<index>。
- 示例:
点击某入口 -> entry_button、输入某字段 -> field_input、勾选某选项 -> option_checkbox、点击确认 -> confirm_button、上传文件 -> file_upload。
- 如果无法确定真实 selector,使用
[data-testid="<selector_key>"],并保持 status: "todo"。
status: "todo" 的 selector 应尽量生成 candidates,例如 role、label、placeholder、text、data-testid、id、class 候选。
candidates 不能写入 selector 字段,也不能让 selector 变为 confirmed;dsl-selector-enrichment 负责验证 candidates 并在唯一命中后写回 confirmed selector。
playwright-dsl-to-spec 只执行 status: "confirmed" 的 selector,忽略 candidates。
- 不要仅凭
点击 XXX 推断为 role=button[name="XXX"] confirmed;真实 DOM 中可能是 button、link 或普通文本,交给 dsl-selector-enrichment probe 校准。
- 每个 selector 占位都必须在
todos 中记录 selector_key、来源用例、来源步骤和原因。
Expected 规则
- 只有 expected 包含明确 UI 文案时才生成 selector/assert,例如
显示“xxx”、提示“xxx”、看到“xxx”。
页面加载完成、页面展示xxx、字段展示已输入状态、PRD未说明、规则未说明 等状态类 expected 禁止生成 selector。
- 状态类 expected 转换为
action: wait_for、optional: true,comment 使用 expected is page/business state, selector not generated。
复合步骤规则
- 支持拆分通用原子动作:
输入 A 和 B -> 两个 fill;点击 A 并点击 B -> 两个 click;勾选 A 并提交 -> checkbox click + button click。
- 不可拆分的导航语义,例如
进入某页面、进入某表单,转换为 optional: true 的 wait_for,comment 使用 compound navigation step, requires manual decomposition,并写入 unsupported_steps。
TODO reason 规则
- 操作类 selector:
无法在 DSL 阶段确认 DOM selector,需 enrichment probe 校准。
- 页面/业务状态类 expected:
expected 为页面/业务状态,不生成 selector。
- PRD 不明确:
PRD 未提供明确 UI 信息。
- 复合步骤:
复合步骤需拆分为原子操作。
输出约定
最终 YAML 必须符合以下顶层结构:
schema_version: "1.0"
meta: {}
selectors: {}
test_data: {}
flows: []
todos: []
unsupported_steps: []