Skip to main content

从 Puppeteer 迁移

迁移原则​

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

  • 大多数 Puppeteer API 可以按原样使用
  • 不鼓励使用 ElementHandle,请改用 Locator 对象和 web-first 断言。
  • Playwright 是跨浏览器的
  • 您可能不需要显式等待

备忘单​

PuppeteerPlaywright Library
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.$(...)不鼓励,请改用 Locators
await page.$x(xpath_selector)不鼓励,请改用 Locators
没有专门用于复选框或单选输入的的方法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).type(...)
请也考虑 locator.fill(value[, options])
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(url, handler[, options])

page.waitForNavigation 和 page.waitForSelector 仍然存在,但在许多情况下,由于 自动等待,它们将不再需要。

不鼓励使用 ElementHandle,请改用 Locator 对象和 web-first 断言。

Locators 是 Playwright 自动等待和重试能力的核心部分。Locators 是严格的。这意味着如果多个元素匹配给定的选择器,则暗示某个目标 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('http://whatsmyuseragent.org/', {
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('http://whatsmyuseragent.org/', {
waitUntil: 'networkidle', // 4
});
await page.screenshot({ path: 'example.png' });
await browser.close();
})();

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

  1. 每个 Playwright Library 文件都有 chromium 的显式导入。可以使用其他浏览器 webkit 或 firefox。
  2. 为了浏览器状态隔离,请考虑 浏览器上下文
  3. setViewport 变为 setViewportSize
  4. networkidle2 变为 networkidle。请注意,在大多数情况下,由于自动等待,它并不常用。

测试示例​

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.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 homepage', () => {
test('contains hero title', 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 文件都有 test 和 expect 函数的显式导入
  2. 测试函数标记为 async
  3. Playwright Test 被赋予一个 page 作为其参数之一。这是 Playwright Test 中众多 有用的 fixtures 之一。Playwright Test 为每个测试创建一个隔离的 Page 对象。但是,如果您想在多个测试之间重用单个 Page 对象,您可以在 test.beforeAll(hookFunction) 中创建自己的对象,并在 test.afterAll(hookFunction) 中关闭它。
  4. 使用 page.locator(selector[, options]) 创建定位器是为数不多的同步方法之一。
  5. 使用 断言 来验证状态,而不是 page.$eval()。

测试​

只需几行代码,您就可以将 Playwright 连接到现有的 JavaScript 测试运行器。

为了改进测试,建议使用 Locators 和 web-first 断言。请参阅 编写测试

在 Puppeteer 中,通常使用 page.evaluate() 或 page.$eval() 来检查 ElementHandle 并提取文本内容、属性、类的值... Web-first 断言 为此目的提供了几个匹配器,它更可靠且更易读。

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

Playwright Test 超能力​

一旦您使用 Playwright Test,您将获得很多!

  • 完全零配置的 TypeScript 支持
  • 在 任何流行的操作系统(Windows、macOS、Ubuntu)上的 所有 Web 引擎(Chrome、Firefox、Safari)上运行测试
  • 完全支持多个来源、(i)frames、选项卡和上下文
  • 在多个浏览器中并行隔离运行测试
  • 内置测试工件收集:视频录制、截图 和 playwright 跟踪

您还可以获得所有这些与 Playwright Test 捆绑在一起的 ✨ 很棒的工具 ✨:

进一步阅读​

了解有关 Playwright Test 运行器的更多信息: