跳到主要内容

从 Puppeteer 迁移

迁移原则

本指南描述了从 Puppeteer 迁移到 Playwright LibraryPlaywright 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()
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.$(...)不建议使用,请使用 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).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 而变得不必要。

不建议使用 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('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。请注意,在大多数情况下,由于 auto-waiting,它不是很有用。

测试示例

Puppeteer 与 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.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 中许多有用的 fixtures 之一。Playwright Test 为每个测试创建一个隔离的 Page 对象。但是,如果您想在多个测试之间重用单个 Page 对象,您可以在 test.beforeAll() 中创建自己的对象,并在 test.afterAll() 中关闭它。
  4. 使用 page.locator() 创建 Locator 是少数几个同步方法之一。
  5. 使用断言来验证状态而不是 page.$eval()

测试

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

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

Playwright Test 是我们首推的与 Playwright 一起使用的测试运行器。它提供了几个功能,如 Page Object Model、并行、fixtures 或报告器。

Playwright Test 超能力

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

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

你还可以获得所有这些与 Playwright Test 捆绑在一起的 ✨ 强大的工具 ✨

进一步阅读

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