Skip to main content

从 Puppeteer 迁移

迁移原则

¥Migration Principles

本指南介绍从 Puppeteer 迁移到 Playwright 库Playwright 测试。这些 API 有相似之处,但 Playwright 为 Web 测试和跨浏览器自动化提供了更多可能性。

¥This guide describes migration to Playwright Library and Playwright Test from Puppeteer. The APIs have similarities, but Playwright offers much more possibilities for web testing and cross-browser automation.

  • 大多数 Puppeteer API 都可以按原样使用

    ¥Most Puppeteer APIs can be used as is

  • 不鼓励使用 ElementHandle,而是使用 Locator 对象和 Web 优先断言。

    ¥The use of ElementHandle is discouraged, use Locator objects and web-first assertions instead.

  • Playwriter 是跨浏览器的

    ¥Playwright is cross-browser

  • 你可能不需要显式等待

    ¥You probably don't need explicit wait

备忘单

¥Cheat Sheet

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 保留,但在许多情况下由于 auto-waiting 而不再需要。

¥page.waitForNavigation and page.waitForSelector remain, but in many cases will not be necessary due to auto-waiting.

不鼓励使用 ElementHandle,而是使用 Locator 对象和 Web 优先断言。

¥The use of ElementHandle is discouraged, use Locator objects and web-first assertions instead.

定位器是 Playwright 自动等待和重试能力的核心部分。定位器是严格的。这意味着如果多个元素与给定选择器匹配,则对暗示某个目标 DOM 元素的定位器的所有操作都将引发异常。

¥Locators are the central piece of Playwright's auto-waiting and retry-ability. Locators are strict. This means that all operations on locators that imply some target DOM element will throw an exception if more than one element matches a given selector.

示例

¥Examples

自动化示例

¥Automation example

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.nodejs.cn/', {
waitUntil: 'networkidle2',
});
await page.screenshot({ path: 'example.png' });
await browser.close();
})();

逐行迁移到 Playwright:

¥Line-by-line migration to 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.nodejs.cn/', {
waitUntil: 'networkidle', // 4
});
await page.screenshot({ path: 'example.png' });
await browser.close();
})();

迁移亮点(请参阅 Playwright 代码片段中的内联注释):

¥Migration highlights (see inline comments in the Playwright code snippet):

  1. 每个 Playwright 库文件都有 chromium 的显式导入。可以使用其他浏览器 webkitfirefox

    ¥Each Playwright Library file has explicit import of chromium. Other browsers webkit or firefox can be used.

  2. 对于浏览器状态隔离,请考虑 浏览器上下文

    ¥For browser state isolation, consider browser contexts

  3. setViewport 变成 setViewportSize

    ¥setViewport becomes setViewportSize

  4. networkidle2 变成 networkidle。请注意,在大多数情况下,由于自动等待,它没有用。

    ¥networkidle2 becomes networkidle. Please note that in most cases it is not useful, thanks to auto-waiting.

测试示例

¥Test example

使用 Jest 的 Puppeteer:

¥Puppeteer with Jest:

import puppeteer from 'puppeteer';

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

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

it('contains hero title', async () => {
await page.goto('https://playwright.nodejs.cn/');
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 测试:

¥Line-by-line migration to Playwright Test:

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

test.describe('Playwright homepage', () => {
test('contains hero title', async ({ page }) => { // 2, 3
await page.goto('https://playwright.nodejs.cn/');
const titleLocator = page.locator('.hero__title'); // 4
await expect(titleLocator).toContainText( // 5
'Playwright enables reliable end-to-end testing'
);
});
});
  1. 每个 Playwright 测试文件都显式导入 testexpect 函数

    ¥Each Playwright Test file has explicit import of the test and expect functions

  2. 测试功能标有 async

    ¥Test function is marked with async

  3. Playwright 测试被赋予 page 作为其参数之一。这是 Playwright 测试中众多 有用的夹具 之一。Playwright Test 为每个测试创建一个独立的 Page 对象。但是,如果你想在多个测试之间重用单个 Page 对象,你可以在 test.beforeAll() 中创建自己的对象并在 test.afterAll() 中关闭它。

    ¥Playwright Test is given a page as one of its parameters. This is one of the many useful fixtures in Playwright Test. Playwright Test creates an isolated Page object for each test. However, if you'd like to reuse a single Page object between multiple tests, you can create your own in test.beforeAll() and close it in test.afterAll().

  4. 使用 page.locator() 创建定位器是少数同步方法之一。

    ¥Locator creation with page.locator() is one of the few methods that is sync.

  5. 使用 assertions 而不是 page.$eval() 来验证状态。

    ¥Use assertions to verify the state instead of page.$eval().

测试

¥Testing

为了改进测试,建议使用 定位器 和 Web 优先 断言。见 编写测试

¥To improve testing, it is advised to use Locators and web-first Assertions. See Writing Tests

Puppeteer 常见的是使用 page.evaluate()page.$eval() 来检查 ElementHandle 并提取文本内容、属性、类的值...Web-first 断言 为此提供了多个匹配器,它更加可靠和可读。

¥It is common with Puppeteer to use page.evaluate() or page.$eval() to inspect an ElementHandle and extract the value of text content, attribute, class... Web-first Assertions offers several matchers for this purpose, it is more reliable and readable.

Playwright 测试 是我们推荐与 Playwright 一起使用的第一方测试运行器。它提供了多种功能,如页面对象模型、并行性、夹具或报告器。

¥Playwright Test is our first-party recommended test runner to be used with Playwright. It provides several features like Page Object Model, parallelism, fixtures or reporters.

Playwright 测试超能力

¥Playwright Test Super Powers

一旦参加 Playwright 测试,你就会收获很多!

¥Once you're on Playwright Test, you get a lot!

  • 完全零配置 TypeScript 支持

    ¥Full zero-configuration TypeScript support

  • 在任何流行操作系统(Windows、macOS、Ubuntu)上跨所有 Web 引擎(Chrome、Firefox、Safari)运行测试

    ¥Run tests across all web engines (Chrome, Firefox, Safari) on any popular operating system (Windows, macOS, Ubuntu)

  • 全面支持多来源、(i)frames选项卡和上下文

    ¥Full support for multiple origins, (i)frames, tabs and contexts

  • 跨多个浏览器并行运行隔离测试

    ¥Run tests in isolation in parallel across multiple browsers

  • 内置测试 制品集合

    ¥Built-in test artifact collection

你还可以获得所有这些 ✨ 很棒的工具 ✨ 与 Playwright 测试打包在一起:

¥You also get all these ✨ awesome tools ✨ that come bundled with Playwright Test:

进一步阅读

¥Further Reading

了解有关 Playwright 测试运行程序的更多信息:

¥Learn more about Playwright Test runner: