跳转到主要内容

从 Puppeteer 迁移

迁移原则

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

  • 大多数 Puppeteer API 可以照常使用
  • 不鼓励使用 ElementHandle,请改用 Locator 对象和 web-first 断言。
  • 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,请改用 Locator 对象和 web-first 断言。

定位器是 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 Library 文件都显式导入 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 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.net.cn/');
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 中众多有用的夹具之一。Playwright Test 为每个测试创建一个隔离的 Page 对象。但是,如果您想在多个测试之间重用一个 Page 对象,您可以在 test.beforeAll() 中创建它并在 test.afterAll() 中关闭它。
  4. 使用 page.locator() 创建定位器是少数同步方法之一。
  5. 使用 断言 来验证状态,而不是 page.$eval()

测试

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

使用 Puppeteer 检查 ElementHandle 并提取文本内容、属性、类等的值通常使用 page.evaluate()page.$eval()。Web 优先 断言 为此提供了几种匹配器,它更可靠和可读。

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

Playwright Test 超能力

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

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

您还将获得所有这些随 Playwright Test 捆绑的 ✨ 强大工具 ✨

进一步阅读

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