跳至主要内容

从 Puppeteer 迁移

迁移原则

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

  • 大多数 Puppeteer API 可以照常使用
  • 不建议使用 ElementHandle,而应使用 Locator 对象和 Web优先断言。
  • Playwright 是跨浏览器的
  • 你可能不需要显式等待

备忘单

PuppeteerPlaywright 库
await puppeteer.launch()await playwright.chromium.launch()
puppeteer.launch({product: 'firefox'})await playwright.firefox.launch()
WebKit 不受 Puppeteer 支持await 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,而应使用 Locator 对象和 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.net.cn/', {
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.net.cn/', {
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 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.net.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 测试

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

test.describe('Playwright homepage', () => {
test('contains hero title', async ({ page }) => { // 2, 3
await page.goto('https://playwright.net.cn/');
const titleLocator = page.locator('.hero__title'); // 4
await expect(titleLocator).toContainText( // 5
'Playwright enables reliable end-to-end testing'
);
});
});
  1. 每个 Playwright 测试文件都显式导入 testexpect 函数
  2. 测试函数用 async 标记
  3. Playwright 测试提供了一个 page 作为其参数之一。这是 Playwright 测试中众多 有用夹具 之一。Playwright 测试为每个测试创建了一个隔离的 Page 对象。但是,如果要在多个测试之间重用一个 Page 对象,可以在 test.beforeAll() 中创建它,并在 test.afterAll() 中关闭它。
  4. 使用 page.locator() 创建定位器是同步方法中为数不多的几种方法之一。
  5. 使用 断言 来验证状态,而不是 page.$eval()

测试

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

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

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

Playwright 测试的超级力量

使用 Playwright 测试后,你会获得很多好处!

  • 完整的零配置 TypeScript 支持
  • 在所有 Web 引擎(Chrome、Firefox、Safari)上,在任何流行的操作系统(Windows、macOS、Ubuntu)上运行测试
  • 完全支持多个来源、(i)框架标签和上下文
  • 在多个浏览器中以并行方式隔离运行测试
  • 内置测试 工件收集

你还会获得与 Playwright 测试捆绑在一起的所有这些 ✨ 很棒的工具 ✨

进一步阅读

详细了解 Playwright 测试运行器