supabase 仓库中的 Vitest 配置实践vitest.config.ts 核心选项与多包测试体系详解【免费下载链接】supabaseThe Postgres development platform. Supabase gives you a dedicated Postgres database to build your web, mobile, and AI applications.项目地址: https://gitcode.com/GitHub_Trending/supa/supabaseVitest 的配置文件是整个测试体系的地基它决定测试在什么环境中运行、如何发现测试文件、失败后如何重试、覆盖率如何统计。本文基于 supabase 仓库中的 Vitest 配置参考文档core-config.md展开并结合仓库内apps/studio、apps/docs、apps/www、packages/ui等真实vitest.config.ts文件讲清楚配置加载优先级、核心选项的取值与语义以及大型 Monorepo 如何组织多包测试配置。读完后你可以独立完成一个新包的 Vitest 配置并读懂本仓库各应用包的测试脚本行为。配置加载机制vitest.config.ts 与 vite.config.tsVitest 从vitest.config.ts或vite.config.ts读取配置且与 Vite 共享同一套配置格式——测试专属配置全部挂在test属性下其余字段就是标准 Vite 配置如plugins、resolve.alias。这意味着 Vite 的转换管线在测试中同样生效resolve.alias、插件都能直接复用这是 Vitest 相对独立测试框架的一个关键设计收益。配置解析有几条明确的优先级与约定vitest.config.ts优先于vite.config.ts可通过--config命令行参数指定自定义配置路径运行测试时process.env.VITEST会被设置为true可用于区分是否处于测试环境测试专用选项一律写在test属性内。基础配置vitest.config.ts最小可用的独立测试配置如下// vitest.config.ts import { defineConfig } from vitest/config export default defineConfig({ test: { // test options }, })supabase 仓库中packages/ai-commands包就是一个典型的独立配置示例packages/ai-commands/vitest.config.ts/// reference typesvitest / import { defineConfig } from vitest/config export default defineConfig({ test: { environment: node, testTimeout: 30000, setupFiles: [./vitest.setup.ts], }, })这个 AI 命令包跑的是 Node 侧逻辑不需要 DOM 环境因此environment显式设为node并把testTimeout从默认的 5000ms 放宽到 30000ms——AI 相关测试通常涉及网络或模型调用默认超时不够用。与已有 Vite 配置共存如果项目已有vite.config.ts可以直接在其上扩展test属性同时加上类型引用让 TypeScript 识别该字段// vite.config.ts /// reference typesvitest/config / import { defineConfig } from vite export default defineConfig({ test: { globals: true, environment: jsdom, }, })注意/// reference typesvitest/config /这一行的作用它把 Vitest 的类型扩展注入到 Vite 的UserConfig中使test字段获得类型提示与校验而无需引入额外的类型声明文件。合并配置mergeConfig当 Vite 配置与测试配置分处两个文件、又不想互相 import 副作用时可以用mergeConfig显式合并// vitest.config.ts import { defineConfig, mergeConfig } from vitest/config import viteConfig from ./vite.config export default mergeConfig(viteConfig, defineConfig({ test: { environment: jsdom, }, }))mergeConfig是 Vite 提供的深合并工具会正确合并数组如plugins追加与对象如resolve.alias按 key 合并避免手写展开运算符导致的字段覆盖。核心配置选项逐一拆解参考文档列出了最常用的test选项全集下面结合仓库中的真实用法逐项说明。defineConfig({ test: { // 启用全局 APIdescribe、it、expect无需 import globals: true, // 测试环境node、jsdom、happy-dom environment: node, // 每个测试文件执行前运行的 setup 文件 setupFiles: [./tests/setup.ts], // 测试文件匹配规则 include: [**/*.{test,spec}.{js,ts,jsx,tsx}], // 排除规则 exclude: [**/node_modules/**, **/dist/**], // 测试超时ms testTimeout: 5000, // 钩子超时ms hookTimeout: 10000, // 默认进入 watch 模式 watch: true, // 覆盖率配置 coverage: { provider: v8, // 或 istanbul reporter: [text, html], include: [src/**/*.ts], }, // 隔离执行每个文件独立进程 isolate: true, // 执行池threads、forks、vmThreads pool: threads, // 线程/进程数 poolOptions: { threads: { maxThreads: 4, minThreads: 1, }, }, // 测试间自动清空 mock clearMocks: true, // 测试间自动恢复 mock restoreMocks: true, // 失败重试次数 retry: 0, // 首次失败即停止0 为不启用 bail: 0, }, })globals、environment环境选择与全局 APIenvironment: node适合纯逻辑、服务端代码如 packages/ai-commands/vitest.config.tsenvironment: jsdom适合渲染 React 组件的测试。apps/studio与packages/ui均为 UI 应用/组件库配置里都写了environment: jsdom见 apps/studio/vitest.config.tsglobals: true免去每个文件import { describe, it, expect } from vitestapps/studio即采用该方式。值得一提的是apps/studio的配置中留下了一条 TODO 注释environment: jsdom, // TODO(kamil): This should be set per test via header in .tsx files only这说明团队有意让环境默认值全局生效未来计划逐步迁移为在单个.tsx测试文件头部按需声明环境实现全局 node、局部 jsdom的精细控制。setupFiles 与 globalSetup两个容易混淆的钩子setupFiles在每个测试文件的工作进程内执行适合注入 polyfill、mock、环境变量而globalSetup在整个测试运行开始时于主进程执行一次适合准备共享资源数据库、静态文件等。apps/docs同时使用了两者是理解二者分工的好样本apps/docs/vitest.config.ts 中export default defineConfig({ test: { // 排除 examples 目录避免被误当作测试发现路径 exclude: [examples/**/*, **/node_modules/**], setupFiles: [vitest.setup.ts], globalSetup: [vitest.globalSetup.ts], }, plugins: [ tsconfigPaths({ root: import.meta.dirname, // 只扫描本应用自己的 tsconfig避免误扫 examples/** 子目录 projects: [tsconfig.json], }), ], })apps/docs/vitest.setup.ts 在beforeAll里注入本地 Supabase 连接环境变量NEXT_PUBLIC_SUPABASE_URL指向http://localhost:54321并用vi.mock(server-only, ...)屏蔽 Next.js 的 server-only 模块限制afterAll中还原环境变量并doUnmockapps/docs/vitest.globalSetup.ts 则把仓库根目录的examples/目录整体拷贝到apps/docs/examples/保证CodeSample.test.ts等测试在npx vitest、pnpm test:local或 IDE 单测等绕过pretest生命周期钩子的场景下也能找到 fixture否则会报 ENOENT。对照apps/docs的 package.json 脚本apps/docs/package.jsontest: 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,可以看出命令行参数与配置文件是叠加关系--exclude在配置基础上额外排除 smoke 测试--run关闭默认 watch 行为以便 CI 一次性跑完。include / exclude测试发现与排除include默认匹配**/*.{test,spec}.*exclude默认排除node_modules、dist等。仓库中的实际用法展示了两个常见技巧展开configDefaults.exclude再追加自定义项避免默认排除项被覆盖。apps/www与apps/studio都这样写// apps/www exclude: [...configDefaults.exclude, .next/*],按文件粒度排除不稳定的大测试。apps/studio的exclude里除了.next/*Next.js 产物目录外还单独排除了tests/features/logs/logs-query.test.tsx与tests/features/reports/storage-report.test.tsx两个文件apps/studio/vitest.config.ts。注意apps/docs的配置注释特别强调exclude只影响测试发现不影响vite-tsconfig-paths插件对 tsconfig 的扫描所以插件侧需要单独用projects: [tsconfig.json]收敛扫描范围。testTimeout、retry超时与 CI 抖动策略testTimeout单测试超时与hookTimeoutbefore/after 类钩子超时是毫秒数按需放大如前文ai-commands包将testTimeout设为 30000retry是抑制 flaky 测试的标准手段。apps/studio的配置给出了一个值得参考的 CI 分层策略apps/studio/vitest.config.tsconst IS_CI !!process.env.CI test: { // 仅在 CI 中重试不稳定测试本地失败应立即暴露 retry: IS_CI ? 2 : 0, }本地开发时retry: 0让失败即时可见CI 环境允许最多 2 次重试来吸收流水线环境的偶发抖动。coverage覆盖率coverage下可指定providerv8或istanbul、reporter与参与统计的文件范围。仓库各包的差异展示了配置意图apps/studio/vitest.config.tsreporter: [text, text-summary, lcov]include: [lib/**/*.ts]只统计核心逻辑目录并排除**/*.test.ts(x)自身与个别无需覆盖的工具文件packages/ui/vitest.config.tsreporter: [lcov]include覆盖组件库源码src/**/*.{ts,tsx}配合 package.json 中的test:civitest --run --coverage与test:report打开coverage/lcov-report/index.html形成CI 收集、本地查看的完整链路packages/ui-patterns/vitest.config.ts 的 reporter 为[text, json, html]说明不同包按消费方式CI 汇总 vs 人工浏览选择不同的输出格式。pool、isolate执行模型isolate: true让每个测试文件在独立上下文中执行避免文件间状态串扰是大型仓库的安全默认pool: threads使用 Worker Threads 池执行测试forks走子进程隔离性更强但启动成本更高vmThreads提供 V8 隔离上下文poolOptions.threads.maxThreads / minThreads控制并发规模与--no-file-parallelism等 CLI 开关配合可以进一步调节。本仓库各包未显式配置pool使用默认值即可从各包测试能稳定运行的现状看默认参数对这类前端/Node 测试场景是足够的此结论为从仓库现状推断。clearMocks / restoreMocks / bailMock 卫生与失败策略clearMocks: true在每个测试前自动清空 mock 的调用记录与实现省去手写vi.clearAllMocks()restoreMocks: true更进一步把被vi.spyOn替换的原函数还原防止跨测试泄漏bail: 0表示失败后继续跑完剩余测试设为n则累计失败 n 次后停止本地调试想跑一个错一个时可临时调成 1。条件化配置mode 与 process.env.VITEST配置函数可以接收mode参数做条件化分支例如测试模式下跳过某些插件export default defineConfig(({ mode }) ({ plugins: mode test ? [] : [myPlugin()], test: { // test options }, }))同时process.env.VITEST true是另一条可靠的判断路径适合在共享代码而非配置文件中切换行为。apps/studio的IS_CI条件化见上文 retry 示例则是同一思路在 CI 维度的延伸条件分支不必局限于测试/非测试任何环境变量都可驱动配置。Monorepo 场景projects 与多包配置两种组织方式参考文档给出的projects方案是在一个 Vitest 进程内运行多套配置defineConfig({ test: { projects: [ packages/*, { test: { name: unit, include: [tests/unit/**/*.test.ts], environment: node, }, }, { test: { name: integration, include: [tests/integration/**/*.test.ts], environment: jsdom, }, }, ], }, })projects数组成员既可以是目录通配如packages/*每个子目录用自己的配置也可以是内联配置对象适合同一个测试树按 unit/integration 分泳道的场景。而 supabase 仓库本身采用的是另一种 Monorepo 组织方式pnpm workspace Turbo每个应用/包各自维护独立的vitest.config.tsapps/docs、apps/studio、apps/www、packages/ui、packages/ui-patterns、packages/ai-commands、packages/dev-tools等由根目录 package.json 的脚本按 filter 分发执行test:docs: turbo run test --filterdocs, test:ui: turbo run test --filterui, test:ui-patterns: turbo run test --filterui-patterns, test:studio: turbo run test --filterstudio从源码结构看这种每包独立配置 Turbo 编排的方式让各包可以完全自主地选择 environment、setup 与覆盖率范围前文各包的差异即为例证代价是需要在每个包内重复少量通用配置两种方案各有取舍可依据包之间配置的同质程度选择。关键要点回顾Vitest 复用 Vite 的转换管线resolve.alias、plugins在测试中直接生效本仓库各配置普遍依赖vite-tsconfig-paths与vitejs/plugin-react插件vitest.config.ts优先于vite.config.ts自定义路径用--config指定process.env.VITEST在测试运行时为true测试专属选项全部收敛在test属性下其余字段是标准 Vite 配置仓库实战经验setupFiles每文件与globalSetup全局一次分工明确exclude记得展开configDefaults.excluderetry按 CI/本地分层设置coverage.include只圈定真正想统计的源码目录。掌握以上内容后你既能按参考文档快速写出新包的vitest.config.ts也能对照 apps/studio/vitest.config.ts、apps/docs/vitest.config.ts 等真实配置理解每个选项在本仓库测试体系中的实际落点。【免费下载链接】supabaseThe Postgres development platform. Supabase gives you a dedicated Postgres database to build your web, mobile, and AI applications.项目地址: https://gitcode.com/GitHub_Trending/supa/supabase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
