Playwright 自动化测试:跨浏览器与移动模拟
Playwright 自动化测试:从入门到跨浏览器移动端模拟
Playwright 是由微软开源的一个自动化测试框架,它通过单一 API 支持 Chromium、Firefox 和 WebKit 三大引擎,并能轻松模拟移动设备、处理网络拦截,是端到端测试领域的现代利器。本教程将带你从零搭建环境,掌握多浏览器测试与移动端模拟的核心技能。
1. 什么是 Playwright,为什么选择它
Playwright 能够自动操控浏览器进行页面跳转、表单填写、点击、截图等操作,常用于:
- 端到端(E2E)测试:验证用户真实操作路径
- 爬虫与数据抓取:处理动态渲染页面
- 自动化任务:生成 PDF、监控页面状态
相比 Selenium 等传统工具,Playwright 具备以下优势:
- 自带浏览器,无需额外安装驱动
- 自动等待元素可操作,减少 flaky 测试
- 网络拦截、修改请求和响应
- 原生支持移动端模拟、地理位置、权限控制
- 多页面、多上下文隔离,运行速度快
2. 环境准备与第一个脚本
2.1 安装 Node.js
Playwright 官方推荐使用 Node.js 环境。请确保已安装 Node.js 16 以上版本。 在终端执行:
node -v
2.2 初始化项目并安装 Playwright
mkdir playwright-demo && cd playwright-demo
npm init -y
npm install playwright
安装完成后,执行浏览器安装命令(会下载 Chromium、Firefox、WebKit):
npx playwright install
2.3 编写第一个测试脚本
创建 example.js 文件:
const { chromium } = require('playwright');
(async () => {
// 启动浏览器(默认无头模式,设为 false 可看到界面)
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto('https://example.com');
// 获取页面标题
const title = await page.title();
console.log('页面标题:', title);
await browser.close();
})();
运行:
node example.js
3. 基本元素定位与交互
Playwright 提供了强大的选择器引擎,支持文本、CSS、XPath、角色等定位方式。
3.1 点击与输入
// 文本选择器(推荐,语义清晰)
await page.click('text=登录');
// CSS 选择器
await page.fill('#username', 'myuser');
// 按占位文字填写
await page.fill('input[placeholder="密码"]', '123456');
// 通过角色定位(无障碍树)
await page.click('button:has-text("提交")');
3.2 自动等待机制
Playwright 在执行动作前会自动检查元素是否附着到 DOM、是否可见、是否稳定,无需显式 sleep。
// 点击后页面可能跳转,playwright 会等待新页面加载完成
await page.click('a[href="/next"]');
4. 跨浏览器测试:同一脚本运行于三大引擎
Playwright 的精华在于一套代码同时测试 Chromium、Firefox、WebKit。
4.1 启动不同浏览器
const { chromium, firefox, webkit } = require('playwright');
(async () => {
for (const browserType of [chromium, firefox, webkit]) {
const browser = await browserType.launch();
const page = await browser.newPage();
await page.goto('https://whatsmyua.com');
// 打印用户代理,验证不同浏览器环境
const ua = await page.evaluate(() => navigator.userAgent);
console.log(`${browserType.name()} UA:`, ua);
await browser.close();
}
})();
4.2 复用测试逻辑
实际项目中,通常使用测试运行器(如 Playwright Test)组织用例,但核心思想是通过参数化浏览器类型来覆盖多引擎。
5. 移动设备模拟与视口定制
Playwright 内置了数十种设备的预设(iPhone、Pixel、iPad 等),可模拟屏幕尺寸、userAgent、触摸事件等。
5.1 使用内置设备描述符
const { chromium, devices } = require('playwright');
const iPhone = devices['iPhone 12'];
(async () => {
const browser = await chromium.launch();
const context = await browser.newContext({
...iPhone, // 展开设备配置
locale: 'zh-CN', // 语言/地区
permissions: ['geolocation'],
geolocation: { longitude: 116.4074, latitude: 39.9042 },
});
const page = await context.newPage();
await page.goto('https://www.baidu.com');
await page.screenshot({ path: 'iphone-baidu.png' });
await browser.close();
})();
5.2 自定义视口与 UserAgent
如果没有预设的设备,你可以手动指定:
const context = await browser.newContext({
viewport: { width: 375, height: 812 },
userAgent: 'Mozilla/5.0 (Linux; Android 10; SM-G980F) AppleWebKit/537.36 ...',
isMobile: true,
hasTouch: true,
});
5.3 模拟网络条件
通过 context.setOffline() 或 page.route() 可实现离线测试或网络节流:
const context = await browser.newContext({
...iPhone,
offline: false,
});
// 注意:真正的网络节流需要在上下文创建后使用 CDPSession(仅Chromium)
// 但大多数移动模拟场景中,关注点是视口与交互
6. 典型测试场景实战
6.1 自动登录与状态验证
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://example.com/login');
await page.fill('#email', 'user@test.com');
await page.fill('#password', 'pass123');
await page.click('button[type="submit"]');
// 等待导航到用户首页
await page.waitForURL('**/dashboard');
const welcomeText = await page.textContent('.welcome');
console.log('欢迎信息:', welcomeText);
await browser.close();
})();
6.2 移动端触摸滑动
在模拟移动设备时,可以直接使用触摸操作:
const { webkit, devices } = require('playwright');
const iPhone = devices['iPhone 13'];
(async () => {
const browser = await webkit.launch();
const context = await browser.newContext(iPhone);
const page = await context.newPage();
await page.goto('https://m.baidu.com');
// 触摸滑动:从 (x1, y1) 滑动到 (x2, y2)
await page.touchscreen.tap(100, 200); // 单点触摸
// 模拟滑动搜索框聚焦
await page.tap('input[name="word"]');
await page.fill('input[name="word"]', 'Playwright');
await page.click('button[type="submit"]');
await page.screenshot({ path: 'mobile_search.png' });
await browser.close();
})();
7. 进阶技巧:网络拦截与断言
7.1 拦截请求并修改响应
await page.route('**/*.png', route => route.abort()); // 拦截所有图片
// 模拟 API 返回
await page.route('**/api/user', route => {
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ name: 'MockUser', id: 1 })
});
});
7.2 常用断言(需配合 @playwright/test 或手动)
即使不用测试运行器,也可以手动断言:
const { expect } = require('@playwright/test'); // 需要安装
// 或使用 Node 内置 assert
const assert = require('assert');
const title = await page.title();
assert.strictEqual(title, '预期标题');
8. 常见问题与调试
- 元素找不到:使用
page.pause()进入调试模式,或在启动时设置{ headless: false, slowMo: 100 }观察操作流程。 - 移动端点击失效:确认
context配置了isMobile: true,并使用page.tap()而非page.click()。 - 等待超时:提高默认超时
browser.newPage({ timeout: 60000 }),或使用更智能的等待如page.waitForResponse()。
9. 总结与学习路径
通过本教程,你已经掌握:
- Playwright 的环境搭建与基本操作
- 跨 Chromium、Firefox、WebKit 的测试执行
- 移动设备模拟与触摸交互
- 网络拦截与断言思路
下一步建议:
- 学习 Playwright Test Runner 编写结构化的测试用例
- 探索 Trace Viewer 分析测试步骤时间线
- 研究 Page Object Model 提升代码可维护性
Playwright 让你以贴近用户的方式验证应用质量,无论是 Web 还是移动 Web,一套代码即可全平台覆盖。