Previous
Day 07 · Advanced Locators: Filtering and Chaining
Next
Day 09 · Auto-waiting and Timeouts
定位断言
Day 0860-120 minutesPlaywright QA hands-on drill

Day 08 - Assertions

今日目标

  • 掌握常用 web-first assertions。
  • 知道什么时候断言页面、元素、URL、文本、数量。

学习时间安排(60–120 分钟)

时间模块做什么
0-20 分钟核心概念与词汇读概念表,区分页面断言、元素断言、数量断言。
20-45 分钟官方文档阅读读 Assertions 文档的通用断言和 locator 断言部分。
45-75 分钟实操练习给 Day 5 的 smoke tests 增加 8 种断言。
75-105 分钟示例代码改写把普通断言替换成 web-first assertion 并说明差异。
105-120 分钟复盘与作业记录最常用的 3 个断言,完成今日问题。

核心概念与词汇

English中文场景用法
web-first assertion网页优先断言Use it when you explain why expect retries until the condition is met or times out.
toBeVisible()可见断言Use it when you verify an element is rendered and visible to the user.
toBeEnabled()可用断言Use it when you verify a control is interactive, not disabled.
toHaveText()文本全等断言Use it when the element text must equal the expected string exactly.
toContainText()包含文本断言Use it when the element text only needs to contain a substring.
toHaveCount()数量断言Use it when you verify how many matching elements exist.
toHaveAttribute()属性断言Use it when you verify href, value, class, or data attributes.
toHaveURL()URL 断言Use it when you verify navigation, redirects, or query parameters.
toHaveTitle()标题断言Use it when you verify the tab title.
auto-retry自动重试Use it when you explain why assertions survive slow UI updates.
positive assertion正向断言Use it when you assert the expected state appears.
negative assertion反向断言Use it when you assert an element is hidden or absent.

学习材料

  • 必读:[Assertions](https://playwright.dev/docs/test-assertions)
  • 必读:[Auto-waiting](https://playwright.dev/docs/actionability) 中关于断言重试的说明
  • 选读:[Expect API](https://playwright.dev/docs/api/class-playwrightassertions)(浏览一遍可用断言清单)

重点理解

常用断言:

await expect(page).toHaveTitle(/Playwright/);
await expect(page).toHaveURL(/.*intro/);
await expect(locator).toBeVisible();
await expect(locator).toBeEnabled();
await expect(locator).toHaveText('Success');
await expect(locator).toContainText('Success');
await expect(locator).toHaveCount(3);
await expect(locator).toHaveAttribute('href', '/docs/intro');

注意:

  • Playwright 的 web-first assertions 会自动重试。
  • 不要用 expect(await locator.textContent()).toBe(...) 替代 web-first assertion,除非有明确原因。
  • 断言应该表达业务期望,而不是实现细节。

实操步骤

为 Day 5 的 smoke tests 增加断言:

  • 标题断言。
  • URL 断言。
  • 按钮可见断言。
  • 文本断言。
  • 列表数量断言。

示例代码

import { test, expect } from '@playwright/test';

test('order page shows correct summary', async ({ page }) => {
  await page.goto('/orders/42');
  await expect(page).toHaveTitle(/Order #42/);
  await expect(page).toHaveURL(/\/orders\/42/);

  const status = page.getByRole('status');
  await expect(status).toBeVisible();
  await expect(status).toContainText('Paid');

  await expect(page.getByRole('listitem')).toHaveCount(3);
  await expect(page.getByRole('button', { name: 'Ship' })).toBeEnabled();
});

常见坑

  • expect(await locator.textContent()).toBe('Success') 手动取值比较,丢掉自动重试,遇到慢加载就 flaky。
  • toBeTruthy() 类断言包着 isVisible(),报错信息看不出页面状态。
  • toHaveTexttoContainText 混用:完整校验用前者,部分匹配用后者。
  • 断言写实现细节(如 class 名、DOM 结构),UI 重构后全红。
  • 只写操作不写断言,测试“跑通”却什么都没验证。

今日产出

  • 至少 8 个不同断言示例。
  • 记录哪个断言最常用。

今日问题

  1. Web-first assertion 和普通 assertion 有什么区别?
  2. 为什么 toBeVisible() 比检查 CSS class 更好?
  3. toHaveTexttoContainText 有什么区别?
  4. toHaveCount 适合哪些场景?
  5. 断言过多和过少分别有什么问题?

复盘要点

  • 断言是测试的“价值部分”:没有断言的测试只是操作脚本。
  • 好的断言描述用户看到的结果(可见、可点、文案正确、数量正确),而不是 DOM 长相。
  • 记住自动重试机制:断言失败前会持续重试到超时,这是 Playwright 稳定性的根基之一。

AI 时代扩展:AI 辅助 Playwright 测试

新增概念

English中文
assertion coverage断言覆盖
expected result预期结果
over-assertion过度断言
assertion strategy断言策略

适用场景

让 AI 检查你的测试“操作了很多但验证了什么”,或者根据需求描述生成候选断言。注意:哪些业务结果是关键验证点,必须由 QA 自己判断。

可复用表达 / 提示词

我的测试只做了点击和填写,请根据「提交后应显示成功提示并跳转到列表页」这个预期,补充最少且必要的断言。
下面这条断言验证的是实现细节还是用户可见结果?请给出理由和替代方案。

追问加练

  • AI 建议断言某个 class 名,你会接受吗?为什么?
  • 一条测试里 10 个断言和 2 个断言,哪个更难维护?
  • AI 无法替你判断的断言是什么类型的?

今日作业

  • 给 Day 5 的 smoke.spec.ts 每条测试补充至少 2 个业务断言。
  • 整理“断言速查表”:8 个常用断言 + 场景 + 一个反面例子。
  • 让 AI 审查你的断言,找出验证实现细节的地方并修改。

自检清单

Previous
Day 07 · Advanced Locators: Filtering and Chaining
Next
Day 09 · Auto-waiting and Timeouts