分析测试性能
运行 Vitest 时,它会报告多项测试时间指标:
bashRUN v2.1.1 /x/vitest/examples/profiling ✓ test/prime-number.test.ts (1) 4517ms ✓ generate prime number 4517ms Test Files 1 passed (1) Tests 1 passed (1) Start at 09:32:53 Duration 4.80s (transform 44ms, setup 0ms, collect 35ms, tests 4.52s, environment 0ms, prepare 81ms) # Time metrics ^^
- Transform(转换):文件转换所需的时间。参见 文件转换。
- Setup(设置):运行
setupFiles
文件所需的时间。 - Collect(收集):收集测试文件中所有测试所需的时间。这包括导入所有文件依赖项所需的时间。
- Tests(测试):实际运行测试用例所需的时间。
- Environment(环境):设置测试
environment
所需的时间,例如 JSDOM。 - Prepare(准备):Vitest 准备测试运行器所需的时间。
测试运行器
如果你的测试执行时间较长,可以生成测试运行器的性能分析文件。请参阅 NodeJS 文档以了解以下选项:
WARNING
由于 node:worker_threads
的限制,--prof
选项不适用于 pool: 'threads'
。
要将这些选项传递给 Vitest 的测试运行器,请在 Vitest 配置中定义 poolOptions.<pool>.execArgv
:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
pool: 'forks',
poolOptions: {
forks: {
execArgv: [
'--cpu-prof',
'--cpu-prof-dir=test-runner-profile',
'--heap-prof',
'--heap-prof-dir=test-runner-profile',
],
// 生成单个配置文件
singleFork: true,
},
},
},
});
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
pool: 'threads',
poolOptions: {
threads: {
execArgv: [
'--cpu-prof',
'--cpu-prof-dir=test-runner-profile',
'--heap-prof',
'--heap-prof-dir=test-runner-profile',
],
// 生成单个配置文件
singleThread: true,
},
},
},
});
测试运行后,应该会生成 test-runner-profile/*.cpuprofile
和 test-runner-profile/*.heapprofile
文件。有关如何分析这些文件的说明,请参阅 检查性能分析记录。
有关示例,请参阅 Profiling | Examples。
主线程
对主线程进行性能分析对于调试 Vitest 的 Vite 使用情况和 globalSetup
文件非常有用。 这也是你的 Vite 插件运行的地方。
为此,你需要将参数传递给运行 Vitest 的 Node.js 进程。
$ node --cpu-prof --cpu-prof-dir=main-profile ./node_modules/vitest/vitest.mjs --run
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^
# NodeJS 参数 Vitest 参数
测试运行后,应该会生成 main-profile/*.cpuprofile
文件。有关如何分析这些文件的说明,请参阅 检查性能分析记录。
文件转换
如果你的测试转换和收集时间较长,可以使用 DEBUG=vite-node:*
环境变量来查看哪些文件正在被 vite-node
转换和执行。
$ DEBUG=vite-node:* vitest --run
RUN v2.1.1 /x/vitest/examples/profiling
vite-node:server:request /x/vitest/examples/profiling/global-setup.ts +0ms
vite-node:client:execute /x/vitest/examples/profiling/global-setup.ts +0ms
vite-node:server:request /x/vitest/examples/profiling/test/prime-number.test.ts +45ms
vite-node:client:execute /x/vitest/examples/profiling/test/prime-number.test.ts +26ms
vite-node:server:request /src/prime-number.ts +9ms
vite-node:client:execute /x/vitest/examples/profiling/src/prime-number.ts +9ms
vite-node:server:request /src/unnecessary-file.ts +6ms
vite-node:client:execute /x/vitest/examples/profiling/src/unnecessary-file.ts +4ms
...
这种性能分析策略是识别由 桶文件(barrel files) 引起的不必要转换的有效手段。 如果这些日志包含在测试运行时不应加载的文件,则你的桶文件可能不必要地导入了文件。
你还可以使用 Vitest UI 来调试由桶文件引起的性能问题。 下面的示例展示了在不使用桶文件的情况下导入文件如何将转换的文件数量减少约 85%。
├── src
│ └── utils
│ ├── currency.ts
│ ├── formatters.ts <-- 要测试的文件
│ ├── index.ts
│ ├── location.ts
│ ├── math.ts
│ ├── time.ts
│ └── users.ts
├── test
│ └── formatters.test.ts
└── vitest.config.ts
import { expect, test } from 'vitest';
import { formatter } from '../src/utils';
import { formatter } from '../src/utils/formatters';
test('formatter works', () => {
expect(formatter).not.toThrow();
});

要查看文件如何被转换,你可以使用 VITE_NODE_DEBUG_DUMP
环境变量将转换后的文件写入文件系统:
$ VITE_NODE_DEBUG_DUMP=true vitest --run
[vite-node] [debug] dump modules to /x/examples/profiling/.vite-node/dump
RUN v2.1.1 /x/vitest/examples/profiling
...
$ ls .vite-node/dump/
_x_examples_profiling_global-setup_ts-1292904907.js
_x_examples_profiling_test_prime-number_test_ts-1413378098.js
_src_prime-number_ts-525172412.js
代码覆盖率
如果你的项目生成代码覆盖率报告很慢,可以使用 DEBUG=vitest:coverage
环境变量来启用性能日志记录。
$ DEBUG=vitest:coverage vitest --run --coverage
RUN v3.1.1 /x/vitest-example
vitest:coverage Reading coverage results 2/2
vitest:coverage Converting 1/2
vitest:coverage 4 ms /x/src/multiply.ts
vitest:coverage Converting 2/2
vitest:coverage 552 ms /x/src/add.ts
vitest:coverage Uncovered files 1/2
vitest:coverage File "/x/src/large-file.ts" is taking longer than 3s
vitest:coverage 3027 ms /x/src/large-file.ts
vitest:coverage Uncovered files 2/2
vitest:coverage 4 ms /x/src/untested-file.ts
vitest:coverage Generate coverage total time 3521 ms
这种性能分析方法非常适合检测被覆盖率提供程序意外选中的大文件。 例如,如果你的配置意外地将大型构建的压缩 Javascript 文件包含在代码覆盖率中,它们应该会出现在日志中。 在这些情况下,你可能需要调整你的 coverage.include
和 coverage.exclude
选项。
检查性能分析记录
你可以使用各种工具分析 *.cpuprofile
和 *.heapprofile
文件的内容。示例请参阅下面的列表。