Vitest
Vitest 是 Vite 生态系统中的一个测试运行器。将其与 Turborepo 集成将带来巨大的速度提升。
Vitest 文档 展示了如何创建“Vitest 项目”配置,该配置从一个根命令运行 monorepo 中的所有测试,从而开箱即用地实现合并的代码覆盖率报告等功能。此功能不遵循 monorepo 的现代最佳实践,因为它旨在与 Jest 兼容(Jest 的 Workspace 功能是在 包管理器 Workspaces 之前构建的)。
Vitest 已弃用 workspaces,转而使用 projects。使用 projects 时,各个项目的 vitest 配置无法再扩展根配置,因为它们会继承 projects 配置。相反,需要一个单独的共享文件,如 vitest.shared.ts。
因此,您有两种选择,每种都有其自身的权衡
利用 Turborepo 进行缓存
为了提高缓存命中率并仅运行已更改的代码的测试,您可以选择为每个包配置任务,将 Vitest 命令拆分为每个包中单独的可缓存脚本。这种速度是以您需要自己创建合并的代码覆盖率报告为代价的。
有关完整示例,请运行 npx create-turbo@latest --example with-vitest 或 访问示例的源代码。
设置
假设我们有一个简单的 包管理器 Workspace,如下所示
apps/web 和 packages/ui 都有自己的测试套件,vitest 安装在使用它们的包中。它们的 package.json 文件包含一个运行 Vitest 的 test 脚本
在根目录的 turbo.json 中,创建一个 test 任务


现在,turbo run test 可以并行化并缓存每个包的所有测试套件,仅测试已更改的代码。
在监视模式下运行测试
当您在 CI 中运行测试套件时,它会记录结果并在完成后退出。这意味着您可以 使用 Turborepo 缓存它。但是,当您在开发过程中使用 Vitest 的监视模式运行测试时,该进程永远不会退出。这使得监视任务更像一个 长期运行的开发任务。
由于这种差异,我们建议指定 **两个独立的 Turborepo 任务**:一个用于运行测试,一个用于在监视模式下运行它们。
下面的策略创建了两个任务,一个用于本地开发,一个用于 CI。您可以选择将 test 任务用于本地开发,并创建一些 test:ci 任务。
例如,在每个工作区的 package.json 文件中
然后在根目录的 turbo.json 中


您现在可以使用 全局 turbo 以 turbo run test:watch 的方式运行您的任务,或者从根目录的 package.json 中的脚本运行
创建合并的代码覆盖率报告
Vitest 的 Projects 功能 开箱即用地创建了代码覆盖率报告,该报告合并了您所有包的测试代码覆盖率报告。但是,按照 Turborepo 的策略,您将不得不自己合并代码覆盖率报告。
with-vitest 示例 展示了一个完整的示例,您可以根据需要进行调整。您可以使用 npx create-turbo@latest --example with-vitest 快速开始使用它。
要做到这一点,您需要遵循几个通用步骤
- 运行
turbo run test以创建代码覆盖率报告。 - 使用
nyc merge合并代码覆盖率报告。 - 使用
nyc report创建报告。
Turborepo 任务将如下所示


设置好之后,运行 turbo test && turbo report 以创建合并的代码覆盖率报告。
with-vitest 示例 展示了一个完整的示例,您可以根据需要进行调整。您可以使用 npx create-turbo@latest --example with-vitest 快速开始使用它。
使用 Vitest 的 Projects 功能
Vitest Projects 功能不遵循与 包管理器 Workspace 相同的模型。相反,它使用一个根脚本,然后该脚本会触及仓库中的每个包,以处理相应包中的测试。
在此模型中,从现代 JavaScript 生态系统的角度来看,没有包边界。这意味着您无法依赖 Turborepo 的缓存,因为 Turborepo 依赖于这些包边界。
因此,如果您想使用 Turborepo 运行测试,您需要使用 Root Tasks。配置好 Vitest Projects 设置 后,为 Turborepo 创建 Root Tasks


值得注意的是,Root Task 的文件输入默认包含所有包,因此任何包中的更改都会导致缓存未命中。 虽然这简化了创建合并的代码覆盖率报告的配置,但您将错过缓存重复工作的机会。
使用混合方法
您可以通过实现混合解决方案来结合这两种方法的优点。此方法使用 Vitest 的 Projects 功能统一本地开发,同时保留 CI 中的 Turborepo 缓存。这需要进行一些额外的配置,并且在存储库中采用混合任务运行模型。
首先,创建一个共享配置包,因为在项目使用 projects 时,单个项目无法扩展根配置。为您的共享 Vitest 配置创建一个新包
然后,使用 projects 创建您的根 Vitest 配置
在此设置中,您的包维护其个人 Vitest 配置,这些配置导入共享配置。首先,安装共享配置包
然后创建 Vitest 配置
确保更新您的 turbo.json 以将新配置包包含在依赖关系图中


虽然您的根 package.json 包含全局运行测试的脚本
此配置允许开发人员在根目录运行 pnpm test:projects 或 pnpm test:projects:watch 以获得无缝的本地开发体验,使用 Vitest projects,而 CI 继续使用 turbo run test 来利用包级别的缓存。您仍需要手动处理合并的代码覆盖率报告,如上一节所述。