入门基础
Day 02 - Understanding the Test File Structure
今日目标
- 看懂 Playwright 的测试语法。
- 理解
test、expect、page的关系。 - 能写第一个自己的测试。
学习时间安排(60–120 分钟)
| 时间 | 模块 | 做什么 |
|---|---|---|
| 0-20 分钟 | 核心概念与词汇 | 读概念表,重点理解 test、expect、fixture、async/await 四个词。 |
| 20-45 分钟 | 官方文档阅读 | 读 Writing tests 的 test structure 部分,对照昨天的 example.spec.ts。 |
| 45-75 分钟 | 实操练习 | 创建 tests/day02-basic.spec.ts,完成 3 条测试。 |
| 75-105 分钟 | 示例代码改写 | 把示例 URL 换成自己的练习网站,补充第 4、5 条测试。 |
| 105-120 分钟 | 复盘与作业 | 完成今日问题,逐行解释自己写的测试。 |
核心概念与词汇
| English | 中文 | 场景用法 |
|---|---|---|
test() | 定义测试用例 | Use it when you declare a test case and give it a readable name. |
expect() | 断言 | Use it when you verify page state, text, URL, or element visibility. |
| fixture | 测试夹具 | Use it when you explain where page, context, request come from in the test signature. |
page | 页面对象 | Use it when you navigate, locate elements, and interact with one tab of the browser. |
async / await | 异步等待 | Use it when you explain why every browser operation returns a Promise. |
| spec file | 测试文件 | Use it when you explain that *.spec.ts files contain test cases. |
| assertion | 断言 | Use it when you describe the expected business outcome of a test. |
| locator | 定位器 | Use it when you describe how to find an element on the page. |
page.goto() | 打开页面 | Use it when you navigate to a URL at the start of a test. |
toHaveTitle() | 标题断言 | Use it when you verify the browser tab title. |
toHaveURL() | URL 断言 | Use it when you verify navigation or redirect results. |
| readable name | 可读的用例名 | Use it when you name a test so the report reads like user behavior. |
学习材料
- 必读:[Writing tests](https://playwright.dev/docs/writing-tests)(First test 与 Test structure 部分)
- 必读:[Assertions](https://playwright.dev/docs/test-assertions) 的开头部分
- 选读:[Test isolation](https://playwright.dev/docs/browser-contexts) 中关于 BrowserContext 的说明
重点理解
import { test, expect } from '@playwright/test';
test('has title', async ({ page }) => {
await page.goto('https://playwright.dev/');
await expect(page).toHaveTitle(/Playwright/);
});
概念解释:
test():定义一个测试用例。async/await:等待异步浏览器操作完成。{ page }:Playwright 内置 fixture,每个测试拿到独立的页面。page.goto():打开页面。expect():断言。toHaveTitle():页面标题断言,支持正则表达式。
实操步骤
创建文件:
tests/day02-basic.spec.ts
写 3 个测试:
- 打开 Playwright 官网,断言 title。
- 查找 Get started 链接。
- 点击 Get started 后断言 URL 包含
/docs/intro。
示例代码
import { test, expect } from '@playwright/test';
test('open Playwright homepage', async ({ page }) => {
await page.goto('https://playwright.dev/');
await expect(page).toHaveTitle(/Playwright/);
});
test('get started link is visible', async ({ page }) => {
await page.goto('https://playwright.dev/');
await expect(page.getByRole('link', { name: 'Get started' })).toBeVisible();
});
test('navigate to docs', async ({ page }) => {
await page.goto('https://playwright.dev/');
await page.getByRole('link', { name: 'Get started' }).click();
await expect(page).toHaveURL(/.*docs\/intro/);
});
常见坑
- 忘记
await,浏览器操作在断言前还没执行完。 - 把
page理解成整个浏览器——它只代表一个标签页,浏览器是browser,上下文是context。 - 用
expect(await locator.textContent()).toBe(...)代替 web-first assertion,丢失自动重试。 - 测试名写得太技术化(如
test case 3),报告里看不出业务意图。 - 一个测试塞进 10 个断言,失败时定位不了是哪一步出了问题。
今日产出
- 一个包含 3 条测试用例的 spec 文件。
- 能解释每一行代码的作用。
今日问题
- 为什么 Playwright 的 API 大量使用
await? page是浏览器页面还是浏览器本身?expect(page).toHaveURL()和手动读取 URL 后比较有什么区别?- 测试文件命名为什么常用
.spec.ts? - 一个测试用例应该验证几个目标?
复盘要点
- 测试文件 =
test()+expect()+ fixture,这是未来 30 天的全部语法基础。 - 从今天开始,每写一行代码都问自己:这一行在模拟用户做什么?
- 把
toHaveTitle、toHaveURL、toBeVisible三个断言记成你的第一批武器。
AI 时代扩展:AI 辅助 Playwright 测试
新增概念
| English | 中文 |
|---|---|
| code completion | 代码补全 |
| AI code review | AI 代码审查 |
| assertion quality | 断言质量 |
| test intent | 测试意图 |
适用场景
让 AI 解释你写的测试每一行做了什么,或者让 AI 检查你的测试缺少哪些断言。注意:AI 解释语法很可靠,但判断业务是否该这样断言时,你需要自己把关。
可复用表达 / 提示词
逐行解释下面这段 Playwright 测试在做什么,并指出哪一行最容易失败。
我的测试目标是「验证用户能从首页跳到文档页」,请检查我的断言是否真正验证了这个目标。
追问加练
- AI 说“这条断言是多余的”,你会用什么标准判断它说得对不对?
- 测试意图不清会导致什么维护问题?
- 哪类断言 AI 无法替你判断正确性?
今日作业
- 把 3 条测试复制一份,换成任意练习网站(如 TodoMVC)再跑通。
- 给每条测试写上注释:它在模拟哪个用户动作、验证哪个业务结果。
- 让 AI 逐行解释你的测试,找出并修正你理解错误的行。