Supabase 仓库中 Vitest CLI 实战指南:命令、常用选项与 CI 分片策略全解析
本文以 Supabase 开源仓库内置的 Vitest CLI 参考文档为骨架,完整梳理 Vitest 命令行接口(CLI)的命令体系、常用选项与 CI 分片策略,并结合该仓库中多个应用(Studio、Docs、WWW、UI 包)的真实测试脚本与配置文件,说明这些命令和选项在大型 pnpm + Turborepo monorepo 中的实际用法。读完本文,你既能快速掌握 Vitest CLI 的每个子命令与过滤、覆盖率、分片等关键参数的含义,也能学到一套可直接复用到 Supabase 这类 monorepo 中的测试执行与 CI 组织方式。
1. CLI 文档在 Supabase 仓库中的定位
该文档位于仓库的 Agent 技能目录 .agents/skills/vitest/references/core-cli.md,属于 Vitest 技能包(见 .agents/skills/vitest/SKILL.md)中"Core"部分的 CLI 参考页,基于 Vitest 3.x 于 2026-01-28 生成。它与同目录下的 core-config、core-test-api、features-filtering 等参考页共同构成 Vitest 的速查手册。
在 Supabase 仓库中,Vitest 是多个应用的单测执行器。根目录 package.json 通过 Turborepo 定义了按包过滤的测试入口:
{
"scripts": {
"test:docs": "turbo run test --filter=docs",
"test:ui": "turbo run test --filter=ui",
"test:ui-patterns": "turbo run test --filter=ui-patterns",
"test:studio": "turbo run test --filter=studio",
"test:studio:watch": "turbo run test --filter=studio -- watch"
}
}
即根命令 turbo run test --filter=<包名> 最终落到各包 package.json 的 test 脚本上,而各包的 test 脚本正是本文所讲的 Vitest CLI 命令组合。仓库运行环境要求(根 package.json 的 engines 字段)为 Node >=22.13、pnpm 11.13。
2. 命令体系:从 vitest 到 vitest init
2.1 vitest:默认入口
裸命令 vitest 的行为取决于运行环境——开发环境进入 watch 模式,CI 环境(process.env.CI 已设置)自动切换为 run 模式:
vitest # Watch mode in dev, run mode in CI
vitest foobar # Run tests containing "foobar" in path
vitest basic/foo.test.ts:10 # Run specific test by file and line number
两个细节值得注意:
- 位置参数支持"文件名包含"式模糊匹配(
vitest foobar匹配路径中含foobar的测试文件),也支持文件路径:行号的精确格式; - CI 自动检测正是 Supabase 仓库中大量配置生效的开关。例如 apps/studio/vitest.config.ts 中:
const IS_CI = !!process.env.CI
// ...
test: {
// Retry flaky tests in CI only; failures locally should surface immediately.
retry: IS_CI ? 2 : 0,
}
可以确认:Studio 包的配置刻意让本地失败立即暴露,而仅在 CI 中对 flaky 测试重试 2 次(对应 CLI 的 --retry 选项)。
2.2 vitest run:单次运行
显式以"运行一次后退出"的模式执行,是 CI 与提交前检查的推荐形式:
vitest run
vitest run --coverage
Supabase 仓库中多个包都遵循这一约定。例如 apps/www/package.json 与 packages/dev-tools/package.json:
{ "test": "vitest --run" } // apps/www(kebab-case 等价写法)
{ "test": "vitest run" } // packages/dev-tools(子命令写法)
两种写法(vitest run 子命令与 vitest --run 标志)都用于保证"单次运行",文档在 Key Points 中特别强调了对 lint-staged 等 pre-commit 工具的重要性——否则钩子会卡在 watch 模式无法退出。
2.3 vitest watch:显式 watch 模式
vitest watch
与 2.1 中依赖环境推断不同,vitest watch 明确强制进入 watch 模式。仓库中 apps/studio/package.json 提供了典型的本地开发脚本:
{
"scripts": {
"test:watch": "vitest watch",
"test": "vitest --run --coverage",
"test:ui": "vitest --ui",
"test:update": "vitest --run --update",
"test:report": "open coverage/lcov-report/index.html"
}
}
从源码结构看,Studio 包的日常测试闭环是:test:watch 开发调试 → test(等价于 vitest --run --coverage)提交前全量跑 → test:report 打开 lcov HTML 报告。其中 test:report 能打开 coverage/lcov-report/,正是因为 apps/studio/vitest.config.ts 的覆盖率配置声明了 reporter: ['text', 'text-summary', 'lcov'] 且限定 include: ['lib/**/*.ts']。
2.4 vitest related:只跑与变更文件相关的测试
vitest related src/index.ts src/utils.ts --run
该命令执行"导入(或反被导入)指定文件"的测试集合,文档特别标注其典型搭档是 lint-staged:在 pre-commit 阶段只对被暂存文件影响的测试跑单测,兼顾速度与覆盖。结尾的 --run 同样是为了让钩子能单次运行后退出。
2.5 vitest bench:只跑基准测试
vitest bench
独立于普通测试执行 bench 套件,避免基准测试拖慢常规 vitest run 的反馈周期。
2.6 vitest list:只列出、不执行
vitest list # List test names
vitest list --json # Output as JSON
vitest list --filesOnly # List only test files
list 命令在 CI 编排与工具链集成中非常实用:--json 输出可被脚本消费以生成测试清单或分片计划;--filesOnly 则用于快速清点测试文件分布,例如确认 apps/docs/vitest.config.ts 中 exclude: ['examples/**/*', '**/node_modules/**'] 生效后的文件集合。
2.7 vitest init:初始化项目
vitest init browser # Set up browser testing
用于在新项目中生成基础测试脚手架(如 browser 模式);对已经落地 Vitest 的成熟仓库,init 主要价值是参考其生成的配置形态。
3. 常用选项速查(含仓库佐证)
文档给出的常见选项按用途分组如下,本文在每组后补充了 Supabase 仓库中的实际用法佐证:
# Configuration
--config <path> # Path to config file
--project <name> # Run specific project
# Filtering
--testNamePattern, -t # Run tests matching pattern
--changed # Run tests for changed files
--changed HEAD~1 # Tests for last commit changes
# Reporters
--reporter <name> # default, verbose, dot, json, html
--reporter=html --outputFile=report.html
# Coverage
--coverage # Enable coverage
--coverage.provider v8 # Use v8 provider
--coverage.reporter text,html
# Execution
--shard <index>/<count> # Split tests across machines
--bail <n> # Stop after n failures
--retry <n> # Retry failed tests n times
--sequence.shuffle # Randomize test order
# Watch mode
--no-watch # Disable watch mode
--standalone # Start without running tests
# Environment
--environment <env> # jsdom, happy-dom, node
--globals # Enable global APIs
# Debugging
--inspect # Enable Node inspector
--inspect-brk # Break on start
# Output
--silent # Suppress console output
--no-color # Disable colors
3.1 过滤类:-t / --testNamePattern 的真实用例
apps/docs/package.json 中的 smoke 测试脚本是一个教科书级示例:
{
"scripts": {
"test": "pnpm supabase start && pnpm run test:local && pnpm supabase stop",
"test:local": "vitest --exclude \"**/*.smoke.test.ts\"",
"test:local:unwatch": "vitest --exclude \"**/*.smoke.test.ts\" --run",
"test:smoke": "pnpm run codegen:references && vitest -t \"prod smoke test\""
}
}
test:smoke 用 -t "prod smoke test" 按测试名模式只跑 smoke 用例;test:local 用 --exclude 把需要真实环境的 smoke 文件排除在本地单测之外,而 test:local:unwatch 再追加 --run 得到"排除 smoke 的单次运行"。这说明 CLI 标志与配置文件选项(如 apps/docs/vitest.config.ts 中的 setupFiles、globalSetup、exclude)可以叠加组合:配置定基线,CLI 标志做增量调整。
3.2 执行类:--retry 与环境差异
--retry <n> 在 Studio 包通过 retry: IS_CI ? 2 : 0(见 apps/studio/vitest.config.ts)体现为"CI 重试、本地零容忍"的策略,与文档 Key Points 中"watch 模式是开发默认、CI 自动切 run 模式"的设计哲学一致:本地求快求真,CI 求稳。
3.3 环境与全局 API:--environment / --globals
Studio 与 UI 包均为 React 组件测试,配置中显式声明了 environment: 'jsdom'(见 apps/studio/vitest.config.ts 与 packages/ui/vitest.config.ts),Studio 还同时开启 globals: true 以省略 import { describe, it, expect }。--environment 标志的价值在于临时覆盖配置——例如想对某个用例切换到 node 环境验证时不必改配置文件。
3.4 调试与输出:--inspect / --silent
--inspect 与 --inspect-brk 用于把 Node inspector 挂到测试进程上排查挂死、内存问题;--silent 抑制测试内 console 输出,便于在 CI 中聚焦失败信息。文档同时指出布尔选项支持 --no- 前缀取反(如 --no-watch、--no-color),且驼峰与 kebab-case 双写法通用(--testTimeout ≡ --test-timeout)——仓库脚本中两种风格都有出现(vitest --run --coverage 与 vitest list --filesOnly 即为证)。
4. package.json Scripts 的组织范式
文档给出的最小脚本集:
{
"scripts": {
"test": "vitest",
"test:run": "vitest run",
"test:ui": "vitest --ui",
"coverage": "vitest run --coverage"
}
}
对照 Supabase 仓库,各包在"watch/单次/UI/覆盖率"四个维度上都给出了实现,例如:
| 包 | test |
本地 watch | 其他 |
|---|---|---|---|
| apps/studio | vitest --run --coverage |
vitest watch |
test:ui、test:update(vitest --run --update)、test:report |
| apps/www | vitest --run |
vitest watch |
— |
| packages/ui | vitest |
— | — |
| packages/dev-tools | vitest run |
vitest |
— |
可见仓库实际做法比文档模板更细:把"默认带覆盖率的 CI 跑法"直接放进 test(供 Turborepo 的 turbo run test --filter=studio 聚合调用),把"带 UI 的可视化运行"与"快照更新"拆成独立脚本,避免开发者手敲长串标志。根目录 package.json 的 test:studio:watch(turbo run test --filter=studio -- watch)还展示了 Turborepo 语法:-- 之后的参数会透传给目标包的 test 脚本,从而临时切换到 watch 参数。
5. CI 分片(Sharding):文档方案与仓库实践
5.1 文档给出的标准分片流程
将测试切分到多台机器并行,最后合并报告:
# Machine 1
vitest run --shard=1/3 --reporter=blob
# Machine 2
vitest run --shard=2/3 --reporter=blob
# Machine 3
vitest run --shard=3/3 --reporter=blob
# Merge reports
vitest --merge-reports --reporter=junit
要点:每台机器用 --shard=index/count 声明自己在分片矩阵中的位置,并以 blob reporter 产出可合并的中间报告;聚合端用 --merge-reports 把所有分片的 blob 汇总为最终报告(示例输出为 junit)。
5.2 仓库中同构的 CI 实践
从源码结构看,Supabase 仓库的 e2e CI 采用了与上述文档完全同构的"分片 + blob + merge"三件套,见 .github/workflows/studio-e2e-test.yml:
strategy:
matrix:
shardIndex: [1, 2]
shardTotal: [2]
# ...
run: PWTEST_SHARD_WEIGHTS=62:38 pnpm e2e --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
工作流中包含独立的 merge-reports job 聚合各分片结果,并用 blob-report-<framework>-<shardIndex> 命名的工件传递中间报告。虽然该流水线分片的是 Playwright e2e 套件,但其"矩阵分片 → 每片产出 blob 工件 → 独立 job 合并"的架构与 vitest run --shard=n/m --reporter=blob + vitest --merge-reports 的方案一一对应。可以推断:在 Studio 这类测试量大的包上,Vitest 单测分片若需横向扩展,可直接套用文档中的标准写法,与现有 CI 的分片/合并习惯保持一致。
6. Watch 模式快捷键与关键行为要点
6.1 键盘快捷键
进入 watch 模式后按以下键与测试会话交互:
| 按键 | 作用 |
|---|---|
a |
运行全部测试(清除过滤) |
f |
只运行上次失败的测试 |
u |
更新快照 |
p |
按文件名模式过滤 |
t |
按测试名模式过滤 |
q |
退出 |
这套快捷键与 CLI 的过滤选项形成对应关系:p 对应路径过滤,t 对应 --testNamePattern,u 等价于 --update(Studio 包的 test:update 脚本即其一次性版本)。
6.2 Key Points 汇总
文档结尾的四条行为要点是使用 CLI 前必须建立的心智模型,本文结合仓库给出印证:
- Watch 是开发默认、CI 是 run 模式——由
process.env.CI驱动。Supabase 的 CI 侧脚本(如 apps/studio/package.json 的test:ci)仍显式写出vitest --run --coverage,双保险确保流水线行为确定; --run对 pre-commit 工具至关重要——保证 lint-staged 等钩子单次运行后能退出;- 驼峰与 kebab-case 参数等价(
--testTimeout≡--test-timeout)——仓库脚本两种风格混用而互不影响; - 布尔选项支持
--no-取反——如--no-watch、--no-color,可临时压住配置或默认行为。
7. 在 Supabase 仓库中上手 Vitest CLI 的操作路径
结合仓库结构,推荐的实操路径如下(均为只读/运行类操作,环境前提:Node >=22.13、pnpm 11.13,依赖用 pnpm install 安装):
- 单包本地调试:进入目标包(如
apps/studio)后pnpm test:watch,用f/p/t快捷键收敛到失败用例; - 单包提交前验证:
pnpm test(Studio 包即vitest --run --coverage),失败快照用pnpm test:update(vitest --run --update)批量更新后人工复核; - 按名/按文件过滤:
vitest -t "prod smoke test"复刻 apps/docs 的 smoke 用法;vitest 关键字做路径模糊匹配; - 清点与工具化:
vitest list --filesOnly或vitest list --json生成测试清单供脚本消费; - 从仓库根聚合运行:
pnpm test:studio/pnpm test:ui走 Turborepo 过滤链路,适合改动跨包依赖(如packages/ui)后的回归验证; - 深入配置:CLI 选项之外,各包的
vitest.config.ts(如 apps/studio/vitest.config.ts、packages/ui/vitest.config.ts)定义了setupFiles、environment、coverage.include等基线,CLI 标志在其上做临时覆盖。
需要说明的适用边界:本文的 CLI 参考基于 Vitest 3.x(技能包于 2026-01-28 生成),标志语义以该版本为准;仓库内部分 test 脚本(如 apps/docs)会先拉起本地 Supabase 环境(pnpm supabase start)再执行 vitest,此类组合脚本依赖仓库根 package.json 中的 setup:cli 类基础设施,脱离仓库环境时不能直接照搬。
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 StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00