关于 vitest-3-features
面向 Vitest 3.x 开发者的参考技能,涵盖测试功能、配置及从 Vitest 2.x 迁移的要点,并介绍定向运行、浏览器测试、报告和项目组织。
主要功能
- 01测试注释与附件
- 02按行号选择测试
- 03监视模式与报告改进
- 04工作区项目配置
- 05浏览器测试与覆盖率指南
- 06模拟与匹配器更新
适用场景
- 01开发时运行单个测试
- 02组织单元与集成测试项目
- 03向测试报告添加元数据
- 04将项目从 Vitest 2.x 迁移
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ josiahsiegel/ claude-plugin-marketplace --skill vitest-3-features安装后在 Claude Code 中输入/vitest-3-features确认已加载。
详细介绍
🚨 重要指南
Windows 文件路径要求
必须:在 Windows 上始终使用反斜杠表示文件路径
在 Windows 上使用 Edit 或 Write 工具时,必须在文件路径中使用反斜杠(\),而不是正斜杠(/)。
示例:
- ❌ 错误:
D:/repos/project/file.tsx - ✅ 正确:
D:\repos\project\file.tsx
适用于:
- Edit 工具的 file_path 参数
- Write 工具的 file_path 参数
- Windows 系统上的所有文件操作
文档指南
除非用户明确要求,否则绝不要创建新的文档文件。
- 优先级:更新现有的 README.md 文件,而不是创建新文档
- 仓库整洁度:保持仓库根目录整洁——除非用户另有要求,否则只保留 README.md
- 风格:文档应简洁、直接、专业,避免使用 AI 生成式语气
- 用户偏好:只有用户明确要求编写文档时,才创建其他 .md 文件
Vitest 3.x 功能与最佳实践(2025)
概述
Vitest 3.0 于 2025 年 1 月发布,在报告、浏览器测试、监视模式和开发者体验方面进行了重大改进。本指南全面介绍 Vitest 3.x 的功能和现代测试模式。
Vitest 3.0+ 的主要功能
1. 注解 API(Vitest 3.2+)
注解 API 允许你向任何测试添加自定义元数据、消息和附件,并在 UI、HTML、JUnit、TAP 和 GitHub Actions 报告器中查看。
用法:
import { test, expect } from 'vitest';
test('user authentication', async ({ task }) => {
// Add custom annotation
task.meta.annotation = {
message: 'Testing OAuth2 flow with external provider',
attachments: [
{ name: 'config', content: JSON.stringify(oauthConfig) }
]
};
const result = await authenticateUser(credentials);
expect(result.token).toBeDefined();
});
使用场景:
- 记录复杂的测试场景
- 附加调试信息
- 链接到外部资源(工单、文档)
- 添加性能指标
- 跟踪用于报告的测试元数据
2. 按行号筛选
通过文件中的行号运行特定测试,以便从 IDE 精确执行测试。
CLI 用法:
# Run test at specific line
vitest run tests/user.test.js:42
# Run multiple tests by line
vitest run tests/user.test.js:42 tests/user.test.js:67
# Works with ranges
vitest run tests/user.test.js:42-67
IDE 集成:
- VS Code:点击行号栏
- JetBrains IDE:从上下文菜单运行
- 支持“运行光标所在处的测试”功能
3. 增强的监视模式
监视模式更加智能、响应更快,变更检测也得到改进。
功能:
- 更准确地检测变更
- 仅重新运行受影响的测试
- 更快的重建速度
- 在 Windows 上更好地监视文件
- 减少误报
配置:
export default defineConfig({
test: {
watch: true,
watchExclude: ['**/node_modules/**', '**/dist/**'],
// New in 3.0: More intelligent caching
cache: {
dir: '.vitest/cache'
}
}
});
4. 改进的测试报告
全面改进了测试运行报告,减少闪烁并让输出更清晰。
报告器 API 变更:
// Custom reporter with new lifecycle
export default class CustomReporter {
onInit(ctx) {
// Called once at start
}
onTestStart(test) {
// More reliable test start hook
}
onTestComplete(test) {
// Includes full test metadata
}
onFinished(files, errors) {
// Final results with all context
}
}
优势:
- 测试运行期间终端闪烁更少
- 测试状态指示更清晰
- 错误格式更易读
- 改进进度跟踪
5. 简化工作区配置
无需单独的工作区文件,可直接在配置中定义项目。
旧方式(Vitest 2.x):
// vitest.workspace.js
export default ['packages/*'];
新方式(Vitest 3.0):
// vitest.config.js
export default defineConfig({
test: {
workspace: [
{
test: {
name: 'unit',
include: ['tests/unit/**/*.test.js']
}
},
{
test: {
name: 'integration',
include: ['tests/integration/**/*.test.js']
}
}
]
}
});
6. 增强的浏览器测试
改进了浏览器模式的性能和缓存机制。
多个浏览器实例:
export default defineConfig({
test: {
browser: {
enabled: true,
instances: [
{ browser: 'chromium', name: 'chrome' },
{ browser: 'firefox', name: 'ff' },
{ browser: 'webkit', name: 'safari' }
]
}
}
});
优势:
- 所有浏览器共用一个 Vite 服务
- 缓存文件处理结果
- 并行执行浏览器测试
- 缩短启动时间
7. 改进的覆盖率
自动将测试文件排除在覆盖率报告之外。
自动排除项(Vitest 3.0):
export default defineConfig({
test: {
coverage: {
provider: 'v8',
// Test files automatically excluded
// No need to manually exclude *.test.js
exclude: [
// Only need to specify custom exclusions
'**/node_modules/**',
'**/dist/**'
]
}
}
});
8. 增强的模拟功能
新增间谍函数复用和强大的匹配器。
间谍函数复用:
const spy = vi.fn();
// Vitest 3.0: Reuse spy on already mocked method
vi.spyOn(obj, 'method').mockImplementation(spy);
vi.spyOn(obj, 'method'); // Reuses existing spy
新匹配器:
// toHaveBeenCalledExactlyOnceWith
expect(mockFn).toHaveBeenCalledExactlyOnceWith(arg1, arg2);
// Ensures called exactly once with exact arguments
// Fails if called 0 times, 2+ times, or with different args
9. 项目排除模式
使用否定模式排除特定项目。
CLI 用法:
# Run all except integration tests
vitest run --project=!integration
# Run all except multiple projects
vitest run --project=!integration --project=!e2e
# Combine inclusion and exclusion
vitest run --project=unit --project=!slow
10. UI 改进
大幅增强了测试 UI,提供更好的调试和导航体验。
UI 新功能:
- 在 UI 中运行单个测试
- 自动滚动到失败的测试
- 可切换 node_modules 的可见性
- 改进筛选和搜索
- 更完善的测试管理控件
- 模块图可视化
启动 UI:
vitest --ui
Vitest 3.x 最佳实践
1. 使用注解 API 处理复杂测试
test('complex payment flow', async ({ task }) => {
task.meta.annotation = {
message: 'Tests Stripe webhook integration',
attachments: [
{ name: 'webhook-payload', content: JSON.stringify(payload) },
{ name: 'ticket', content: 'https://jira.company.com/TICKET-123' }
]
};
// Test implementation
});
2. 在开发中充分利用按行筛选
# Quick iteration on single test
vitest run src/auth.test.js:145 --watch
3. 使用工作区项目组织测试
export default defineConfig({
test: {
workspace: [
{
test: {
name: 'unit-fast',
include: ['tests/unit/**/*.test.js'],
environment: 'node'
}
},
{
test: {
name: 'unit-dom',
include: ['tests/unit/**/*.dom.test.js'],
environment: 'happy-dom'
}
},
{
test: {
name: 'integration',
include: ['tests/integration/**/*.test.js'],
setupFiles: ['tests/setup.js']
}
}
]
}
});
4. 使用 toHaveBeenCalledExactlyOnceWith 进行严格测试
test('should call API exactly once with correct params', () => {
const apiSpy = vi.spyOn(api, 'fetchUser');
renderComponent({ userId: 123 });
// Strict assertion - fails if called 0, 2+ times or wrong args
expect(apiSpy).toHaveBeenCalledExactlyOnceWith(123);
});
5. 优化大型项目的监视模式
export default defineConfig({
test: {
watch: true,
watchExclude: [
'**/node_modules/**',
'**/dist/**',
'**/.git/**',
'**/coverage/**'
],
// Run only related tests
changed: true,
// Faster reruns
isolate: false // Use with caution
}
});
6. 为 CI/CD 使用自定义报告器
// reporters/junit-plus.js
export default class JUnitPlusReporter {
onFinished(files, errors) {
const results = files.map(file => ({
name: file.name,
tests: file.tasks.length,
failures: file.tasks.filter(t => t.result?.state === 'fail').length,
// Add annotations from tests
annotations: file.tasks
.map(t => t.meta?.annotation)
.filter(Boolean)
}));
// Export to CI system
exportToCI(results);
}
}
// vitest.config.js
export default defineConfig({
test: {
reporters: ['default', './reporters/junit-plus.js']
}
});
从 Vitest 2.x 迁移到 3.x
破坏性变更
-
工作区配置:
- 将工作区项目移至主配置中
- 更新项目引用
-
报告器 API:
- 将自定义报告器更新为使用新的生命周期
- 检查报告器方法签名
-
浏览器模式:
- 如果使用浏览器模式,请更新提供程序语法
- 检查浏览器配置
迁移步骤
# Update Vitest
npm install -D vitest@^3.0.0
# Update related packages
npm install -D @vitest/ui@^3.0.0
npm install -D @vitest/coverage-v8@^3.0.0
# Run tests to check for issues
npm test
# Update configs based on deprecation warnings
性能优化技巧
1. 使用工作区项目实现隔离
// Separate fast unit tests from slower integration tests
workspace: [
{
test: {
name: 'unit',
include: ['tests/unit/**'],
environment: 'node' // Fastest
}
},
{
test: {
name: 'integration',
include: ['tests/integration/**'],
environment: 'happy-dom',
setupFiles: ['tests/setup.js']
}
}
]
2. 并行执行测试
# Run projects in parallel
vitest run --project=unit --project=integration
# Exclude slow tests during development
vitest run --project=!e2e --project=!slow
3. 使用行过滤进行 TDD
# Rapid iteration on single test
vitest run src/feature.test.js:42 --watch
4. 优化浏览器测试
export default defineConfig({
test: {
browser: {
enabled: true,
// Reuse context for speed (less isolation)
isolate: false,
// Single instance for development
instances: [{ browser: 'chromium' }]
}
}
});
常见模式
用于调试的测试注释
test('payment processing', async ({ task }) => {
const startTime = Date.now();
try {
const result = await processPayment(data);
task.meta.annotation = {
message: `Completed in ${Date.now() - startTime}ms`,
attachments: [
{ name: 'result', content: JSON.stringify(result) }
]
};
expect(result.success).toBe(true);
} catch (error) {
task.meta.annotation = {
message: 'Payment processing failed',
attachments: [
{ name: 'error', content: error.message },
{ name: 'payload', content: JSON.stringify(data) }
]
};
throw error;
}
});
多项目测试策略
export default defineConfig({
test: {
workspace: [
// Fast feedback loop
{
test: {
name: 'unit-critical',
include: ['tests/unit/critical/**'],
environment: 'node'
}
},
// Standard tests
{
test: {
name: 'unit-standard',
include: ['tests/unit/**'],
exclude: ['tests/unit/critical/**'],
environment: 'happy-dom'
}
},
// Slow integration tests
{
test: {
name: 'integration',
include: ['tests/integration/**'],
testTimeout: 30000
}
}
]
}
});