Storybook Test Runner 本地构建 CI 工作流实战:在 GitHub Actions 中构建、服务并运行组件测试
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 环境中,最常见的两种接入方式:
- 针对已部署的 Storybook 测试:依赖 Vercel、Netlify 等平台触发 GitHub Actions 的
deployment_status事件,将部署 URL 通过TARGET_URL环境变量传给 Test Runner; - 针对本地构建产物测试(本文主题):不依赖任何部署平台,在 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 ci或pnpm 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 获取全部细节。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust4.21 K636- DDeepSeek-V4.1-FlashDeepSeek-V4.1-Flash 是一个多模态混合专家(MoE)模型,拥有 5520 亿骨干参数,并支持最多一百万 token 的上下文长度。该模型原生支持图像和文本输入,并以自回归方式生成文本Python80
jforgamejforgame是一个一站式游戏服务器开发框架。包含游戏服务器开发所需要的各种组件,比如网关,socket服务端与客户端,自定义高效消息编解码,游戏热更新,游戏通用工具等等。包含游戏服,跨服,匹配服,后台管理系统等实现,同时提供大量业务案例以供学习。亦可用于其他socket应用,例如及时聊天等。Java201
fizz-gateway-nodeAn Aggregation API Gateway in Java . FizzGate 是一个基于 Java开发的微服务聚合网关,是拥有自主知识产权的应用网关国产化替代方案,能够实现热服务编排聚合、自动授权选择、线上服务脚本编码、在线测试、高性能路由、API审核管理、回调管理等目的,拥有强大的自定义插件系统可以自行扩展,并且提供友好的图形化配置界面,能够快速帮助企业进行API服务治理、减少中间层胶水代码以及降低编码投入、提高 API 服务的稳定性和安全性。Java110
certd开源SSL证书管理工具;全自动证书申请、更新、续期;通配符证书,泛域名证书申请;证书自动化部署到阿里云、腾讯云、主机、群晖、宝塔;https证书,pfx证书,der证书,TLS证书,nginx证书自动续签自动部署JavaScript120
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python300