Playwright 问题整理
1. 什么是 Playwright?
答法: Playwright 是微软推出的一个现代化 Web 自动化测试框架,用来做端到端测试、UI 自动化、跨浏览器测试,也支持接口测试。 它可以驱动 Chromium、Firefox、WebKit,支持多标签页、iframe、网络拦截、截图、录屏、Trace 等能力,比较适合现代前端项目。
2. Playwright 和 Selenium 有什么区别?
答法:
Playwright 优势
- 原生支持多浏览器
- 自动等待机制更强
- API 更现代,开发体验更好
- 对 SPA、动态页面支持更友好
- 自带 Trace、Mock、并发、多上下文等功能
Selenium 特点
- 生态更老、更广
- 历史包袱更重
- 某些传统测试体系里还很多
一句话总结
如果是现代前端项目,Playwright 一般更高效、更稳定。
3. Playwright 支持哪些浏览器?
答法: 支持三大浏览器引擎:
- Chromium
- Firefox
- WebKit
其中 Chromium 也覆盖 Chrome 和 Edge 这类 Chromium 内核浏览器。
4. Playwright 的核心对象有哪些?
答法:
browser:浏览器实例context:浏览器上下文,类似一个独立会话page:具体页面,一个 tablocator:元素定位器test:测试定义expect:断言工具
一般测试最常接触的是 page、locator、expect。
5. Browser、Context、Page 的区别是什么?
答法:
browser:整个浏览器context:浏览器里的独立环境,类似无痕窗口,可隔离 cookie / localStoragepage:上下文中的一个页面标签
举例
一个浏览器里可以开多个 context, 每个 context 里又可以开多个 page。
这在多用户登录、隔离测试场景很有用。
6. Playwright 为什么比别的工具稳定?
答法: 一个重要原因是它的自动等待机制。 比如点击、输入、断言时,Playwright 会自动等待元素满足可见、可交互、稳定等条件,而不是立刻执行。
这减少了很多因为页面加载慢、元素未渲染完成导致的偶发失败。
7. 什么是 Locator?为什么推荐 Locator?
答法: Locator 是 Playwright 推荐的元素定位方式。 它不是一次性抓 DOM,而是带有自动重试和自动等待能力的定位对象。
为什么推荐
- 更稳定
- 支持链式操作
- 配合断言更自然
- 比直接
querySelector思路更适合测试场景
8. 常见定位方式有哪些?推荐顺序是什么?
答法:
常见方式:
getByRolegetByLabelgetByPlaceholdergetByTextgetByTestIdlocator(css)xpath
推荐顺序
getByRolegetByLabelgetByPlaceholdergetByTestId- CSS
- XPath
原因
越语义化,越稳定,越贴近用户真实操作。
9. 为什么不推荐大量使用 XPath?
答法: XPath 通常可读性差、维护成本高,而且容易和页面结构强耦合。 页面层级稍微改一下,XPath 就可能失效。 除非特殊场景,否则更推荐语义化定位或者稳定的 testId。
10. Playwright 中常见断言有哪些?
答法:
toHaveTitletoHaveURLtoBeVisibletoBeHiddentoHaveTexttoContainTexttoHaveValuetoHaveCounttoBeCheckedtoBeEnabled
这些断言本身也带自动等待。
11. page.locator() 和 page.getByRole() 有什么区别?
答法:
locator()更通用,可以写 CSS/XPath/复杂选择器getByRole()更语义化,更贴近无障碍标准,更推荐优先使用
如果页面本身语义做得好,getByRole() 往往更稳定,也更能体现从用户视角操作页面。
12. Playwright 中等待机制有哪些?
答法:
常见等待方式:
- 自动等待
expect(...).toBeVisible()这种断言等待locator.waitFor()page.waitForURL()page.waitForResponse()page.waitForRequest()
不推荐
waitForTimeout()
因为它是固定死等,慢且不稳定。
13. 为什么不推荐 waitForTimeout()?
答法: 因为它是拍脑袋等待。
问题有两个:
- 等短了,页面没准备好,测试失败
- 等长了,测试变慢
更好的方式是等待明确条件,比如元素可见、URL 变化、接口响应成功。
14. Playwright 如何处理 iframe?
答法:
通过 frameLocator()。
const frame = page.frameLocator('#my-frame');
await frame.getByRole('button', { name: '提交' }).click();
这样可以在 iframe 内继续使用 Playwright 的定位和断言能力。
15. 如何处理新窗口或新标签页?
答法:
const [newPage] = await Promise.all([
page.waitForEvent('popup'),
page.getByText('打开').click(),
]);
然后对 newPage 做操作和断言。
16. 如何处理文件上传和下载?
答法:
上传
用 setInputFiles():
await page.locator('input[type="file"]').setInputFiles('./a.png');
下载
监听 download 事件:
const downloadPromise = page.waitForEvent('download');
await page.getByText('下载').click();
const download = await downloadPromise;
await download.saveAs('./downloads/a.xlsx');
17. 如何处理弹窗 alert / confirm / prompt?
答法:
通过监听页面的 dialog 事件:
page.on('dialog', async dialog => {
console.log(dialog.message());
await dialog.accept();
});
如果要取消,就用 dismiss()。
18. Playwright 中如何做接口 Mock?
答法:
通过 page.route() 拦截请求,再用 route.fulfill() 返回假数据。
await page.route('**/api/user', async route => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ name: '张三' }),
});
});
这在前后端并行开发、异常场景测试、边界测试里很常用。
19. 如何监听接口请求或响应?
答法:
监听响应:
await page.waitForResponse(resp =>
resp.url().includes('/api/user') && resp.status() === 200
);
监听请求:
await page.waitForRequest('**/api/login');
20. Playwright 如何复用登录状态?
答法:
通过 storageState 保存 cookie 和本地存储状态。
保存
await page.context().storageState({ path: 'playwright/.auth/user.json' });
使用
在配置中:
use: {
storageState: 'playwright/.auth/user.json',
}
这样可以避免每条用例都重复登录,提高执行效率。
21. 什么是 Page Object Model(POM)?
答法: POM 是页面对象模型,把页面元素和页面操作封装成类,提高复用性和可维护性。
优点
- 减少重复代码
- 页面改动时更容易统一维护
- 测试代码更清晰
适用场景
当项目页面多、流程复杂时,POM 很有价值。
22. POM 有什么缺点?
答法: 如果封装过度,会造成:
- 层级过深
- 维护成本上升
- 简单测试反而变复杂
所以我一般会适度封装,只把高复用页面和公共流程抽出去,不会为了封装而封装。
这个回答面试官通常会觉得你比较实战,不是只会背概念。
23. Playwright 如何做跨浏览器测试?
答法:
在 playwright.config.ts 里配置多个 projects:
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
]
运行时就可以并行在不同浏览器上执行。
24. Playwright 如何调试失败用例?
答法:
常用方法:
--debugpage.pause()--headed- 看截图
- 看视频
- 看 Trace
其中 Trace 最有价值,因为它能完整回放测试过程,包括点击、网络、DOM 快照、控制台信息。
25. 什么是 Trace?为什么有用?
答法: Trace 是 Playwright 的执行追踪能力。 失败后可以回看测试执行的完整上下文,比如:
- 每一步操作
- 页面快照
- 请求响应
- 控制台日志
- 错误信息
这比单纯看报错日志更容易定位问题。
26. Playwright 如何做 API 测试?
答法:
Playwright 除了页面测试,也支持接口测试,可以用 request fixture 发送 HTTP 请求。
test('api test', async ({ request }) => {
const resp = await request.get('/api/user');
expect(resp.ok()).toBeTruthy();
});
适合把 UI 测试和部分接口验证放到同一套框架里。
27. E2E 测试和 UI 自动化测试的区别是什么?
答法:
- UI 自动化测试 更偏页面层面,比如按钮、表单、页面展示
- E2E 测试 更强调完整业务链路,从前端到后端到数据库的一整条流程
Playwright 常用于 E2E,也可以做单纯的 UI 自动化。
28. Playwright 适合做什么,不适合做什么?
答法:
适合
- Web E2E 测试
- 回归测试
- 多浏览器兼容测试
- UI 自动化
- 一部分 API 测试
不太适合
- 非浏览器桌面应用自动化
- 极重度性能压测
- 完全替代后端接口测试体系
29. 如何让 Playwright 测试更稳定?
答法:
我的做法一般有这几条:
- 优先用稳定定位方式,比如
getByRole、getByTestId - 少用固定等待,多用显式条件等待
- 保证测试数据独立
- 公共流程适度封装
- 对失败场景保留截图、视频、Trace
- 控制测试之间依赖
- 尽量避免一条用例验证太多事情
30. 如何设计高质量自动化测试用例?
答法: 我会关注这几件事:
- 用例目标明确,一个 case 验证一个核心点
- 可重复执行,不依赖前序状态
- 数据可控,方便回归
- 优先覆盖核心业务路径
- 正常场景 + 异常场景都要有
- 保证断言是有效断言,不只是“点了一遍没报错”
31. 自动化测试里最容易踩的坑是什么?
答法:
常见坑有:
- 定位不稳定
- 依赖固定等待
- 用例之间相互依赖
- 测试环境数据污染
- 一个 case 写太长
- 失败后缺少证据,难排查
如果我来落地项目,我会优先从“定位规范、等待策略、测试数据隔离、失败证据”这几个方面先定规则。
32. Playwright 和 Cypress 有什么区别?
答法:
Playwright 优势
- 浏览器支持更完整,含 WebKit
- 多页面、多标签支持更自然
- 自动化能力更强
- API 测试、Mock、权限、下载上传等更灵活
Cypress 特点
- 上手也快
- 前端圈有一定普及
- 但某些复杂浏览器场景不如 Playwright 灵活
如果是新项目,我一般更倾向 Playwright。
33. 你在项目中怎么落地 Playwright?
这个很高频,建议这样答。
参考答法:
我一般会这样落地:
- 先确定自动化范围,优先覆盖核心主流程
- 设计目录结构,比如页面对象、测试用例、公共方法、测试数据分层
- 建立定位规范,优先
getByRole/getByTestId - 封装登录、公共导航、数据准备等高频动作
- 配好失败截图、视频、Trace
- 接入 CI,让主干分支自动跑回归
- 后续根据缺陷和变更持续补充回归用例
这样能保证自动化不是“写了一堆脚本”,而是真能服务质量保障。
34. 如果测试很慢,你怎么优化?
答法:
我会从几方面优化:
- 复用登录态,减少重复登录
- 并行执行测试
- 减少不必要的 UI 操作
- 用 API 准备测试数据
- 只在失败时保留重型证据
- 拆分冒烟、回归、全量测试分层执行
35. 如果某条用例偶发失败,你怎么排查?
答法: 我会按这个顺序排查:
- 看报错点
- 看截图 / 视频 / Trace
- 判断是环境问题、数据问题还是脚本问题
- 检查定位是否稳定
- 检查是不是等待条件写得不对
- 看接口响应是否异常
- 如果是偶发,就分析是否存在异步加载、动画、弹窗遮挡、脏数据等问题
重点不是“重跑过了就算了”,而是定位 flakiness 的根因。
36. 你觉得 Playwright 的最佳实践有哪些?
答法:
- 语义化定位优先
- 少 sleep,多等条件
- 测试独立
- 公共流程适度封装
- 核心流程优先自动化
- 失败证据完整
- CI 持续执行
- 测试代码也要像生产代码一样维护质量
面试加分回答模板
如果面试官问:
“你为什么选 Playwright?”
你可以这样答:
因为它对现代 Web 应用支持比较好,自动等待和跨浏览器能力都很强,而且调试工具完善,像 Trace、Mock、下载上传、多标签页这些场景都支持得比较成熟。对于前端项目的 E2E 和回归测试,落地效率很高。
“你在项目里怎么保证脚本可维护?”
你可以这样答:
我会先统一定位策略和目录结构,然后把高复用流程做适度封装,比如登录、导航、数据准备,同时避免过度封装。测试用例保持目标单一、相互独立,失败时保留 Trace 和截图,这样维护成本会低很多。
“Playwright 稳定性怎么保证?”
你可以这样答:
关键是定位策略、等待策略和数据隔离。优先用稳定定位方式,避免固定等待;测试数据尽量独立;同时保留失败现场,这样既能减少 flaky case,也能快速定位问题。
最后给你一个面试建议
如果你真要拿它去面试,最值得准备的是这 4 类:
- 基础概念:browser / context / page / locator
- 稳定性:自动等待、少 sleep、定位规范
- 工程化:POM、目录结构、CI、登录态复用
- 实战排错:Trace、Mock、偶发失败怎么查
这几类答顺了,基本就不像“只看过文档的人”。