Skip to main content

从 Testing Library 迁移

迁移原则

🌐 Migration principles

本指南介绍了如何从 DOM Testing LibraryReact Testing LibraryVue Testing Library 迁移到 Playwright 的 组件测试

🌐 This guide describes migration to Playwright's component testing from DOM Testing Library, React Testing Library and Vue Testing Library.

note

如果你在浏览器中使用 DOM Testing Library(例如,你使用 webpack 打包端到端测试),你可以直接切换到 Playwright Test。下面的示例主要针对组件测试,但对于端到端测试,你只需要将 await mount 替换为 await page.goto('http://localhost:3000/') 来打开被测页面。:::

🌐 If you use DOM Testing Library in the browser (for example, you bundle end-to-end tests with webpack), you can switch directly to Playwright Test. Examples below are focused on component tests, but for end-to-end test you just need to replace await mount with await page.goto('http://localhost:3000/') to open the page under test.

Playwright 通过一个 故事 来渲染组件——这是一个小型封装,将组件放在一个特定场景中——由你自己的开发服务器从 图库 页面提供。Testing Library 在测试中直接调用 render(),而 Playwright 则把这个设置放到故事里,并在测试中通过 id 引用它。关于如何设置图库,请参见 组件测试

🌐 Playwright renders a component through a story — a small wrapper that embeds the component in one specific scenario — served from a gallery page by your own dev server. Where Testing Library calls render() inline in the test, Playwright moves that setup into the story and refers to it by id from the test. See Component testing for how to set up the gallery.

备忘单

🌐 Cheat Sheet

测试库Playwright
屏幕页面组件
查询定位器
异步辅助断言
用户事件操作
await user.click(screen.getByText('Click me'))await component.getByText('Click me').click()
await user.click(await screen.findByText('Click me'))await component.getByText('Click me').click()
await user.type(screen.getByLabelText('Password'), 'secret')await component.getByLabel('Password').fill('secret')
expect(screen.getByLabelText('Password')).toHaveValue('secret')await expect(component.getByLabel('Password')).toHaveValue('secret')
screen.getByRole('button', { pressed: true })component.getByRole('button', { pressed: true })
screen.getByLabelText('...')component.getByLabel('...')
screen.queryByPlaceholderText('...')component.getByPlaceholder('...')
screen.findByText('...')component.getByText('...')
screen.getByTestId('...')component.getByTestId('...')
render(<Component />);一个故事导出 + await mount('Component/Default');
const { unmount } = render(<Component />);const component = await mount('...'); await component.unmount();
const { rerender } = render(<Component />);const component = await mount('...'); await component.update(props);

示例

🌐 Example

测试库:

🌐 Testing Library:

import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

test('sign in', async () => {
// Setup the page.
const user = userEvent.setup();
render(<SignInPage />);

// Perform actions.
await user.type(screen.getByLabelText('Username'), 'John');
await user.type(screen.getByLabelText('Password'), 'secret');
await user.click(screen.getByRole('button', { name: 'Sign in' }));

// Verify signed in state by waiting until "Welcome" message appears.
expect(await screen.findByText('Welcome, John')).toBeInTheDocument();
});

逐行迁移到 Playwright 测试。首先,将场景从测试移到组件旁边的故事中:

🌐 Line-by-line migration to Playwright Test. First, the scenario moves from the test into a story next to the component:

src/pages/SignInPage.story.tsx
import { SignInPage } from './SignInPage';

export const Default = () => <SignInPage />; // 1

然后测试通过 ID 挂载那个故事:

🌐 Then the test mounts that story by id:

const { test, expect } = require('@playwright/test'); // 2

test('sign in', async ({ mount }) => { // 3
// Setup the page.
const component = await mount('pages/SignInPage/Default'); // 4

// Perform actions.
await component.getByLabel('Username').fill('John'); // 5
await component.getByLabel('Password').fill('secret');
await component.getByRole('button', { name: 'Sign in' }).click();

// Verify signed in state by waiting until "Welcome" message appears.
await expect(component.getByText('Welcome, John')).toBeVisible(); // 6
});

迁移亮点(见 Playwright 测试代码片段中的内联评论):

🌐 Migration highlights (see inline comments in the Playwright Test code snippets):

  1. 无论 render() 用来设置的内联内容——props、providers、模拟数据——都会变成一个故事导出。故事在浏览器中运行,所以实时对象不再需要传到测试中。
  2. @playwright/test 导入所有内容,用于组件测试和端到端测试。
  3. 测试函数给出了一个 page,它与其他测试隔离,还有一个 mount,它在此页面上渲染一个故事。这是 Playwright 测试中两个有用的夹具
  4. render 替换为 fixtures.mount(),它接收一个故事 id 并返回一个作用于图库根元素的 组件定位器
  5. 使用通过 locator.locator()page.locator() 创建的定位器来执行大多数操作。
  6. 使用 断言 来验证状态。

迁移查询

🌐 Migrating queries

所有像 getBy...findBy...queryBy... 这样的查询及其多元素对应项都会被替换为 component.getBy... 定位器。定位器总是会在需要时自动等待和重试,因此你不必担心选择正确的方法。当你想执行list 操作,例如断言一组文本时,Playwright 会自动执行多元素操作。

🌐 All queries like getBy..., findBy..., queryBy... and their multi-element counterparts are replaced with component.getBy... locators. Locators always auto-wait and retry when needed, so you don't have to worry about choosing the right method. When you want to do a list operation, e.g. assert a list of texts, Playwright automatically performs multi-element operations.

替换 waitFor

🌐 Replacing waitFor

Playwright 包含能够自动等待条件的断言,因此你通常不需要显式调用 waitFor/waitForElementToBeRemoved

🌐 Playwright includes assertions that automatically wait for the condition, so you don't usually need an explicit waitFor/waitForElementToBeRemoved call.

// Testing Library
await waitFor(() => {
expect(getByText('the lion king')).toBeInTheDocument();
});
await waitForElementToBeRemoved(() => queryByText('the mummy'));

// Playwright
await expect(page.getByText('the lion king')).toBeVisible();
await expect(page.getByText('the mummy')).toBeHidden();

当你找不到合适的断言时,请改用 expect.poll

🌐 When you cannot find a suitable assertion, use expect.poll instead.

await expect.poll(async () => {
const response = await page.request.get('https://api.example.com');
return response.status();
}).toBe(200);

替换 within

🌐 Replacing within

你可以使用 locator.locator() 方法在另一个定位器内创建定位器。

🌐 You can create a locator inside another locator with locator.locator() method.

// Testing Library
const messages = screen.getByTestId('messages');
const helloMessage = within(messages).getByText('hello');

// Playwright
const messages = component.getByTestId('messages');
const helloMessage = messages.getByText('hello');

Playwright 测试超能力

🌐 Playwright Test Super Powers

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

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

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

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

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

进一步阅读

🌐 Further Reading

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

🌐 Learn more about Playwright Test runner: