返回博客

用于 Playwright 组件测试的可移植 Story

在 Playwright CT 中测试您的 story,只需最少的设置。

loading
Yann Braga
@yannbf
最后更新

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

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

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

这就是为什么我很高兴宣布推出新的实验性 Portable Stories API

  • ✍️ 以组件 Story Format (CSF) 编写 story,专为组件开发量身定制
  • 🧪 在 Playwright CT 中测试这些 story,重用 props/样式/组件设置
  • 🥳 在 Storybook 8.1 中为 React 18+ 和 Vue 3 提供

请继续阅读,详细了解如何在您的项目中使用带有 Playwright CT 的可移植 story。

可移植 story

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

Storybook 创建了一种用于隔离开发 UI 组件的格式,该格式针对提供这些输入进行了优化。组件 Story Format (CSF) 是快速编目组件所有关键变体的最佳方式。

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

可移植 story 是一个 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 社区大家好,我们刚刚发布了 Visual Tests addon,用于跨多个浏览器和视口自动测试 story。这是以最快、最安全的方式查找像素级错误的方法。

面向 Storybook 用户的 Playwright CT

如果您是喜欢使用 Playwright CT 的 Storybook 用户,我们希望使您的体验尽可能无缝。从 Storybook 8.1 开始,现在可以在 Playwright CT 中重用您的 React 和 Vue3 Storybook story。这样做分为三个步骤

1 - 导入全局注解

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

第一步是使用 Storybook 中的 setProjectAnnotations API 作为 Playwright 设置文件的一部分。这将确保您的可移植 story 也将全局配置考虑在内。

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

setProjectAnnotations(previewAnnotations)

2 - 创建可移植 story 文件

Playwright CT 期望使用 “test story” 文件进行测试。对于您要测试的每个组件,在其 story 文件旁边创建一个新的 *.stories.portable.ts 文件。此文件将使用可移植 story composeStories 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 - 将可移植 story 实验性 API 用于 Playwright CT

在您的测试文件中,从刚刚创建的文件中导入可移植 story,并使用 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')
})

就是这样!现在,每当您更改 story 时,这些更改也会自动成为 Playwright 测试的一部分。

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

0:00
/0:26

面向 Playwright CT 用户的 Storybook

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

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

什么最适合我?

Playwright CT 是一个用于在隔离状态下浏览器测试组件的出色工具。Storybook 自己的 Test Runner、Cypress CT 和 Vitest 也是如此。

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

可移植 story 通过使您可以将隔离的组件带到对您的项目和个人偏好最有意义的任何地方,从而避免了工具锁定。我们鼓励您尝试一下,作为简化和面向未来的组件开发和测试的一种方式。

立即试用

用于 Playwright CT 的可移植 story 在 Storybook 8.1 中可用。在新项目中试用

npx storybook@latest init

或升级现有项目

npx storybook@latest upgrade

您可以按照文档了解有关入门和完整 API 的更多详细信息。

下一步是什么

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

加入 Storybook 邮件列表

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

6,730位开发者以及更多

我们正在招聘!

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

查看职位

热门文章

Storybook 8.1

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

Storybook 中类型安全的模块模拟

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

Storybook 8

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

特别感谢 Netlify CircleCI