首页
/ Storybook Test Runner 本地构建 CI 工作流实战:在 GitHub Actions 中构建、服务并运行组件测试

Storybook Test Runner 本地构建 CI 工作流实战:在 GitHub Actions 中构建、服务并运行组件测试

2026-09-09 17:07:42作者:劳婵绚Shirley

Storybook Test Runner 能够把项目中的每一个 Story 转化为可执行的测试:对于没有 play function 的 Story,它验证组件能否无错误渲染;对于带有 play function 的 Story,它还会执行交互并校验断言结果。本文聚焦官方文档提供的“本地构建工作流”——在 CI(以 GitHub Actions 为例)中先构建 Storybook 静态产物,再用静态服务器托管,最后对构建产物运行 Test Runner。读完本文,你将掌握这套工作流的完整 YAML 配置、每个步骤的底层原理,以及它与“针对已部署 Storybook 测试”方案的取舍。

为什么需要“本地构建”式的工作流

Storybook 的 Test Runner 是一个独立于 Storybook 框架运行的测试工具,它需要在测试执行时访问一个正在运行的 Storybook 实例——无论是本地开发服务器,还是已经部署到公网的静态站点。官方文档明确指出:Test Runner 要求本地运行中的 Storybook 或已发布的 Storybook 才能执行全部已有测试。

在 CI 环境中,最常见的两种接入方式:

  1. 针对已部署的 Storybook 测试:依赖 Vercel、Netlify 等平台触发 GitHub Actions 的 deployment_status 事件,将部署 URL 通过 TARGET_URL 环境变量传给 Test Runner;
  2. 针对本地构建产物测试(本文主题):不依赖任何部署平台,在 CI 内完成 build-storybook 构建 → http-server 静态服务 → wait-on 端口探测 → test-storybook 执行测试的全流程。

第二种方式尤其适合以下场景:Storybook 需要认证才能访问、团队希望测试与部署解耦,或者 CI 中根本没有接部署平台。官方文档也建议:当已发布的 Storybook 需要认证时,优先采用“非部署式”的本地构建方案。

核心工作流:完整配置与逐行解析

官方在 test-runner-local-build-workflow.md 中给出了推荐配方,该片段被主文档 test-runner.mdx 引用。它将构建、服务、测试三个环节用 concurrently 组织在一个任务中,通过 -k 保证测试结束(成功或失败)后自动终止静态服务器,避免 CI 任务悬挂。完整配置如下:

name: 'Storybook Tests'

on: push

jobs:
  test:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version-file: '.nvmrc'
      - name: Install dependencies
        run: yarn
      - name: Install Playwright
        run: npx playwright install --with-deps
      - name: Build Storybook
        run: yarn build-storybook --quiet
      - name: Serve Storybook and run tests
        run: |
          npx concurrently -k -s first -n "SB,TEST" -c "magenta,blue" \
            "npx http-server storybook-static --port 6006 --silent" \
            "npx wait-on tcp:127.0.0.1:6006 && yarn test-storybook"

触发器与任务级配置

  • on: push:任意分支的推送都会触发测试。如果希望只在主分支或 pull request 上运行,可以替换为 on: [push, pull_request] 或配合 branches 限定范围。
  • timeout-minutes: 60:整个 Job 的硬性超时时间。首次构建依赖、下载 Playwright 浏览器二进制、构建 Storybook 并跑完测试通常需要数分钟到十几分钟,60 分钟是文档提供的安全默认值;若项目 Storybook 较大或 Story 数量多,可适当调大。
  • runs-on: ubuntu-latest:Test Runner 底层基于 Playwright,需要 Linux 环境来运行浏览器;其他 CI 供应商(GitLab Pipelines、CircleCI 等)可以参照 Playwright 的 CI 文档选择基础镜像。

环境准备步骤

  • actions/checkout@v4:拉取仓库代码。
  • actions/setup-node@v4 + node-version-file: '.nvmrc':从仓库根目录的 .nvmrc 文件读取 Node.js 版本。如果你的项目没有 .nvmrc,可以改用 node-version: '20' 这类写法。
  • yarn:安装依赖。官方文档给出的配方默认使用 Yarn,实际项目中完全可以用 npm cipnpm install --frozen-lockfile 替代,保持与本地开发一致的包管理器即可。
  • npx playwright install --with-deps:安装 Playwright 浏览器二进制及系统级依赖。--with-deps 会在 ubuntu 镜像中额外安装浏览器运行所需的系统库,这是 CI 上避免“浏览器启动失败”的关键一步。

