返回博客

适用于 Playwright 组件测试的便携式故事/示例

通过最少的设置在 Playwright CT 中测试你的故事/示例。

loading
Yann Braga
@yannbf
最后更新

Storybook 是构建、文档化和测试 UI 组件的行业标准工作坊。它被 Shopify、Gov.UK 和 NASA 等组织的领先开发团队使用。

在 Storybook 中开发的最大好处之一是你可以免费获得测试。每个独立的组件示例——或者说“story”——都是一个 UI 测试。如果你想测试数据获取和用户交互,Storybook 也提供了相应的工具!

为了将你的 stories 作为测试执行,Storybook 包含一个基于 Playwright 的 测试运行器。虽然成千上万的团队很高兴地使用它来功能性测试他们的组件,但也有其他团队希望在其他测试工具和环境中重用他们的 stories,例如 Playwright CT(组件测试)。

这就是为什么我很兴奋地宣布一个新的实验性便携式 Stories API

  • ✍️ 使用组件故事格式(CSF)编写 stories,专为组件开发量身定制
  • 🧪 在 Playwright CT 中测试这些 stories,重用 props/样式/组件设置
  • 🥳 在 Storybook 8.1 中可用,支持 React 18+ 和 Vue 3

继续阅读,了解如何在你的项目中使用便携式 stories 和 Playwright CT。

便携式 stories

要在隔离的环境(应用之外)中渲染一个组件,你需要为其提供必要的上下文,包括 props、providers、wrappers 和 mocks。这对在 Vitest、Cypress CT 和 Playwright CT 等工具中测试组件来说是一个挑战。

Storybook 创建了一种在隔离环境中开发 UI 组件的格式,该格式经过优化,可用于提供这些输入。组件故事格式(CSF)是快速编目组件所有关键变体的最佳方式。

Illustration showing the code for each story and their visual representation.
每个命名导出都是一个 story,它捕获了渲染组件所需的所有上下文。

便携式 stories 是一个 API,它将 story 上下文转换为一个可正确渲染的组件。例如,一个 React story 变成一个 React 组件,一个 Vue story 变成一个 Vue 组件,依此类推。

import { composeStories } from '@storybook/react'  // or @storybook/vue3
import * as stories from './RestaurantCard.stories'

// Each of these components can be rendered in other environments
const { Default, New, Closed, Loading } = composeStories(stories)

这很有用,因为你可以在任何使用组件的工具中重用所有这些设置(props、样式、路由等)。在组件测试的情况下,这通常可以取代“arrange / act / assert”中的“arrange”步骤。

Storybook 交互测试 vs Playwright CT

Storybook 通过 play function 及其自己的基于 Playwright 的 test-runner 提供内置测试功能。这使你能够验证组件如何响应用户交互,例如点击、输入和鼠标输入。这是我们推荐的组件测试技术栈。

然而,你可能考虑使用 Playwright CT 的原因有很多。它速度快,拥有出色的 VSCode 集成,以及 测试生成器trace viewer 等其他酷炫功能。

Storybook 社区大家好,我们刚刚推出了 可视化测试附加组件,可以自动测试 stories 在多个浏览器和视口中的表现。这是最快、最安全的方法来找出像素级的 bug。

Playwright CT for Storybook 用户

如果你是 Storybook 用户但更喜欢使用 Playwright CT,我们希望让你的体验尽可能无缝。从 Storybook 8.1 开始,现在可以在 Playwright CT 中重用你的 React 和 Vue3 Storybook stories。这需要三个步骤

1 - 导入全局注解

在 Storybook 中,你在 .storybook/preview.ts 文件中导入全局样式并定义全局注解(argsdecorators 等)。Playwright CT 在 playwright/index.tsx 下有类似的概念。

第一步是使用 Storybook 的 setProjectAnnotations API 作为你的 Playwright 设置文件的一部分。这将确保你的便携式 stories 也将全局配置考虑在内。

// playwright/index.tsx
import { setProjectAnnotations } from '@storybook/react' // or @storybook/vue3
import previewAnnotations from '../.storybook/preview'

setProjectAnnotations(previewAnnotations)

2 - 创建一个便携式 stories 文件

Playwright CT 期望一个 “测试 story” 文件用于测试。对于你想要测试的每个组件,在其 stories 文件旁边创建一个新的 *.stories.portable.ts 文件。该文件将使用便携式 stories 的 composeStories API,该 API 会将文件中的每个 story 转换为一个便携式组件

// RestaurantDetailPage.stories.portable.ts
import { composeStories } from '@storybook/react'

import * as stories from './RestaurantDetailPage.stories'

// Output an object that maps 1:1 to your stories, now in portable components
export default composeStories(stories)
💡
注意:目前,由于 Playwright CT 复杂的 Node-to-Browser 架构,你不能在测试文件本身中使用 composeStories API,这样做会更简单。Playwright 团队正在积极改进他们的工具,所以希望将来这会变得不必要。

