关于 codeceptjs-exploration
面向使用 CodeceptJS 编写或维护测试的开发者,提供页面探索和定位器选择流程。它结合页面快照、元素检查与稳定定位器原则,帮助验证候选元素并避免脆弱选择器。
主要功能
- 01运行代码并采集页面快照
- 02检查元素状态、文本和属性
- 03通过 ARIA、截图与 HTML 探索页面
- 04按上下文和语义选择定位器
- 05提交前验证定位器唯一匹配
适用场景
- 01为新测试查找页面元素
- 02调试失败测试中的定位器
- 03替换过时或脆弱的选择器
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ codeceptjs/ skills --skill codeceptjs-exploration安装后在 Claude Code 中输入/codeceptjs-exploration确认已加载。
详细介绍
CodeceptJS 页面探索
编写测试、调试故障和重构过时定位器,本质上都是同一项任务:打开页面,找到正确的元素,选择稳定的定位器。这就是本指南。
工具
run_code— 运行 CodeceptJS 代码,返回生成的值,捕获console.*,并保存最终状态快照。适用于“执行操作并查看结果”。snapshot— 不执行操作,只捕获状态(URL、cookies、localStorage、HTML、ARIA、截图、控制台)。适用于“查看页面当前内容”。
工件来源,优先级从高到低:
- ARIA 快照 — 结构化,没有样式干扰,便于扫描重复项和无障碍名称
- 截图 — 用于视觉确认;能发现 ARIA 无法显示的布局问题
- HTML — 仅在 ARIA 缺少上下文时使用(没有无障碍名称的自定义组件、由属性驱动的行为)
检查元素
I.grabWebElement(locator) → 一个 WebElement;I.grabWebElements(locator) → 一个数组。Playwright / Puppeteer / WebDriver 上均提供相同的跨辅助 API。
| 你想要…… | 方法 |
|---|---|
| 确认已渲染 / 可见 / 已启用 | exists()、isVisible()、isEnabled() |
| 读取文本 / 值 / 属性 / 特性 | getText()、getValue()、getAttribute(n)、getProperty(n) |
| 查看页面位置 | getBoundingBox() — 标记屏幕外或尺寸为零的元素 |
| 查看已渲染标记 | toOuterHTML()、toSimplifiedHTML(300)(已截断,适合 MCP) |
| 为修复获取稳定选择器 | toAbsoluteXPath() |
| 位于 iframe 内部 | inIframe(async (body) => { ... }) |
| 深入检查子元素 | $(loc)、$$(loc) |
| 浏览器端函数 | evaluate(fn, ...args) |
明显的定位器未命中时发现候选元素
当 Edit 未匹配到任何内容时,控件可能显示“Change”,带有 aria-label="Edit user",或位于 .btn-edit 中。使用 I.grabWebElements 和宽泛的 XPath 搜索候选元素,然后再消除歧义。
在 XPath 中用 OR 组合以下条件:
- 可见文本 —
text()(或用于后代元素的.) - 属性 —
@class、@aria-label、@title、@data-action、@id - 同义词 — edit/change/modify;delete/remove/trash;submit/send/save
通过 translate(...) 实现不区分大小写:
//*[contains(translate(., 'EDIT', 'edit'), 'edit')
or contains(translate(@class, 'EDIT', 'edit'), 'edit')
or contains(translate(@aria-label, 'EDIT', 'edit'), 'edit')
or contains(translate(., 'CHANGE', 'change'), 'change')]
然后遍历结果并调用 toSimplifiedHTML(150),选出正确的候选元素,再根据其可区分的属性或文本,确定稳定的定位器。
选择稳定的定位器
按顺序做出两个决定:哪个区域限定查找范围(上下文),以及区域内用什么标识元素。先选区域,标识符就能保持简短且具有语义 — 消除歧义时找到的区分条件应放在上下文参数中:
I.click('Edit user', '.user-row') // ✅ region + what the user sees
I.click('#user-row-42 button.edit') // ❌ same element, brittle, unreadable
稳定的区域:地标(nav、main、{ role: 'dialog' })、应用外壳容器(.sidebar、.toolbar、.modal)、通过 locate(...) 按数据标识的行 / 卡片。标识符优先级(完整说明见 codeceptjs-fundamentals § Locators):
- 可见标签 / 无障碍名称 — 普通字符串已匹配
aria-label;不要扩展成{ css: '[aria-label="..."]' } - 上下文内存在歧义时,或角色本身是检查内容时,使用 ARIA 角色
- 当团队提供测试属性时,通过
customLocator使用$name - 组合 CSS,但仍需限定范围:
I.click('button.edit', '#user-row-42') toAbsoluteXPath()— 最后手段;提醒团队添加data-testid
绝不要提交未经验证的定位器 — 使用 run_code 确认它只匹配一个元素(I.seeElement(loc, context) 或 grabWebElement(loc))。
常见模式
- 严格模式下匹配到 2 个以上 → 对每个结果调用
grabWebElements('Save')+toSimplifiedHTML(200),找出区分条件,并将其作为上下文传入:I.click('Save', '.modal') - 按钮已渲染但不起作用 →
grabWebElement('Submit')+isEnabled()+getBoundingBox()— 已禁用?位于屏幕外?尺寸为零? - 列表中选错行 →
grabWebElements('.user-row'),逐行调用getText()进行识别,使用getAttribute('data-id')获取稳定钩子 - 位于 iframe 内部 →
(await I.grabWebElement('iframe.editor')).inIframe(async (body) => body.$('button'))
应避免的事项
- 尚未查看候选项就选择定位器。
- 有语义化定位器可用时,仍提交
toAbsoluteXPath()。 - 上下文可缩短定位器时,仍提交未限定范围的定位器。
- 忽略截图——“存在于 HTML 中”≠“用户能看到”。
- WebElement 方法足以满足需求时,仍使用
usePlaywrightTo/useWebDriverTo。
相关技能
codeceptjs-fundamentals— 定位器优先级、await 规则writing-codeceptjs-tests— 在模式 B 探索期间调用此技能debugging-codeceptjs-tests— 用于实时检查;离线版本通过codeceptq使用