构建 Storybook 静态产物

yarn build-storybook --quiet
  • build-storybook 对应 @storybook/cli 提供的构建命令,将项目构建为纯静态 Web 应用。
  • --quiet 减少构建日志输出,避免 CI 日志过长。
  • 官方文档特别提醒:默认情况下 Storybook 将构建产物输出到 storybook-static 目录。如果项目通过 main.js/main.ts 中的配置改动了输出目录(例如自定义 outputDir),必须同步调整下方 http-server 的静态目录参数。仓库内 test-storybooks/mcp/package.json 中即可看到真实的脚本示例:"build-storybook": "storybook build",其配套的 MCP 测试(tests/mcp-endpoint.e2e.test.ts)同样遵循“构建 → 服务 → 测试”的模式。

并行服务与测试:concurrently + http-server + wait-on

npx concurrently -k -s first -n "SB,TEST" -c "magenta,blue" \
  "npx http-server storybook-static --port 6006 --silent" \
  "npx wait-on tcp:127.0.0.1:6006 && yarn test-storybook"

这是整套工作流中最核心也最容易出问题的一行,三个第三方工具各司其职:

工具 作用 关键参数说明
concurrently 同时启动多个命令,并统一转发输出 -k(kill others):任一命令退出时终止其余命令;-s first(success first):以第一个成功退出的命令的结果作为整体退出码;-n "SB,TEST" 为两个命令命名;-c "magenta,blue" 设置前缀颜色便于区分日志
http-server 零配置静态文件服务器 storybook-static 为构建产物目录;--port 6006 与 Test Runner 默认期望的本地端口一致;--silent 抑制请求日志
wait-on 轮询等待某个资源就绪 tcp:127.0.0.1:6006 表示等待本机 6006 端口可连接,避免测试命令在服务器尚未监听时抢先执行而失败

整条链路的执行语义是:concurrently 同时拉起“静态服务器”与“等待端口 + 运行测试”两条命令;wait-on 探测到 6006 端口可访问后,test-storybook 才开始运行;测试跑完(无论通过与否),-k 会立刻杀掉仍在监听的 http-server,配合 -s first 将测试的退出码传递给 CI,从而让 GitHub Actions 正确标记构建的成败状态。

关于端口,Test Runner 默认假设本地 Storybook 运行在 6006 端口,所以配方中 http-server 显式指定 --port 6006 正是为了与默认行为对齐;若你通过 --url 指定了其他端口,这里也需保持一致。

前置配置:安装与本地脚本

在把工作流搬上 CI 之前,需要先在项目中完成 Test Runner 的安装与脚本配置(详见 test-runner.mdx):

# npm
npm install @storybook/test-runner --save-dev
# 或 pnpm
pnpm add --save-dev @storybook/test-runner
# 或 yarn
yarn add --dev @storybook/test-runner

package.json 中注册脚本:

{
  "scripts": {
    "test-storybook": "test-storybook"
  }
}

本地开发时,先启动 Storybook 开发服务器(默认 6006 端口),再开一个新终端执行 yarn test-storybook(或 npm run test-storybook / pnpm run test-storybook)即可运行测试。这套本地流程与 CI 工作流是同一套测试逻辑,CI 中只是把“开发服务器”替换成了“构建产物 + http-server”。

备选方案:针对已部署 Storybook 的 deployment_status 工作流

官方文档在“Run against deployed Storybooks”一节给出了另一份配方(test-runner-with-deploy-event-workflow.md),与本地构建方案形成互补:

name: Storybook Tests

on: deployment_status

jobs:
  test:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    if: github.event.deployment_status.state == 'success'
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version-file: '.nvmrc'
      - name: Install dependencies
        run: yarn
      - name: Install Playwright
        run: npx playwright install --with-deps
      - name: Run Storybook tests
        run: yarn test-storybook
        env:
          TARGET_URL: '${{ github.event.deployment_status.target_url }}'