3 - 将便携式 stories 实验性 API 用于 Playwright CT

在你的测试文件中,从刚刚创建的文件中导入便携式 stories,并使用 Storybook 的 createTest API,它扩展了 Playwright 的基础 test API。挂载一个 story 后,它的所有 decoratorsloadersplay function 都将正确执行。

// RestaurantDetailPage.spec.tsx
// For Vue3, import from '@storybook/vue3/experimental-playwright'
import { createTest } from '@storybook/react/experimental-playwright'
// For Vue3, import from '@playwright/experimental-ct-vue'
import { test as base, expect } from '@playwright/experimental-ct-react'

import stories from './RestaurantDetailPage.stories.portable'

const test = createTest(base)

test('Default', async ({ mount }) => {
  // The mount function will execute all the necessary steps in the story,
  // such as loaders, render, and play function
  await mount(<stories.Default />)
})

test('WithItemsInTheCart', async ({ mount, page }) => {
  await mount(<stories.Success />)
  await page.getByLabel('menu item').first().click()
  await page.getByLabel('increase quantity by one').click()
  await page.getByLabel('confirm').click()
  await expect(page.getByLabel('food cart')).toContainText('€25.50')
})

就是这样!现在,无论你何时对你的 stories 进行更改,这些更改也将自动成为你的 Playwright 测试的一部分。

这是 Mealdrop 中的一个例子,其中一个复杂页面(样式、状态管理、路由、数据获取等)的 stories 在 Playwright CT 中被重用。这个例子展示了 Playwright 的 VSCode 扩展及其测试生成器

0:00
/0:26

Storybook for Playwright CT 用户

Storybook 也可以补充你现有的 Playwright CT 测试,这将为你的测试套件带来超能力

  1. 隔离的开发环境:Storybook 提供了一个类似沙盒的环境,你可以在其中独立于应用程序的其余部分构建和测试 UI 组件。它提供了便于为你的组件编写新变体(stories)的功能,从而更容易提高测试覆盖率。
  2. 移交和协作:Storybook 生成一个静态应用,可以部署和托管在任何地方,允许团队成员在不部署整个应用的情况下查看和讨论修改。这有助于开发者与设计师或利益相关者之间的协作。
  3. 文档和组件目录:Storybook 自动生成一个你的 UI 组件的活文档。因此,你的团队拥有一个单一的真相来源,确保每个人都理解可用的组件以及应如何使用它们。
  4. 丰富的附加组件生态系统:Storybook 支持广泛的集成和附加组件,可增强其功能,从可访问性测试到设计工具集成,使其成为满足各种开发需求的便捷工具。
  5. 可视化回归测试:Storybook 提供了一个 可视化测试附加组件,可确保你的 UI 在发布到生产环境之前在不同设备和浏览器上看起来符合预期。

哪种方法适合我?

Playwright CT 是一个用于在隔离环境中进行浏览器组件测试的强大工具。Storybook 自己的测试运行器、Cypress CT 和 Vitest 也是如此。

在未来的文章中,我们将更批判性地审视这些选项,并分享我们对组件测试最佳实践的看法。与此同时,这些工具不仅各有优缺点,而且它们也是不断发展的目标。今天最好的选择明天很容易被另一种选项所超越。

便携式 stories 通过使你能够将隔离的组件带到最适合你的项目和个人偏好的地方,从而避免了工具锁定。我们鼓励你试一试,将其作为简化和未来化组件开发和测试的一种方式。

立即试用

适用于 Playwright CT 的便携式 stories 在 Storybook 8.1 中可用。在新项目中尝试

npx storybook@latest init

或升级现有项目

npx storybook@latest upgrade

你可以按照文档了解更多入门细节和完整的 API。

未来展望

目前我们在 Playwright CT 中实验性地支持 React 18+ 和 Vue3,但计划后续支持更多渲染器和集成。我们也希望与 Playwright 团队合作,在未来版本中使便携式 stories 更易于设置。

加入 Storybook 邮件列表

获取最新新闻、更新和发布信息

7,180开发者及以上

我们正在招聘!

加入 Storybook 和 Chromatic 背后的团队。构建被数十万开发者在生产中使用的工具。远程优先。

查看职位

热门文章

Storybook 8.1

更高效、更有条理、更可预测的 Storybook
loading
Michael Shilman

Storybook 中的类型安全模块模拟

一种新的、基于标准的模拟方法
loading
Jeppe Reinhold

Storybook 8

下一个级别的测试、性能和兼容性
loading
Michael Shilman
加入社区
7,180开发者及以上
为什么为什么选择 Storybook组件驱动的 UI
文档指南教程更新日志遥测
社区附加组件参与贡献博客
案例展示探索项目组件词汇表
开源软件
Storybook - Storybook 中文

特别感谢 Netlify CircleCI