定位断言
Day 06 - Locators Fundamentals
今日目标
- 掌握 Playwright 推荐 locator。
- 避免脆弱 CSS/XPath。
学习时间安排(60–120 分钟)
| 时间 | 模块 | 做什么 |
|---|---|---|
| 0-20 分钟 | 核心概念与词汇 | 读概念表,重点记 getByRole/getByLabel/getByTestId 三个。 |
| 20-45 分钟 | 官方文档阅读 | 读 Locators 文档的优先推荐部分和最佳实践。 |
| 45-75 分钟 | 实操练习 | 在登录页/表单页用 4 种 locator 定位元素。 |
| 75-105 分钟 | 示例代码改写 | 把 Day 2 测试里的 locator 换成语义化版本。 |
| 105-120 分钟 | 复盘与作业 | 完成 locator 选择规则笔记,完成今日问题。 |
核心概念与词汇
| English | 中文 | 场景用法 |
|---|---|---|
| locator | 定位器 | Use it when you describe how a test finds an element on the page. |
getByRole() | 按角色定位 | Use it when you locate elements by their accessibility role and accessible name. |
getByLabel() | 按标签定位 | Use it when you locate form fields by their associated label text. |
getByPlaceholder() | 按占位符定位 | Use it when an input has no label and only a placeholder. |
getByText() | 按文本定位 | Use it when you locate non-interactive text like titles, messages, or cell content. |
getByTestId() | 按测试 ID 定位 | Use it when UI structure changes often and the team agrees on data-testid. |
getByAltText() | 按图片 alt 定位 | Use it when you locate images by their alt text. |
getByTitle() | 按 title 属性定位 | Use it when an element only exposes a title attribute. |
| accessible name | 可访问名称 | Use it when you explain what name option matches in getByRole. |
| accessibility tree | 可访问性树 | Use it when you explain why role-based locators are more stable than CSS. |
| ElementHandle | 旧式元素句柄 | Use it when you explain why modern Playwright prefers Locator. |
| strict mode | 严格模式 | Use it when multiple elements match a locator and the test errors out. |
学习材料
- 必读:[Locators](https://playwright.dev/docs/locators)
- 必读:[Best practices](https://playwright.dev/docs/best-practices)
- 选读:[Picking a locator](https://playwright.dev/docs/locators#picking-a-locator) 的决策图
重点理解
优先使用:
page.getByRole()
page.getByText()
page.getByLabel()
page.getByPlaceholder()
page.getByAltText()
page.getByTitle()
page.getByTestId()
推荐优先级:
getByRole:最接近用户和可访问性语义。getByLabel:表单输入。getByPlaceholder:输入框辅助。getByText:文本。getByTestId:稳定测试标识。- CSS / XPath:最后选择。
实操步骤
找一个登录页或表单页,分别使用不同 locator 定位:
- 用户名输入框。
- 密码输入框。
- 登录按钮。
- 错误提示。
- 页面标题。
示例代码
await page.getByLabel('Username').fill('testuser');
await page.getByLabel('Password').fill('password');
await page.getByRole('button', { name: 'Login' }).click();
await expect(page.getByText('Invalid username or password')).toBeVisible();
常见坑
- 用
page.locator('#login-btn')定位按钮——CSS 选择器不表达语义,UI 重构即失效。 - 复制 XPath 长链
//div[3]/div/div[1]/button,DOM 任何变动都会破坏。 getByRole的name写错(写完整文本却包含隐藏字符),一直匹配不到。- 多个相同文本的元素用
getByText直接点,触发 strict mode 报错。 - 页面没有
data-testid时硬用getByTestId,把成本转嫁给前端。
今日产出
- 一个使用 4 种 locator 的测试文件。
- 一份 locator 选择规则笔记。
今日问题
- 为什么官方推荐 Locator 而不是 ElementHandle?
getByRole为什么更稳定?- 什么时候适合用
getByTestId? - 为什么长 CSS/XPath 容易导致 flaky test?
- Locator 的 auto-waiting 体现在哪里?
复盘要点
- Locator 是 E2E 测试维护成本的核心变量:今天的选择决定三个月后的 flaky 数量。
- 决策顺序背下来:role → label → placeholder → text → testid → CSS/XPath。
- 遇到定位不到的元素,先打开 DevTools 的 Accessibility 面板看 role 和 name,而不是直接上 CSS。
AI 时代扩展:AI 辅助 Playwright 测试
新增概念
| English | 中文 |
|---|---|
| locator suggestion | 定位器建议 |
| semantic locator | 语义化定位器 |
| accessibility snapshot | 可访问性快照 |
| selector brittleness | 选择器脆弱性 |
适用场景
让 AI 为一段 HTML 片段推荐 locator 并说明理由,或者让 AI 审查你测试里的 CSS/XPath 并给出语义化替代方案。注意 AI 看不到真实页面,建议需要你在页面上验证。
可复用表达 / 提示词
这是按钮的 HTML:<div class="cta-wrap"><a href="/start">Get started</a></div>。请给出 3 种定位方案并按稳定性排序,说明理由。
请检查下面测试中的 locator,指出哪些是脆弱选择器,并给出语义化替代。
追问加练
- AI 推荐的 locator 在页面上匹配了 3 个元素,你会怎么办?
data-testid和 role 之间,AI 会倾向哪个?你的业务里哪个更合理?- 让 AI 看 HTML 推荐 locator 的盲区是什么?
今日作业
- 完成 locator 选择规则笔记(优先级 + 每个 API 的适用场景 + 反面例子)。
- 把 Day 2 的 3 条测试全部换成语义化 locator,跑通。
- 用 DevTools 的 Accessibility 面板查看登录按钮的 role 和 name,记录下来。