两种方案的关键差异:

  • 部署方案:由 Vercel、Netlify 等平台触发 deployment_status 事件,if: github.event.deployment_status.state == 'success' 保证只在部署成功后执行测试,并通过 TARGET_URL 环境变量把部署地址传给 Test Runner;前提是已发布的 Storybook 必须可公开访问,若需要认证则建议改用本地构建方案。
  • 本地构建方案:不依赖外部部署平台,直接在 CI 内构建、服务、测试,产物无需公网可达。

运行测试时,--url 参数与 TARGET_URL 环境变量是等效的两种指定目标地址的方式(test-runner-execute-with-url.md):

# 方式一:--url 参数
yarn test-storybook --url https://the-storybook-url-here.com
# 方式二:TARGET_URL 环境变量
TARGET_URL=https://the-storybook-url-here.com yarn test-storybook

常用 CLI 参数与排查要点

Test Runner 基于 Jest 构建,接受其部分 CLI 参数。以下是高频使用的选项(完整清单见 test-runner.mdx):

参数 用途 示例
--url 指定测试目标 URL(默认本地 6006) test-storybook --url http://localhost:6007
--maxWorkers 限制并行 worker 数,适合内存受限的 CI test-storybook --maxWorkers=2
--watch / --watchAll 监听模式,仅本地开发使用 test-storybook --watch
--coverage 配合 @storybook/addon-coverage 生成覆盖率 test-storybook --coverage
--failOnConsole 浏览器出现 console 错误即判定失败 test-storybook --failOnConsole
--index-json 基于 index.json 静态索引运行(不支持 watch) test-storybook --index-json
--eject 生成 test-runner-jest.config.js 便于深度定制 test-storybook --eject
--ci CI 模式下快照不自动写入,失败需 -u 更新 test-storybook --ci
--shard 1/8 将测试套件拆分到多台机器并行 test-storybook --shard=1/8

官方文档还给出了两个 CI 环境下的高频排查点(Troubleshooting):

  • 测试超时:若出现 Timeout - Async callback was not invoked within the 15000 ms timeout specified by jest.setTimeout,通常是 Story 数量过多或 CI 内存不足,可通过 --maxWorkers=2 限制并行度解决;
  • 错误输出过短:CLI 默认截断错误输出为 1000 字符,可通过 DEBUG_PRINT_LIMIT=5000 yarn test-storybook 放大限制,完整堆栈也可直接在浏览器中打开对应 Story 查看。

演进方向:Vitest Addon

官方文档在 Test Runner 文档开头给出了重要提示:Test Runner 正被 Vitest addon 逐步取代——后者基于更快、更现代的 Vitest 浏览器模式,提供同样的能力,并能在 Storybook 应用中直接运行交互、无障碍与视觉测试。对于使用 Vite 构建的 Storybook 框架,官方推荐优先考虑 Vitest addon。对于仍在 Webpack 技术栈或需要零配置 Jest + Playwright 组合的团队,本文的本地构建工作流依然是经过官方验证的稳定方案。

小结

本文完整拆解了 Storybook Test Runner 的“本地构建 CI 工作流”:在 GitHub Actions 中用 build-storybook 产出静态产物,以 http-server 托管在 6006 端口,通过 wait-on 探测就绪后由 concurrently -k -s first 编排执行 test-storybook,测试结束后自动回收服务器并把退出码正确回传给 CI。这套方案无需公网部署即可在任何 CI 供应商上运行 Storybook 组件测试,适合需要认证访问或希望测试与部署解耦的项目;若 Storybook 可公开访问,也可改用 deployment_status + TARGET_URL 的部署式工作流。两种方案共享同一套安装、配置与 CLI 参数体系,可从 test-runner.mdx 获取全部细节。

热门项目推荐
相关项目推荐

项目优选

收起
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.15 K
2.77 K
kernelkernel
deepin linux kernel
C
34
18
docsdocs
暂无描述
Markdown
900
5.83 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
929
1.85 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.36 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.94 K
1.03 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.47 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
534
603
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
398
leetcodeleetcode
🔥LeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer(第 2 版)》、《程序员面试金典(第 6 版)》题解
Markdown
77
23