Previous
Day 08 · Assertions
Next
Day 10 · Weekly Review 2: Writing Stable Tests
定位断言
Day 0960-120 minutesPlaywright QA hands-on drill

Day 09 - Auto-waiting and Timeouts

今日目标

  • 理解 Playwright 的 auto-waiting。
  • 避免滥用 waitForTimeout()
  • 掌握合理等待策略。

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

时间模块做什么
0-20 分钟核心概念与词汇读概念表,重点理解 actionability 的 5 个条件。
20-45 分钟官方文档阅读读 Auto-waiting 文档,理解 action 和 assertion 各自的等待。
45-75 分钟实操练习改造硬等待脚本,验证自动等待的行为差异。
75-105 分钟示例代码改写把 waitForTimeout 全部替换成 locator/assertion 等待。
105-120 分钟复盘与作业完成改造前后对比表,完成今日问题。

核心概念与词汇

English中文场景用法
auto-waiting自动等待Use it when you explain that actions and assertions wait for conditions automatically.
actionability可操作性Use it when you describe the conditions Playwright checks before an action.
attached已挂载Use it when you describe an element being present in the DOM.
visible可见Use it when you describe an element having a visible bounding box.
stable稳定Use it when you describe an element no longer animating or moving.
enabled可用Use it when you describe a control that is not disabled.
receives events可接收事件Use it when you describe an element not covered by another element.
waitForURL()等待 URLUse it when you wait for navigation or redirects.
waitForLoadState()等待加载状态Use it when you wait for load, domcontentloaded, or networkidle.
networkidle网络空闲Use it with caution when you wait for no network requests for 500ms.
waitForTimeout()硬等待Use it only for debugging or simulating a user pause, never as synchronization.
timeout超时Use it when you describe how long an action or assertion waits before failing.

学习材料

  • 必读:[Auto-waiting](https://playwright.dev/docs/actionability)
  • 必读:[Navigations](https://playwright.dev/docs/navigations) 中关于等待的说明
  • 选读:[Timeouts](https://playwright.dev/docs/test-timeouts)

重点理解

Playwright 会在 action 前自动检查元素是否:

  • attached。
  • visible。
  • stable。
  • enabled。
  • receives events。

常见等待方式:

await expect(locator).toBeVisible();
await page.waitForURL(/dashboard/);
await page.waitForLoadState('networkidle'); // 谨慎使用
await locator.waitFor();

不推荐:

await page.waitForTimeout(5000);

除非你是在 debug 或模拟用户等待。

实操步骤

把一段使用 waitForTimeout() 的脚本改造成基于 locator/assertion 的等待。

示例代码

// 不推荐
await page.getByRole('button', { name: 'Submit' }).click();
await page.waitForTimeout(3000);
await expect(page.getByText('Success')).toBeVisible();

// 推荐:断言自带重试,等到出现为止
await page.getByRole('button', { name: 'Submit' }).click();
await expect(page.getByText('Success')).toBeVisible();

// 等待跳转用 waitForURL,而不是 sleep 后读 URL
await page.getByRole('link', { name: 'Dashboard' }).click();
await page.waitForURL(/dashboard/);

常见坑

  • 全项目散落 waitForTimeout(3000),网络一慢就超时、网络一快就浪费时间。
  • networkidle 等待长轮询/实时推送页面,永远等不到空闲。
  • 在断言前手动 sleep,以为 sleep 能替代断言的重试机制。
  • 全局 timeout 和 expect timeout 分不清:前者是整条测试,后者是单个断言。
  • 不等待就用 expect(locator).toBeVisible() 的反向断言(不可见),其实等到了超时。

今日产出

  • 一份“等待策略改造前后对比”。
  • 至少删除 2 个硬等待。

今日问题

  1. Playwright 自动等待会等什么?
  2. 为什么硬等待会导致测试不稳定或变慢?
  3. 什么情况下需要显式等待?
  4. waitForURL 适合什么场景?
  5. networkidle 为什么要谨慎使用?

复盘要点

  • 等待策略的口诀:能断言就断言,跳转等 URL,元素等 locator,sleep 只用于 debug。
  • 硬等待是 flaky 的最大来源之一,删掉它比加长它更有效。
  • 理解“自动等待 + 超时失败”后,你才能读懂测试失败日志里的等待信息。

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

新增概念

English中文
flaky test不稳定测试
synchronization同步策略
wait strategy等待策略
false negative假阴性

适用场景

让 AI 扫描测试代码找出所有硬等待并给出替代方案,或者让 AI 分析一条 flaky 测试的失败日志,判断是等待问题还是断言问题。

可复用表达 / 提示词

请扫描我的测试代码,找出所有 waitForTimeout 和 sleep,逐个说明它想等什么、应该用什么替代。
这条测试在 CI 上时好时坏,失败日志如下,请判断是等待问题、数据问题还是断言问题,并给出依据。

追问加练

  • AI 把一处 sleep 改成断言等待,你如何验证改法有效?
  • AI 说“这个 flaky 是等待问题”,你需要哪些证据才相信?
  • 为什么删硬等待可能让测试变快,也可能暴露新问题?

今日作业

  • 完成“等待策略改造前后对比”表,至少 3 组。
  • 在自己的测试里找出并删除所有硬等待。
  • 故意给页面加慢速接口(用浏览器 DevTools throttling),验证你的等待策略是否稳健。

自检清单

Previous
Day 08 · Assertions
Next
Day 10 · Weekly Review 2: Writing Stable Tests