10.1 Playwright 基础:定位、点击、输入、截图
一、Playwright 是什么?#
Playwright 是由 微软 于 2020 年正式开源的下一代浏览器自动化框架 。它专为现代 Web 应用设计,通过一个统一的 API 同时控制 Chromium、Firefox 和 WebKit 三大浏览器引擎,无论是自动化测试、数据采集还是流程自动化,都能提供高效可靠的解决方案。
截至 2026 年 4 月,Playwright 在 GitHub 上已获得超过 71.6k 颗星,npm 下载量也已超越 Selenium,成为社区最活跃的浏览器自动化工具之一 。
二、为什么选 Playwright?六大核心优势#
1. 智能自动等待机制#
传统自动化框架最头疼的问题是 “Flaky Test”(不稳定测试)——脚本时而成功时而失败,通常是因为页面元素还没加载完成就开始操作。Playwright 内置了智能自动等待机制,它会自动等待元素变得可见、可交互、稳定后才执行操作 。
// Playwright:一行代码,自动等待元素就绪后点击
await page.click('#submit-btn');
// Selenium:需要手动编写显式等待
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(ExpectedConditions.elementToBeClickable(By.id("submit-btn"))).click();javascript这让开发者不再需要写大量的 time.sleep() 或 WebDriverWait,大幅提升了脚本的稳定性。根据 2026 年的行业数据,Playwright 的首次运行通过率达到 92%,而 Selenium 仅为 72% 。
2. 多语言与跨浏览器支持#
Playwright 支持 JavaScript/TypeScript、Python、Java 和 C# 四种主流语言,团队可以根据技术栈灵活选择 。同时原生支持 Chrome、Edge、Firefox 和 Safari(WebKit),无需额外配置。
| 特性 | Playwright | Selenium | Cypress |
|---|---|---|---|
| 支持语言 | JS/TS, Python, Java, C# | Java, Python, C#, JS, Ruby 等 | 仅 JS/TS |
| 浏览器覆盖 | Chromium, Firefox, WebKit | 几乎所有浏览器(含 IE11) | Chrome, Firefox, Edge |
| 执行速度 | 非常快 | 中等 | 快 |
| 自动等待 | ✅ 内置智能等待 | ❌ 需手动配置 | ✅ 内置 |
| 多标签页/iframe | ✅ 原生支持 | ⚠️ 需额外处理 | ⚠️ 有限支持 |
3. 现代异步 API 设计#
Playwright 基于 async/await 异步编程模型,代码结构清晰直观 。每个操作都有明确的语义,例如 page.click()、page.fill()、page.locator(),上手门槛极低。
// 语义化 API,一看就懂
await page.goto('https://example.com');
await page.getByRole('button', { name: '登录' }).click();
await page.getByLabel('用户名').fill('admin');javascript4. 性能优势#
Playwright 使用 Chrome DevTools Protocol (CDP) 直接与浏览器通信,跳过了 Selenium WebDriver 的 HTTP 协议开销,每个操作节省 200-500ms 的往返时间 。实际迁移案例中,有团队将回归测试套件从 45 分钟缩短到 12 分钟 。
5. 强大的调试工具#
- Codegen(代码生成器):录制浏览器操作自动生成 Playwright 代码,不懂编程也能生成脚本
- Trace Viewer:录制完整执行过程,包含 DOM 快照、网络请求、控制台日志,支持逐帧回放调试
- 内置截图/视频:测试失败自动保存截图和视频,快速定位问题
6. 网络拦截与 Mock#
Playwright 可以轻松拦截和修改网络请求,非常适合测试前端在 API 异常时的表现 :
// Mock API 返回 500 错误,测试前端容错
await page.route('**/api/users', route =>
route.fulfill({ status: 500, body: 'Server Error' })
);javascript三、快速安装#
# 安装 Playwright
npm init playwright@latest
# 或 Python 版本
pip install playwright
playwright installbash一条命令即可安装所有浏览器依赖,无需手动下载 chromedriver 。
四、核心操作实战:定位、点击、输入、截图#
4.1 元素定位(Locators)#
Playwright 推荐使用语义化定位器,它们比传统 CSS/XPath 更稳定,且内置自动等待 。
定位策略优先级#
| 定位方式 | 语法示例 | 推荐度 |
|---|---|---|
| Role 定位(首选) | page.getByRole('button', { name: '提交' }) | ⭐⭐⭐⭐⭐ |
| 文本定位 | page.getByText('立即购买') | ⭐⭐⭐⭐ |
| Label 定位 | page.getByLabel('用户名') | ⭐⭐⭐⭐ |
| Placeholder | page.getByPlaceholder('请输入手机号') | ⭐⭐⭐ |
| Test ID | page.getByTestId('submit-btn') | ⭐⭐⭐⭐⭐ |
| CSS 选择器 | page.locator('#login-btn') | ⭐⭐ |
| XPath | page.locator('//button[text()="登录"]') | ⭐ |
// ✅ 推荐:Role + name 组合(最接近用户视角)
await page.getByRole('button', { name: 'Sign in' }).click();
// ✅ 推荐:Placeholder 定位输入框
await page.getByPlaceholder('请输入用户名').fill('admin');
// ✅ 推荐:自定义 data-testid(最稳定)
await page.getByTestId('submit-button').click();
// ❌ 避免:依赖动态 class 或 id
await page.click('.btn-primary-abc123'); // 不稳定javascript组合定位与过滤#
// 同时满足两个条件
const submitBtn = page.getByRole('button').and(page.getByTitle('提交'));
// 多选一:匹配任意一个
const newEmail = page.getByRole('button', { name: 'New email' });
const dialog = page.getByText('Security settings');
await expect(newEmail.or_(dialog)).toBeVisible();javascript4.2 点击操作(Click)#
Playwright 的点击操作内置自动等待:确保元素可见、启用且稳定后才执行 。
// 基础点击
await page.getByRole('button', { name: '登录' }).click();
// 双击
await page.getByText('提交').dblclick();
// 右键点击
await page.getByRole('button').click({ button: 'right' });
// 强制点击(跳过可操作性检查)
await page.getByRole('button').click({ force: true });
// 悬停(触发下拉菜单等)
await page.getByText('设置').hover();
// 拖拽
await page.dragAndDrop('#item1', '#dropzone');javascript4.3 输入操作(Fill / Type)#
| 方法 | 行为 | 适用场景 |
|---|---|---|
fill() | 清空后一次性填入 | 表单输入(推荐) |
pressSequentially() | 模拟逐字输入 | 需要触发输入事件的场景 |
// ✅ 推荐:fill 快速填入(自动清空原有内容)
await page.getByLabel('用户名').fill('testuser');
await page.getByPlaceholder('密码').fill('secret123');
// 逐字输入(模拟真实打字,可配合 delay)
await page.getByRole('textbox').pressSequentially('Hello World', { delay: 100 });
// 键盘按键
await page.getByRole('textbox').press('Enter');
await page.keyboard.press('Control+a'); // 组合键
// 清空输入框
await page.getByRole('textbox').clear();
// 下拉选择
await page.getByLabel('城市').selectOption('Beijing');
// 文件上传
await page.locator('input[type="file"]').setInputFiles('./photo.jpg');javascript4.4 截图(Screenshot)#
Playwright 提供灵活的截图能力,支持页面、元素、全页截图 。
// 1. 页面截图(视口区域)
await page.screenshot({ path: 'screenshot.png' });
// 2. 全页截图(完整滚动页面)
await page.screenshot({ path: 'fullpage.png', fullPage: true });
// 3. 元素截图
await page.getByRole('img', { name: 'Logo' }).screenshot({ path: 'logo.png' });
// 4. 二进制数据(用于比对或上传)
const buffer = await page.screenshot();javascript高级截图选项#
await page.screenshot({
path: 'result.png',
type: 'jpeg', // png(默认) | jpeg
quality: 80, // jpeg 质量 0-100
fullPage: true, // 滚动截取完整页面
clip: { x: 0, y: 0, width: 800, height: 600 }, // 裁剪区域
omitBackground: true, // 透明背景
animations: 'disabled' // 禁用CSS动画
});javascript测试失败自动截图#
在 playwright.config.ts 中配置:
export default defineConfig({
use: {
screenshot: 'only-on-failure', // 失败时自动截图
video: 'on-first-retry' // 重试时录制视频
}
});javascript五、完整实战:模拟登录并截图#
以下是一个模拟 GitHub 登录并截图的完整脚本:
const { chromium } = require('playwright');
(async () => {
// 1. 启动浏览器
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
// 2. 导航到登录页
await page.goto('https://github.com/login');
// 3. 定位并输入(使用语义化定位器)
await page.getByLabel('Username or email address').fill('your_username');
await page.getByLabel('Password').fill('your_password');
// 4. 点击登录
await page.getByRole('button', { name: 'Sign in' }).click();
// 5. 等待导航完成
await page.waitForURL('https://github.com/');
// 6. 截图保存
await page.screenshot({ path: 'github_homepage.png', fullPage: true });
console.log('登录成功,已截图');
// 7. 关闭浏览器
await browser.close();
})();javascript六、选型建议:什么时候用 Playwright?#
根据 2026 年的行业调研,62% 的新项目选择 Playwright 而非 Selenium 。以下是选型决策树:
是否需要支持 Safari/跨浏览器?
├── 是 → 排除 Cypress,考虑 Playwright 或 Selenium
│ 是否需要 IE11 支持?
│ ├── 是 → 选 Selenium
│ └── 否 → 选 Playwright
└── 否 → 团队技术栈是否为纯 JS/TS?
├── 是 → Cypress 或 Playwright(推荐 Playwright 获得更好稳定性)
└── 否(Java/Python 等)→ 选 Playwrightplaintext总结建议:
- 新项目/现代 Web 应用:首选 Playwright,自动等待和多语言支持能大幅降低维护成本
- 已有大量 Selenium 投资:无需强行迁移,Selenium 的生态系统仍然最成熟
- 前端团队/纯 JS 项目:Cypress 的调试体验极佳,但受限于浏览器支持
七、核心最佳实践#
- 永远优先使用语义化定位器:
getByRole>getByText>getByLabel> CSS - 利用自动等待:无需手动
sleep,Playwright 会自动等待元素可操作 - 避免硬编码时间:用
waitForURL、waitForSelector替代setTimeout - 使用 Web-First 断言:
expect(locator).toBeVisible()会自动重试 - 保持测试隔离:每个测试使用独立的
browser.newContext()
API 速查表#
| 操作 | 方法 | 说明 |
|---|---|---|
| 定位 | page.locator(selector) | 通用定位器 |
page.getByRole(role, {name}) | 按 ARIA 角色 | |
page.getByText(text) | 按可见文本 | |
page.getByLabel(text) | 按标签文本 | |
page.getByTestId(id) | 按自定义 ID | |
| 点击 | locator.click() | 单击 |
locator.dblclick() | 双击 | |
locator.hover() | 悬停 | |
| 输入 | locator.fill(text) | 清空并填入 |
locator.pressSequentially(text) | 逐字输入 | |
locator.clear() | 清空 | |
locator.press(key) | 按键 | |
| 截图 | page.screenshot() | 页面截图 |
locator.screenshot() | 元素截图 |
Playwright 以其现代化的设计、出色的稳定性和强大的调试能力,正在迅速成为浏览器自动化领域的事实标准。无论你是前端开发者、QA 工程师还是爬虫开发者,掌握 Playwright 都能显著提升你的工作效率。