提升性能
测试隔离
默认情况下,Vitest 会根据 pool 在隔离的环境中运行每个测试文件:
threads
池在单独的Worker
中运行每个测试文件。forks
池在单独的 forked child process 中运行每个测试文件。vmThreads
池在单独的 VM context 中运行每个测试文件,但它使用 Worker 进行并行处理。
这种隔离机制会显著增加测试时间。对于不依赖副作用且能正确清理其状态的项目(通常适用于 node
环境的项目)来说,这可能并非理想选择。在这种情况下,禁用隔离将提高测试速度。为此,你可以向 CLI 提供 --no-isolate
标志,或者在配置中将 test.isolate
属性设置为 false
。如果你通过 poolMatchGlobs
同时使用多个池,也可以为特定的池禁用隔离。
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-reports
目录中收集结果,并使用 --merge-reports
选项进行合并:
vitest --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@v4
- 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@v4
- 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 核 CPU 上的测试拆分为 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 --merge-reports