Playwright 第14章:移动端测试
随着移动互联网的普及,移动端 Web 应用和 Hybrid 应用的测试需求越来越大。Playwright 提供了强大的移动端测试能力,让你可以在桌面环境中模拟各种移动设备的行为,无需连接真实设备即可完成大部分测试工作。
移动端测试概述
移动端测试的核心挑战在于设备的多样性和环境的复杂性。不同屏幕尺寸、操作系统版本、浏览器内核、网络条件等因素都可能导致应用表现不一致。Playwright 通过以下方式解决这些问题:
- 设备模拟(Device Mode):预置主流移动设备的配置参数
- 触摸事件模拟:模拟手指点击、滑动、捏合等手势
- 视口(Viewport)控制:精确控制浏览器视口尺寸
- 地理定位模拟:模拟不同的 GPS 位置
- 网络条件模拟:模拟 3G、4G 等网络环境
Playwright 的移动端测试不需要真实的移动设备或模拟器,所有测试都在常规浏览器中运行,但行为和效果与真实设备保持一致。
设备模拟
使用内置设备描述
Playwright 内置了大量主流移动设备的配置描述,包括 iPhone、iPad、Samsung Galaxy 等系列。通过 devices 对象可以直接获取这些配置:
import { test, expect, devices } from '@playwright/test';
// 获取 iPhone 13 的设备配置
const iPhone13 = devices['iPhone 13'];
test('在 iPhone 13 上测试页面', async () => {
const browser = await chromium.launch();
const context = await browser.newContext({
...iPhone13,
});
const page = await context.newPage();
await page.goto('https://example.com');
// 验证移动端布局
await expect(page.locator('.mobile-header')).toBeVisible();
await browser.close();
});
常用设备列表
Playwright 支持数十种设备的模拟,以下是常用设备:
| 设备名称 | 屏幕尺寸 | 设备像素比 | 类型 |
|---|---|---|---|
| iPhone 13 | 390x844 | 3 | 手机 |
| iPhone 13 Pro Max | 428x926 | 3 | 手机 |
| iPhone SE | 375x667 | 2 | 手机 |
| iPad Pro 11 | 834x1194 | 2 | 平板 |
| iPad Mini | 768x1024 | 2 | 平板 |
| Samsung Galaxy S9+ | 412x846 | 4 | 手机 |
| Samsung Galaxy Tab S4 | 712x1138 | 2.25 | 平板 |
| Pixel 5 | 393x851 | 3 | 手机 |
自定义设备配置
除了使用内置设备,你也可以自定义设备配置:
const customDevice = {
viewport: { width: 375, height: 812 },
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X)',
deviceScaleFactor: 3,
isMobile: true,
hasTouch: true,
};
test('自定义移动设备测试', async () => {
const context = await browser.newContext(customDevice);
const page = await context.newPage();
await page.goto('https://example.com');
});
Viewport 设置
Viewport(视口)是移动端测试中最基本的设置项,它决定了浏览器渲染区域的尺寸。
import { test } from '@playwright/test';
test('不同视口尺寸测试', async ({ browser }) => {
// 小屏手机
const smallContext = await browser.newContext({
viewport: { width: 320, height: 568 }, // iPhone SE
});
// 大屏手机
const largeContext = await browser.newContext({
viewport: { width: 414, height: 896 }, // iPhone 11 Pro Max
});
// 平板
const tabletContext = await browser.newContext({
viewport: { width: 1024, height: 1366 }, // iPad Pro
});
const page = await smallContext.newPage();
await page.goto('https://example.com');
// 截取不同视口下的页面快照进行对比
await page.screenshot({ path: 'mobile-small.png' });
});
响应式测试策略
对于响应式网站,建议在多个断点处进行测试:
const viewports = [
{ width: 375, height: 667 }, // 手机
{ width: 768, height: 1024 }, // 平板竖屏
{ width: 1024, height: 768 }, // 平板横屏
{ width: 1440, height: 900 }, // 桌面
];
for (const viewport of viewports) {
test(`视口 ${viewport.width}x${viewport.height} 下的页面布局`, async ({ browser }) => {
const context = await browser.newContext({ viewport });
const page = await context.newPage();
await page.goto('https://example.com');
await expect(page.locator('.main-content')).toBeVisible();
await page.screenshot({ path: `screenshot-${viewport.width}.png` });
});
}
触摸事件模拟
移动设备使用触摸交互,Playwright 提供了完整的触摸事件 API。
启用触摸事件
设置 hasTouch: true 即可启用触摸事件模拟:
const context = await browser.newContext({
hasTouch: true,
isMobile: true,
});
const page = await context.newPage();
触摸操作
// 模拟点击
await page.tap('.button');
// 模拟触摸滑动(滚动)
await page.touchscreen.swipe(0, 200); // 水平滑动
// 触摸长按(通过 hover 模拟)
await page.locator('.long-press-item').hover({ force: true });
await page.waitForTimeout(1000);
手势操作
Playwright 不直接提供捏合、缩放等手势 API,但可以通过模拟多点触控来实现:
// 模拟双指捏合缩放
async function pinchZoom(page, scale: number) {
const center = await page.locator('.pinch-target').boundingBox();
if (!center) return;
const startX = center.x + center.width / 2;
const startY = center.y + center.height / 2;
// 使用 CDP 协议模拟多点触控
await page.touchscreen.tap(startX, startY);
// 部分复杂手势需要结合 Chrome DevTools Protocol
const session = await page.context().newCDPSession(page);
await session.send('Input.dispatchTouchEvent', {
type: 'touchStart',
touchPoints: [
{ x: startX, y: startY, id: 0 },
{ x: startX + 50, y: startY, id: 1 },
],
});
// ... 后续 touchMove、touchEnd 事件
}
// 模拟滑动翻页
async function swipePage(page, direction: 'left' | 'right') {
const viewport = page.viewportSize()!;
const startX = direction === 'left' ? viewport.width * 0.8 : viewport.width * 0.2;
const endX = direction === 'left' ? viewport.width * 0.2 : viewport.width * 0.8;
await page.mouse.move(startX, viewport.height / 2);
await page.mouse.down();
await page.mouse.move(endX, viewport.height / 2, { steps: 10 });
await page.mouse.up();
}
地理定位模拟
许多移动应用依赖地理位置信息。Playwright 可以在浏览器上下文中预设地理位置:
import { test } from '@playwright/test';
test('地理定位测试', async ({ browser }) => {
const context = await browser.newContext({
geolocation: {
latitude: 31.2304, // 上海
longitude: 121.4737,
},
permissions: ['geolocation'],
});
const page = await context.newPage();
await page.goto('https://example.com/map');
await page.click('.get-location');
// 验证页面显示的位置信息
await expect(page.locator('.location-info')).toContainText('上海');
});
test('动态修改地理位置', async ({ page, context }) => {
await page.goto('https://example.com/map');
// 授予地理定位权限
await context.grantPermissions(['geolocation']);
// 动态修改地理位置
await context.setGeolocation({
latitude: 39.9042, // 北京
longitude: 116.4074,
});
await page.reload();
await page.click('.get-location');
await expect(page.locator('.location-info')).toContainText('北京');
});
实际设备测试 vs 模拟器
Playwright 的设备模拟虽然强大,但与真实设备测试仍有区别:
| 方面 | Playwright 设备模拟 | 实际设备测试 |
|---|---|---|
| 执行速度 | 快,无需部署到设备 | 慢,需要部署和配置 |
| 硬件特性 | 无法模拟(CPU、内存、传感器) | 真实硬件表现 |
| 操作系统行为 | 模拟浏览器行为,非 OS 层 | 真实 OS 行为 |
| 网络条件 | 可通过 API 模拟 | 真实网络环境 |
| 调试能力 | 强,可用 DevTools | 受限 |
| 覆盖范围 | 一次性覆盖多设备 | 每台设备单独测试 |
| 成本 | 低 | 需要维护设备集群 |
推荐策略
- CI 流水线中使用 Playwright 模拟:覆盖主要设备和断点
- 关键流程在真实设备上验证:支付、登录等核心链路
- 使用云测试平台补充:BrowserStack、Sauce Labs 等平台提供真实设备
- 性能测试使用真实设备:设备模拟无法反映真实的性能表现
Chrome DevTools 移动端调试
Playwright 可以集成 Chrome DevTools Protocol (CDP) 进行移动端调试:
test('使用 CDP 调试移动端页面', async ({ browser }) => {
const context = await browser.newContext({
...devices['iPhone 13'],
});
const page = await context.newPage();
// 开启 DevTools 调试
const cdpSession = await context.newCDPSession(page);
await cdpSession.send('Page.enable');
await cdpSession.send('Page.setTouchEmulationEnabled', {
enabled: true,
});
await page.goto('https://example.com');
// 监听控制台日志
cdpSession.on('Log.entryAdded', (entry) => {
console.log(`[${entry.level}] ${entry.text}`);
});
// 捕获性能指标
const metrics = await cdpSession.send('Performance.getMetrics');
console.log('性能指标:', metrics);
});
慢速网络模拟
模拟移动设备常见的弱网环境:
test('弱网环境测试', async ({ browser }) => {
const context = await browser.newContext({
...devices['iPhone 13'],
});
const page = await context.newPage();
const cdpSession = await context.newCDPSession(page);
// 模拟 3G 网络
await cdpSession.send('Network.emulateNetworkConditions', {
offline: false,
latency: 100, // 延迟 100ms
downloadThroughput: 750 * 1024, // 下载 750kbps
uploadThroughput: 250 * 1024, // 上传 250kbps
});
// 监听请求时间
await page.goto('https://example.com', { waitUntil: 'networkidle' });
const timing = await page.evaluate(() => performance.timing);
console.log('页面加载耗时:', timing.loadEventEnd - timing.navigationStart);
});
总结
Playwright 的移动端测试能力覆盖了设备模拟、触摸事件、地理定位、网络条件等核心场景。通过内置设备库和灵活的 API,你可以在 CI 流水线中自动执行移动端测试,快速发现布局适配、交互兼容性等问题。结合 Chrome DevTools Protocol,还可以进行更深层次的性能分析和调试。虽然不能完全替代真实设备测试,但 Playwright 的设备模拟已经足以覆盖绝大多数移动端 Web 测试需求,是实现高效移动端质量保障的重要工具。