性能优化
测试隔离
默认情况下,Vitest 会根据 pool 在隔离环境中运行每个测试文件:
threads
池在单独的Worker
中运行每个测试文件。forks
池在单独的 forked 子进程 中运行每个测试文件。vmThreads
池在单独的 VM 上下文 中运行每个测试文件,但它使用 worker 进行并行处理。
这种隔离机制会显著增加测试时间。对于不依赖副作用且能正确清理状态的项目(通常适用于 node
环境的项目)而言,这可能不是最佳选择。在这种情况下,禁用隔离可以提高测试速度。为此,你可以在 CLI 中提供 --no-isolate
标志,或者在配置中将 test.isolate
属性设置为 false
。
vitest --no-isolate
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
isolate: false,
// 你也可以只为特定的池禁用隔离
poolOptions: {
forks: {
isolate: false,
},
},
},
});
TIP
如果你使用的是 vmThreads
池,则无法禁用隔离。请改用 threads
池来提高测试性能。
对于某些项目,禁用并行以缩短启动时间可能也是可取的。为此,请向 CLI 提供 --no-file-parallelism
标志,或者在配置中将 test.fileParallelism
属性设置为 false
。
vitest --no-file-parallelism
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
fileParallelism: false,
},
});
池
默认情况下,Vitest 在 pool: 'forks'
中运行测试。虽然 'forks'
池在兼容性问题(挂起进程和段错误)方面表现更好,但在大型项目中,它可能比 pool: 'threads'
慢一些。
你可以尝试通过在配置中切换 pool
选项来改善测试运行时间:
vitest --pool=threads
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
pool: 'threads',
},
});
分片
测试分片是将测试套件拆分成组或分片的过程。当您拥有大型测试套件且有多台机器可以同时运行该套件的子集时,这会非常有用。
要将 Vitest 测试拆分到多个不同的运行中,请将 --shard
选项与 --reporter=blob
选项配合使用:
vitest run --reporter=blob --shard=1/3 # 第 1 台机器
vitest run --reporter=blob --shard=2/3 # 第 2 台机器
vitest run --reporter=blob --shard=3/3 # 第 3 台机器
Vitest 将您的测试文件(而非测试用例)拆分为分片。如果您有 1000 个测试文件,
--shard=1/4
选项将运行 250 个测试文件,无论单个文件包含多少个测试用例。
从每台机器收集 .vitest-reports
目录中存储的结果,并使用 --merge-reports
选项进行合并:
vitest run --merge-reports
Github action 示例
该设置同样适用于 https://github.com/vitest-tests/test-sharding。
# 灵感来自 https://playwright.dev/docs/test-sharding
name: Tests
on:
push:
branches:
- main
jobs:
tests:
runs-on: ubuntu-latest
strategy:
matrix:
shardIndex: [1, 2, 3, 4]
shardTotal: [4]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Install pnpm
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Install dependencies
run: pnpm i
- name: Run tests
run: pnpm run test --reporter=blob --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
- name: Upload blob report to GitHub Actions Artifacts
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4
with:
name: blob-report-${{ matrix.shardIndex }}
path: .vitest-reports/*
include-hidden-files: true
retention-days: 1
merge-reports:
if: ${{ !cancelled() }}
needs: [tests]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Install pnpm
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Install dependencies
run: pnpm i
- name: Download blob reports from GitHub Actions Artifacts
uses: actions/download-artifact@v4
with:
path: .vitest-reports
pattern: blob-report-*
merge-multiple: true
- name: Merge reports
run: npx vitest --merge-reports
TIP
测试分片在高 CPU 核心数的机器上也会非常有用。
Vitest 只会在其主线程中运行单个 Vite 服务器。其余线程则用于运行测试文件。 在 CPU 核心数较多的机器上,主线程可能会成为瓶颈,因为它无法处理来自所有测试线程的请求。例如,在 32 核机器上,主线程负责处理来自 31 个测试线程的负载。
为了减少主线程 Vite 服务器的负载,您可以使用测试分片。负载可以分摊到多个 Vite 服务器。
# 在 32 核机器上将测试拆分为 4 个分片的示例。
# 由于每个进程需要 1 个主线程,因此每个分片有 7 个线程用于测试运行器 (1+7)*4 = 32
# 根据池使用 VITEST_MAX_THREADS 或 VITEST_MAX_FORKS:
VITEST_MAX_THREADS=7 vitest run --reporter=blob --shard=1/4 & \
VITEST_MAX_THREADS=7 vitest run --reporter=blob --shard=2/4 & \
VITEST_MAX_THREADS=7 vitest run --reporter=blob --shard=3/4 & \
VITEST_MAX_THREADS=7 vitest run --reporter=blob --shard=4/4 & \
wait # https://man7.org/linux/man-pages/man2/waitpid.2.html
vitest run --merge-reports