Playwright 测试框架:多浏览器自动化与网络拦截

FreeGuideOnline 最新 2026-06-12

Playwright 自动化浏览器测试入门:多浏览器自动化与网络拦截

Playwright 是一款由微软开源的端到端测试框架,它能够通过单一 API 自动操控 Chromium、Firefox 和 WebKit 浏览器,并且内置了强大的网络拦截与控制能力。本教程将带你从零开始,掌握 Playwright 的多浏览器执行与网络模拟技巧。

为什么选择 Playwright?

  • 跨浏览器一致性:一套代码,同时测试 Chrome、Edge、Firefox、Safari。
  • 自动等待机制:内置智能等待,无需手动添加 sleep,减少测试不稳定。
  • 强大的网络控制:可以拦截、修改、模拟网络请求与响应。
  • 移动端模拟:轻松模拟移动设备、地理位置、权限等。
  • 多语言支持:JavaScript/TypeScript、Python、C#、Java。

环境准备

首先确保已安装 Node.js(版本 14 以上)。创建项目文件夹并初始化:

mkdir playwright-demo && cd playwright-demo
npm init -y

安装 Playwright 和内置浏览器:

npm install @playwright/test
npx playwright install

npx playwright install 会下载 Chromium、Firefox 和 WebKit 三个浏览器内核,下载一次即可。

编写第一个多浏览器测试

Playwright 的测试模块 @playwright/test 提供了 testexpect,并且可以轻松配置多浏览器项目。

创建 tests/example.spec.js

const { test, expect } = require('@playwright/test');

test('验证页面标题', async ({ page }) => {
  await page.goto('https://example.com');
  // 自动等待标题变为指定内容
  await expect(page).toHaveTitle(/Example Domain/);
});

在项目根目录创建配置文件 playwright.config.js

const { defineConfig } = require('@playwright/test');

module.exports = defineConfig({
  testDir: './tests',
  timeout: 30 * 1000,
  retries: 1,
  use: {
    headless: true,
    screenshot: 'only-on-failure',
    video: 'retain-on-failure',
  },
  projects: [
    { name: 'Chromium', use: { browserName: 'chromium' } },
    { name: 'Firefox',  use: { browserName: 'firefox' } },
    { name: 'WebKit',   use: { browserName: 'webkit' } },
  ],
});

现在运行测试,Playwright 会自动在三个浏览器中执行:

npx playwright test

运行结果会显示每个浏览器的测试通过情况。如果只想在单个浏览器上运行,可以使用 --project 参数:

npx playwright test --project=Chromium

多浏览器中的差异化操作

有时不同浏览器的行为可能不一致,你可以在测试中根据浏览器类型编写条件代码。

test('多浏览器条件执行', async ({ page, browserName }) => {
  await page.goto('https://example.com');

  if (browserName === 'webkit') {
    // 只在 WebKit (Safari) 中执行的逻辑
    console.log('Running WebKit specific check');
  }

  // 通用断言
  await expect(page.locator('h1')).toBeVisible();
});

网络拦截基础

Playwright 提供了 page.route() 方法,可以拦截、修改或mock任何网络请求。

拦截并修改请求

假设你想阻止图片加载以加快测试速度:

test('阻止图片加载', async ({ page }) => {
  // 拦截所有图片请求,直接返回空响应
  await page.route('**/*.{png,jpg,jpeg,gif,svg}', route => route.abort());

  await page.goto('https://example.com');
  // 页面中的图片都不会加载
});

route.abort() 中止请求,route.fulfill() 可以提供自定义响应。

模拟 API 响应

在测试中,我们经常需要 mock 后端接口返回数据:

test('模拟用户接口数据', async ({ page }) => {
  // 拦截 GET 请求 /api/user,返回模拟数据
  await page.route('**/api/user', route => {
    route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify({ name: 'Test User', age: 30 })
    });
  });

  await page.goto('https://your-app.com/profile');
  // 页面将显示模拟的用户数据
});

route.fulfill 可以自定义状态码、头信息和响应体。

修改请求头

有些场景需要为所有请求添加认证头:

test('为请求添加自定义头', async ({ page }) => {
  await page.route('**/*', route => {
    const headers = {
      ...route.request().headers(),
      'X-Custom-Token': 'my-secret-token'
    };
    route.continue({ headers });
  });

  await page.goto('https://example.com');
  // 所有请求都会携带自定义头
});

拦截并修改响应

你可以捕获实际响应,修改内容后再返回给页面:

test('修改响应内容', async ({ page }) => {
  await page.route('**/api/data.json', async route => {
    const response = await route.fetch();
    let body = await response.text();
    // 将响应中的 "old" 替换为 "new"
    body = body.replace(/old/g, 'new');
    route.fulfill({
      status: response.status(),
      headers: response.headers(),
      body
    });
  });

  await page.goto('https://your-app.com');
});

高级网络控制:等待特定网络请求

你可以等待某个特定的网络请求完成,并检查其细节。

test('等待请求并检查数据', async ({ page }) => {
  const [response] = await Promise.all([
    page.waitForResponse('**/api/products'),
    page.goto('https://your-store.com')
  ]);

  const json = await response.json();
  expect(json.length).toBeGreaterThan(0);
});

结合网络拦截与等待,可以构建出非常可靠的测试场景。

实战:完整测试示例

假设有一个天气查询页面,我们模拟天气 API 返回固定数据,并测试页面显示。

test('天气查询功能测试', async ({ page }) => {
  // 拦截天气 API
  await page.route('**/api/weather**', route => {
    route.fulfill({
      status: 200,
      body: JSON.stringify({
        city: '北京',
        temperature: 28,
        condition: '晴朗'
      })
    });
  });

  await page.goto('https://weather-app.com');
  await page.fill('#city-input', '北京');
  await page.click('#search-btn');

  // 断言页面显示了模拟的数据
  await expect(page.locator('.temperature')).toHaveText('28°C');
  await expect(page.locator('.condition')).toHaveText('晴朗');
});

小结

Playwright 提供了开箱即用的多浏览器支持和极其灵活的网络拦截能力。通过本教程,你学会了:

  • 配置并运行跨浏览器的自动化测试
  • 使用 page.route 进行请求拦截、修改和 mock
  • 结合网络控制构建稳定的端到端测试

你可以将这些技术用于接口模拟、加载优化测试、错误场景复现等众多场景。继续探索 Playwright 的更多高级特性,如生成代码、追踪测试执行、CI/CD 集成等,让你的测试体系更加健壮。


下一步推荐学习:

  • Playwright 官方文档
  • 使用 Playwright Test Runner 组织大型测试套件
  • 截图与视频录制的高级配置