Storybook Test Runner
Storybook 官方组件自动化测试运行器
Storybook Test Runner 是 Storybook 官方提供的测试运行器,基于 Playwright 在真实浏览器中自动执行 Story 的交互测试和可访问性检查,将组件文档与自动化测试打通,实现 Story 即测试用例的 workflow。
Storybook Test Runner 组件自动化测试技术调研
Storybook Test Runner 是 Storybook 官方提供的测试运行器,基于 Playwright 在真实浏览器中自动执行 Story 的交互测试(play 函数)和可访问性检查,将组件文档与自动化测试打通,实现「Story 即测试用例」的组件质量保障 workflow。
一、 基本信息
| 维度 | 关键指标 / 描述 |
|---|---|
| 技术标签 | 组件测试 / Storybook / Playwright / 交互测试 / a11y |
| 开发商 | Chromatic(Storybook 团队) |
| 官方网站 | https://storybook.js.org/docs/writing-tests/test-runner |
| npm 包 | @storybook/test-runner |
| 许可协议 | MIT License |
| 首次发布 | 2022 年 |
| 生态成熟度 | 中高(Storybook 测试体系核心组件) |
二、 技术定位与简介
Storybook Test Runner 的工作方式:
- 启动或连接已运行的 Storybook 实例。
- 使用 Playwright 访问每个 Story 的 iframe URL。
- 自动运行 Story 中定义的
play函数(@storybook/test交互步骤)。 - 可选运行 axe 可访问性检查。
- 输出 Jest 风格测试结果,可集成 CI。
它与 Vitest 组件测试、Chromatic 视觉回归 共同构成 Storybook 现代测试三角:交互 + 视觉 + 单元。
三、 快速上手安装说明
1. 安装
pnpm add -D @storybook/test-runner @storybook/test2. 配置 package.json
{
"scripts": {
"test-storybook": "test-storybook"
}
}3. Story 带 play 函数
import type { Meta, StoryObj } from '@storybook/react'
import { expect, userEvent, within } from '@storybook/test'
import { Button } from './Button'
const meta: Meta<typeof Button> = {
component: Button,
}
export default meta
type Story = StoryObj<typeof Button>
export const Click: Story = {
args: { label: 'Click me' },
play: async ({ canvasElement }) => {
const canvas = within(canvasElement)
await userEvent.click(canvas.getByRole('button'))
await expect(canvas.getByText('Clicked')).toBeInTheDocument()
},
}4. 运行
pnpm storybook & # 或先 build 静态 storybook
pnpm test-storybook5. test-runner-jest.config.js
const { getJestConfig } = require('@storybook/test-runner')
module.exports = {
...getJestConfig(),
/** 自定义 setup */
}四、 核心特性
1. 自动遍历 Stories
无需手写每个 Story 的测试文件。
2. play 函数执行
与 @storybook/addon-interactions 共享交互定义。
3. 可访问性测试
集成 @storybook/addon-a11y 与 axe 自动扫描。
4. Playwright 底层
真实浏览器环境,非 jsdom。
5. 并行执行
Jest worker 并行访问 Stories。
6. CI 友好
--ci、--maxWorkers 控制资源。
7. 标签过滤
--includeTags、--excludeTags 选择性运行。
8. 与 Chromatic 协同
视觉回归在 Chromatic 云,交互在 Test Runner 本地/CI。
五、 适用场景
1. 黄金适用场景
- 已采用 Storybook 的组件库/设计系统。
- 需要 Story 级交互回归(按钮、表单、对话框)。
- 组件 a11y 基线检查。
- 设计系统 CI 质量门禁。
play函数即活文档又即测试。
2. 局限适用场景
- 未使用 Storybook 的项目。
- 全应用 E2E 流程(用 Playwright/Cypress)。
- 纯逻辑单元测试(Vitest)。
- 按本项目规范:营销页、纯展示组件可不测。
六、 技术亮点
1. DRY 测试
交互逻辑只在 Story play 中写一次。
2. 真实浏览器
弥补 jsdom 组件测试盲点。
3. 与 Interactions 面板统一
开发时调试的 play 即 CI 执行的 play。
4. 零额外测试文件
减少 Story 与 Test 重复维护。
5. 官方维护
与 Storybook 版本同步演进。
七、 核心概念与架构
digraph SB_TestRunner {
rankdir=LR
node [shape=box, style="rounded,filled", fillcolor="#f0f9ff"]
Runner [label="test-storybook\n(Jest)", fillcolor="#bae6fd"]
Playwright [label="Playwright"]
SB [label="Storybook Server"]
Story [label="Story iframe\n+ play()"]
A11y [label="axe a11y"]
Runner -> Playwright
Playwright -> SB
SB -> Story
Runner -> A11y
Story -> A11y
}八、 技术局限与边界
- 依赖 Storybook:无 Storybook 则无用。
- 启动成本:需运行 Storybook 服务或静态构建。
- 速度:比纯 Vitest 慢。
- 覆盖范围:组件级,非页面级路由。
- 配置门槛:Monorepo、Vite、Next 需正确 Storybook 配置。
- flaky:异步 play 需良好等待实践。
九、 生态地图
| 组件 | 关系 |
|---|---|
| @storybook/test | play 内 expect/userEvent |
| addon-interactions | 开发时调试 play |
| addon-a11y | 可访问性规则 |
| Chromatic | 视觉回归云 |
| Vitest | storybook-addon-vitest 替代/补充 |
十、 生态集成
| 方向 | 说明 |
|---|---|
| Playwright | Test Runner 底层浏览器驱动。 |
| Jest | 测试结果与 worker 模型。 |
| CI | build storybook → test-storybook。 |
| Vitest | 新版可用 vitest 运行 story 测试。 |
| Chromatic | 视觉 + 交互分工。 |
十一、 开发与工程化
1. CI 流水线
- run: pnpm build-storybook
- run: pnpm test-storybook --ci --url file://$(pwd)/storybook-static2. 仅为交互 Story 写 play
展示型 Story 可跳过 play,Test Runner 仍可做 a11y smoke。
3. 与项目规范对齐
稳定业务组件写 play;营销展示组件可不纳入。
十二、 性能与安全
--maxWorkers控制 CI 并行度。- 静态 storybook 比 dev server 更稳定快速。
- Story 中勿使用生产 API 与真实密钥。
- MSW 在 Storybook preview 中 Mock API。
十三、 技术对比
| 方案 | 优势 | 局限 | 适合 |
|---|---|---|---|
| Test Runner | Story=测试、真实浏览器 | 需 Storybook | 设计系统 |
| Vitest CT | 快、与 Vite 集成 | 较新 | Vite 组件库 |
| Testing Library | 灵活 | 独立测试文件 | 应用组件 |
| Chromatic | 视觉回归 | 付费云 | UI 像素对比 |
十四、 最佳实践
- 每个交互组件至少一个带
play的 Story。 - 使用
@storybook/test的within(canvasElement)限定查询范围。 - CI 用静态
storybook-static而非 dev server。 - 启用 a11y addon,Test Runner 自动跑 axe。
- 与 Chromatic 分工:视觉云测,交互本地 CI。
- 异步 UI 用
await expect(...).toBeVisible()等待。 - 复杂 API 在 preview.ts 配置 MSW handlers。
- 用 tags 区分
test与skip-teststories。 - 不要为纯样式 Story 写无意义 play。
- 评估
storybook-addon-vitest是否与 Test Runner 重复。