跳到主要内容

从 Puppeteer 迁移

迁移原则

本指南描述了如何从 Puppeteer 迁移到 Playwright 库Playwright 测试。两者的 API 有相似之处,但 Playwright 为网页测试和跨浏览器自动化提供了更多可能性。

  • 大多数 Puppeteer API 可以直接使用
  • 不建议使用 ElementHandle,推荐使用 Locator 对象和面向网页的断言
  • Playwright 支持跨浏览器
  • 通常不需要显式等待

速查表

PuppeteerPlaywright 库
await puppeteer.launch()await playwright.chromium.launch()
puppeteer.launch({product: 'firefox'})await playwright.firefox.launch()
Puppeteer 不支持 WebKitawait playwright.webkit.launch()
await browser.createIncognitoBrowserContext(...)await browser.newContext(...)
await page.setViewport(...)await page.setViewportSize(...)
await page.waitForXPath(XPathSelector)await page.waitForSelector(XPathSelector)
await page.waitForNetworkIdle(...)await page.waitForLoadState('networkidle')
await page.$eval(...)通常可以使用断言替代来验证文本、属性、类等
await page.$(...)不推荐使用,改用定位器
await page.$x(xpath_selector)不推荐使用,改用定位器
没有专门针对复选框或单选按钮的方法await page.locator(selector).check()
await page.locator(selector).uncheck()
await page.click(selector)await page.locator(selector).click()
await page.focus(selector)await page.locator(selector).focus()
await page.hover(selector)await page.locator(selector).hover()
await page.select(selector, values)await page.locator(selector).selectOption(values)
await page.tap(selector)await page.locator(selector).tap()
await page.type(selector, ...)await page.locator(selector).fill(...)
await page.waitForFileChooser(...)
await elementHandle.uploadFile(...)
await page.locator(selector).setInputFiles(...)
await page.cookies([...urls])await browserContext.cookies([urls])
await page.deleteCookie(...cookies)await browserContext.clearCookies()
await page.setCookie(...cookies)await browserContext.addCookies(cookies)
page.on(...)page.on(...)
要拦截和修改请求,请参阅page.route()

page.waitForNavigationpage.waitForSelector 仍然存在,但由于自动等待功能,许多情况下不再需要。

不推荐使用 ElementHandle,改用[定位器]对象和面向Web的断言。

定位器是 Playwright 自动等待和重试能力的核心。定位器是严格的,这意味着如果给定选择器匹配到多个元素,所有涉及目标DOM元素的操作都会抛出异常。

示例

自动化示例

Puppeteer 版本:

const puppeteer = require('puppeteer');

(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({ width: 1280, height: 800 });
await page.goto('https://playwright.dev/', {
waitUntil: 'networkidle2',
});
await page.screenshot({ path: 'example.png' });
await browser.close();
})();

逐行迁移到 Playwright:

const { chromium } = require('playwright'); // 1

(async () => {
const browser = await chromium.launch();
const page = await browser.newPage(); // 2
await page.setViewportSize({ width: 1280, height: 800 }); // 3
await page.goto('https://playwright.dev/', {
waitUntil: 'networkidle', // 4
});
await page.screenshot({ path: 'example.png' });
await browser.close();
})();

迁移要点(参见 Playwright 代码片段中的内联注释):

  1. 每个 Playwright 库文件都需要显式导入 chromium。也可以使用其他浏览器 webkitfirefox
  2. 为了实现浏览器状态隔离,请考虑使用 浏览器上下文
  3. setViewport 改为 setViewportSize
  4. networkidle2 改为 networkidle。请注意在大多数情况下由于自动等待机制,这个参数并不实用

测试示例

使用 Jest 的 Puppeteer 示例:

import puppeteer from 'puppeteer';

describe('Playwright 首页', () => {
let browser;
let page;

beforeAll(async () => {
browser = await puppeteer.launch();
page = await browser.newPage();
});

it('包含主标题', async () => {
await page.goto('https://playwright.dev/');
await page.waitForSelector('.hero__title');
const text = await page.$eval('.hero__title', e => e.textContent);
expect(text).toContain('Playwright enables reliable end-to-end testing'); // 5
});

afterAll(() => browser.close());
});

逐行迁移到 Playwright Test:

import { test, expect } from '@playwright/test'; // 1

test.describe('Playwright 首页', () => {
test('包含主标题', async ({ page }) => { // 2, 3
await page.goto('https://playwright.dev/');
const titleLocator = page.locator('.hero__title'); // 4
await expect(titleLocator).toContainText( // 5
'Playwright enables reliable end-to-end testing'
);
});
});
  1. 每个 Playwright Test 文件都需要显式导入 testexpect 函数
  2. 测试函数标记为 async
  3. Playwright Test 接收 page 作为参数之一。这是 Playwright Test 中众多实用 fixture之一。Playwright Test 会为每个测试创建独立的 Page 对象。不过,如果你想在多个测试间复用同一个 Page 对象,可以在 test.beforeAll() 中创建并在 test.afterAll() 中关闭它。
  4. 使用 page.locator() 创建定位器是少数同步方法之一
  5. 使用断言来验证状态,而不是 page.$eval()

测试指南

为了提升测试质量,建议使用定位器(Locators)和面向Web的断言(Assertions)。详见编写测试

在Puppeteer中常见的使用方式是page.evaluate()page.$eval()来检查ElementHandle并提取文本内容、属性、类等值。面向Web的断言(Assertions)为此提供了多种匹配器,这种方式更加可靠且易读。

Playwright Test是我们官方推荐与Playwright配合使用的测试运行器。它提供了多种功能,如页面对象模型、并行测试、测试夹具和报告器等。

Playwright Test 的超强能力

一旦使用Playwright Test,你将获得以下优势:

  • 开箱即用的TypeScript支持
  • 可在所有主流操作系统(Windows、macOS、Ubuntu)上运行所有浏览器引擎(Chrome、Firefox、Safari)的测试
  • 全面支持多源站、(i)frames标签页和上下文
  • 支持多浏览器并行隔离运行测试
  • 内置测试结果收集

你还将获得这些✨强大的工具✨:

延伸阅读

了解更多关于Playwright测试运行器的信息: