Vitest
Vitest 实例需要当前的测试模式。它可以是:
- 在运行时测试时为
test - 在运行基准测试时为
benchmark实验性
Vitest 4 新增
Vitest 4 添加了几个新 API(它们标有 "4.0.0+" 徽章)并移除了已弃用的 API:
invalidateschangedTests(请使用onFilterWatchedSpecification代替)server(请使用vite代替)getProjectsByTestFile(请使用getModuleSpecifications代替)getFileWorkspaceSpecs(请使用getModuleSpecifications代替)getModuleProjects(自行通过this.projects过滤)updateLastChanged(重命名为invalidateFile)globTestSpecs(请使用globTestSpecifications代替)globTestFiles(请使用globTestSpecifications代替)listFile(请使用getRelevantTestSpecifications代替)
模式
测试
测试模式只会调用 test 或 it 内部的函数,当遇到 bench 时抛出错误。此模式使用配置中的 include 和 exclude 选项来查找测试文件。
基准测试 实验性
基准测试模式调用 bench 函数,当遇到 test 或 it 时抛出错误。此模式使用配置中的 benchmark.include 和 benchmark.exclude 选项来查找基准测试文件。
配置
根配置(或全局配置)。如果定义了项目,它们将会将此引用为 globalConfig。
WARNING
这是 Vitest 配置,它不扩展 Vite 配置。它只包含来自 test 属性的解析值。
vite
这是一个全局 ViteDevServer。
状态 实验性
WARNING
公共 state 是一个实验性 API(vitest.state.getReportedEntity 除外)。破坏性变更可能不遵循 SemVer,请在使用时固定 Vitest 的版本。
全局状态存储有关当前测试的信息。默认情况下它使用来自 @vitest/runner 的相同 API,但我们建议通过调用 @vitest/runner API 上的 state.getReportedEntity() 来使用 Reported Tasks API:
const task = vitest.state.idMap.get(taskId) // 旧 API
const testCase = vitest.state.getReportedEntity(task) // 新 API将来,旧 API 将不再暴露。
快照
全局快照管理器。Vitest 使用 snapshot.add 方法跟踪所有快照。
你可以通过 vitest.snapshot.summary 属性获取最新的快照摘要。
缓存
缓存管理器,存储有关最新测试结果和测试文件统计信息。在 Vitest 本身中,这仅由默认排序器用于排序测试。
监听器 4.0.0+
Vitest 监听器的实例,具有跟踪文件更改和重新运行测试的有用方法。如果内置监听器被禁用,你可以将自己的监听器与 onFileChange、onFileDelete 或 onFileCreate 一起使用。
项目
属于用户项目的 测试项目 数组。如果用户未指定它们,此数组将仅包含一个 根项目。
Vitest 将确保此数组中始终至少有一个项目。如果用户指定了不存在的 --project 名称,Vitest 将在定义此数组之前抛出错误。
getRootProject
function getRootProject(): TestProject这会返回根测试项目。根项目通常不会运行任何测试,也不会包含在 vitest.projects 中,除非用户在配置中显式包含根配置,或者根本没有定义任何项目。
根项目的主要目标是设置全局配置。实际上,rootProject.config 直接引用 rootProject.globalConfig 和 vitest.config:
rootProject.config === rootProject.globalConfig === rootProject.vitest.configprovide
function provide<T extends keyof ProvidedContext & string>(
key: T,
value: ProvidedContext[T],
): voidVitest 暴露了 provide 方法,它是 vitest.getRootProject().provide 的简写。使用此方法,你可以将值从主线程传递给测试。所有值在存储前都会通过 structuredClone 检查,但值本身不会被克隆。
要在测试中接收值,你需要从 vitest 入口点导入 inject 方法:
import { inject } from 'vitest'
const port = inject('wsPort') // 3000为了更好的类型安全,我们鼓励你扩充 ProvidedContext 的类型:
import { createVitest } from 'vitest/node'
const vitest = await createVitest('test', {
watch: false,
})
vitest.provide('wsPort', 3000)
declare module 'vitest' {
export interface ProvidedContext {
wsPort: number
}
}WARNING
严格来说,provide 是 TestProject 的方法,因此它仅限于特定项目。但是,所有项目都会继承根项目的值,这使得 vitest.provide 成为向测试传递值的通用方式。
getProvidedContext
function getProvidedContext(): ProvidedContext这会返回根上下文对象。这是 vitest.getRootProject().getProvidedContext 的简写。
getProjectByName
function getProjectByName(name: string): TestProject此方法按名称返回项目。类似于调用 vitest.projects.find。
WARNING
如果项目不存在,此方法将返回根项目——如果返回的项目是你正在查找的项目,请再次检查名称。
如果用户未自定义名称,Vitest 将分配一个空字符串作为名称。
globTestSpecifications
function globTestSpecifications(
filters?: string[],
): Promise<TestSpecification[]>此方法通过 project.globTestFiles 收集所有项目中的每个测试来构建新的 测试规范。它接受字符串过滤器来匹配测试文件——这些与 CLI 支持 的过滤器相同。
此方法会自动缓存所有测试规范。下次调用 getModuleSpecifications 时,除非之前调用了 clearSpecificationsCache,否则它将返回相同的规范。
WARNING
从 Vitest 3 开始,如果 poolMatchGlob 有多个池或启用了 typecheck,则可能存在具有相同模块 ID(文件路径)的多个测试规范。此可能性将在 Vitest 4 中移除。
const specifications = await vitest.globTestSpecifications(['my-filter'])
// [TestSpecification{ moduleId: '/tests/my-filter.test.ts' }]
console.log(specifications)getRelevantTestSpecifications
function getRelevantTestSpecifications(
filters?: string[]
): Promise<TestSpecification[]>此方法通过调用 project.globTestFiles 解析每个测试规范。它接受字符串过滤器来匹配测试文件——这些与 CLI 支持 的过滤器相同。如果指定了 --changed 标志,列表将被过滤为仅包含已更改的文件。getRelevantTestSpecifications 不会运行任何测试文件。
WARNING
此方法可能很慢,因为它需要根据 --changed 标志进行过滤。如果你只需要测试文件列表,请不要使用它。
- 如果你需要获取已知测试文件的规范列表,请改用
getModuleSpecifications。 - 如果你需要获取所有可能测试文件的列表,请使用
globTestSpecifications。
mergeReports
function mergeReports(directory?: string): Promise<TestRunResult>合并位于指定目录中的多个运行报告(如果未指定,则使用 --merge-reports 的值)。此值也可以设置在 config.mergeReports 上(默认会读取 .vitest/blob/ 文件夹)。
请注意,directory 将始终相对于工作目录解析。
如果设置了 config.mergeReports,startVitest 会自动调用此方法。
collect
function collect(filters?: string[]): Promise<TestRunResult>执行测试文件而不运行测试回调。collect 返回未处理的错误和 测试模块 数组。它接受字符串过滤器来匹配测试文件——这些与 CLI 支持 的过滤器相同。
此方法根据配置中的 include、exclude 和 includeSource 值解析测试规范。更多信息请参阅 project.globTestFiles。如果指定了 --changed 标志,列表将被过滤为仅包含已更改的文件。
WARNING
请注意,Vitest 不使用静态分析来收集测试。Vitest 将像运行常规测试一样,隔离执行每个测试文件。
这使得此方法非常慢,除非你在收集测试之前禁用了隔离。
start
function start(filters?: string[]): Promise<TestRunResult>初始化报告器、覆盖率提供者并运行测试。此方法接受字符串过滤器来匹配测试文件——这些与 CLI 支持 的过滤器相同。
WARNING
如果还调用了 vitest.standalone(),则不应调用此方法。如果你需要在 Vitest 初始化后运行测试,请改用 runTestSpecifications 或 rerunTestSpecifications。
如果未设置 config.mergeReports 和 config.standalone,startVitest 会自动调用此方法。
standalone 4.1.1+
function standalone(): Promise<void>- 别名:
initdeprecated
初始化报告器和覆盖率提供者。此方法不会运行任何测试。如果提供了 --watch 标志,即使未调用此方法,Vitest 仍会运行已更改的测试。
从内部实现来看,仅当启用 --standalone 标志时才会调用此方法。
WARNING
如果同时调用了 vitest.start(),则不应调用此方法。
如果设置了 config.standalone,startVitest 会自动调用此方法。
getModuleSpecifications
function getModuleSpecifications(moduleId: string): TestSpecification[]返回与模块 ID 相关的测试规范列表。ID 应该已经解析为绝对文件路径。如果 ID 不匹配 include 或 includeSource 模式,返回的数组将为空。
此方法可以根据 moduleId 和 pool 返回已缓存的规范。但请注意,project.createSpecification 始终返回一个新实例,并且不会自动缓存。然而,当调用 runTestSpecifications 时,规范会自动缓存。
WARNING
自 Vitest 3 起,此方法使用缓存来检查文件是否为测试文件。为确保缓存不为空,请至少调用一次 globTestSpecifications。
clearSpecificationsCache
function clearSpecificationsCache(moduleId?: string): void当调用 globTestSpecifications 或 runTestSpecifications 时,Vitest 会自动缓存每个文件的测试规范。此方法会根据第一个参数清除给定文件的缓存或清除整个缓存。
runTestSpecifications
function runTestSpecifications(
specifications: TestSpecification[],
allTestsRun = false
): Promise<TestRunResult>此方法根据接收到的 规范 运行每个测试。第二个参数 allTestsRun 由覆盖率提供者使用,以确定是否需要在报告中包含未覆盖的文件。
WARNING
此方法不会触发 onWatcherRerun、onWatcherStart 和 onTestsRerun 回调。如果你是基于文件更改重新运行测试,请考虑使用 rerunTestSpecifications 代替。
rerunTestSpecifications
function rerunTestSpecifications(
specifications: TestSpecification[],
allTestsRun = false
): Promise<TestRunResult>此方法会发出 reporter.onWatcherRerun 和 onTestsRerun 事件,然后使用 runTestSpecifications 运行测试。如果主进程中没有错误,它将发出 reporter.onWatcherStart 事件。
runTestFiles 4.1.0+
function runTestFiles(
filepaths: string[],
allTestsRun = false
): Promise<TestRunResult>这会自动基于文件路径过滤器创建要运行的规范。
这与 start 不同,因为它不会创建覆盖率提供者,不会触发 onInit 和 onWatcherStart 事件,也不会在没有可运行文件时抛出错误(在这种情况下,函数将返回空数组而不触发测试运行)。
此函数接受与 start 和 CLI 相同的过滤器。
updateSnapshot
function updateSnapshot(files?: string[]): Promise<TestRunResult>更新指定文件中的快照。如果未提供文件,它将更新包含失败测试和过时快照的文件。
collectTests
function collectTests(
specifications: TestSpecification[]
): Promise<TestRunResult>执行测试文件而不运行测试回调。collectTests 返回未处理的错误和 测试模块 数组。
此方法的工作方式与 collect 完全相同,但你需要自己提供测试规范。
WARNING
请注意,Vitest 不使用静态分析来收集测试。Vitest 将像运行常规测试一样,隔离执行每个测试文件。这使得此方法非常慢,除非你在收集测试之前禁用了隔离。
cancelCurrentRun
function cancelCurrentRun(reason: CancelReason): Promise<void>此方法会优雅地取消所有正在进行的测试。它将停止当前正在运行的测试,并且不会运行已经计划但尚未开始的测试。
setGlobalTestNamePattern
function setGlobalTestNamePattern(pattern: string | RegExp): void此方法覆盖全局 测试名称模式。
WARNING
此方法不会开始运行任何测试。要使用更新后的模式运行测试,请调用 runTestSpecifications。
getGlobalTestNamePattern 4.0.0+
function getGlobalTestNamePattern(): RegExp | undefined返回用于全局测试名称模式的正则表达式。
resetGlobalTestNamePattern
function resetGlobalTestNamePattern(): void此方法重置 测试名称模式。这意味着 Vitest 现在不会跳过任何测试。
WARNING
此方法不会开始运行任何测试。要不带模式运行测试,请调用 runTestSpecifications。
启用快照更新
function enableSnapshotUpdate(): void启用允许在运行测试时更新快照的模式。调用此方法后运行的每个测试都将更新快照。要禁用该模式,请调用 resetSnapshotUpdate。
WARNING
此方法不会开始运行任何测试。要更新快照,请使用 runTestSpecifications 运行测试。
重置快照更新
function resetSnapshotUpdate(): void禁用允许在运行测试时更新快照的模式。此方法不会开始运行任何测试。
使文件失效
function invalidateFile(filepath: string): void此方法使每个项目缓存中的文件失效。如果你依赖自己的监视器(watcher),因为 Vite 的缓存持久存在于内存中,所以此方法最有用。
DANGER
如果你禁用了 Vitest 的监视器但保持 Vitest 运行,重要的是使用此方法手动清除缓存,因为无法禁用缓存。此方法还将使文件的导入者(importers)失效。
导入
function import<T>(moduleId: string): Promise<T>使用 Vite 模块运行器导入文件。该文件将由 Vite 使用全局配置进行转换,并在单独的上下文中执行。请注意,moduleId 将相对于 config.root。
DANGER
project.import 复用 Vite 的模块图,因此使用常规导入导入相同的模块将返回不同的模块:
import * as staticExample from './example.js'
const dynamicExample = await vitest.import('./example.js')
dynamicExample !== staticExample // ✅INFO
内部而言,Vitest 使用此方法导入全局设置、自定义覆盖率提供者和自定义报告器,这意味着只要它们属于同一个 Vite 服务器,它们都共享相同的模块图。
关闭
function close(): Promise<void>关闭所有项目及其关联资源。这只能调用一次;关闭承诺(promise)会被缓存直到服务器重启。
退出
function exit(force = false): Promise<void>关闭所有项目并退出进程。如果 force 设置为 true,进程将在关闭项目后立即退出。
此方法还将强制调用 process.exit(),如果进程在 config.teardownTimeout 毫秒后仍然处于活动状态。
是否保持服务器运行
function shouldKeepServer(): boolean如果测试完成后应保持服务器运行,此方法将返回 true。这通常意味着启用了 watch 模式。
服务器重启时的回调
function onServerRestart(fn: OnServerRestartHandler): void注册一个处理程序,当服务器因配置更改而重启时将调用该处理程序。
取消时的回调
function onCancel(fn: (reason: CancelReason) => Awaitable<void>): () => void注册一个处理程序,当使用 vitest.cancelCurrentRun 取消测试运行时将调用该处理程序。
自 4.0.10 起,onCancel 实验性地返回一个清理函数,该函数将移除监听器。自 4.1.0 起,此行为被视为稳定。
关闭时的回调
function onClose(fn: () => Awaitable<void>): void注册一个处理程序,当服务器关闭时将调用该处理程序。
测试重新运行时的回调
function onTestsRerun(fn: OnTestsRerunHandler): void注册一个处理程序,当测试重新运行时将调用该处理程序。当手动调用 rerunTestSpecifications 或文件更改且内置监视器计划重新运行时,测试可能会重新运行。
过滤被监视规范时的回调
function onFilterWatchedSpecification(
fn: (specification: TestSpecification) => boolean
): void注册一个处理程序,当文件更改时将调用该处理程序。此回调应返回 true 或 false,指示是否需要重新运行测试文件。
使用此方法,你可以挂钩到默认监视器逻辑中,以延迟或丢弃用户当前不想跟踪的测试:
const continuesTests: string[] = []
myCustomWrapper.onContinuesRunEnabled(testItem =>
continuesTests.push(item.fsPath)
)
vitest.onFilterWatchedSpecification(specification =>
continuesTests.includes(specification.moduleId)
)Vitest 可以根据 pool 或 locations 选项为同一文件创建不同的规范,因此不要依赖引用。Vitest 还可以从 vitest.getModuleSpecifications 返回缓存的规范 - 缓存基于 moduleId 和 pool。请注意,project.createSpecification 始终返回一个新实例。
匹配项目过滤器 3.1.0+
function matchesProjectFilter(name: string): boolean检查名称是否匹配当前的 项目过滤器。如果没有项目过滤器,这将始终返回 true。
无法以编程方式更改 --project CLI 选项。
等待测试运行结束 4.0.0+
function waitForTestRunEnd(): Promise<void>如果正在发生测试运行,返回一个将在测试运行完成时 resolve 的 Promise。
创建覆盖率提供者 4.0.0+
function createCoverageProvider(): Promise<CoverageProvider | null>如果配置中启用了 coverage,则创建一个覆盖率提供者。如果你使用 start 或 standalone 方法运行测试,这将自动完成。
WARNING
如果 coverage.clean 未设置为 false,此方法还将清除所有之前的报告。
启用覆盖率 4.0.0+
function enableCoverage(): Promise<void>此方法为此调用之后运行的测试启用覆盖率。enableCoverage 不运行任何测试;它仅设置 Vitest 以收集覆盖率。
如果尚不存在覆盖率提供者,它会创建一个新的。
禁用覆盖率 4.0.0+
function disableCoverage(): void此方法禁用之后运行的测试的覆盖率收集。
获取种子 4.0.0+
function getSeed(): number | null如果测试以随机顺序运行,返回种子值。
experimental_parseSpecification 4.0.0+ experimental
function experimental_parseSpecification(
specification: TestSpecification
): Promise<TestModule>此函数将收集文件内的所有测试而不运行它。它在 Vite 的 ssrTransform 之上使用 rollup 的 parseAst 函数来静态分析文件并收集所有能收集到的测试。
WARNING
如果 Vitest 无法分析测试名称,它将向测试或套件注入一个 dynamic: true 属性。id 还将带有 -dynamic 后缀,以免破坏正确收集的测试。
Vitest 总是在带有 for 或 each 修饰器的测试或具有动态名称的测试(例如,hello ${property} 或 'hello' + ${property})中注入此属性。Vitest 仍会为测试分配一个名称,但不能用于过滤测试。
Vitest 无法做到使过滤动态测试成为可能,但你可以使用 escapeTestName 函数将带有 for 或 each 修饰器的测试转换为名称模式:
import { escapeTestName } from 'vitest/node'
// 转换为 /hello, .+?/
const escapedPattern = new RegExp(escapeTestName('hello, %s', true))WARNING
Vitest 仅收集文件中定义的测试。它永远不会跟踪导入到其他文件。
Vitest 收集所有 it、test、suite 和 describe 定义,即使它们不是从 vitest 入口点导入的。
experimental_parseSpecifications 4.0.0+ experimental
function experimental_parseSpecifications(
specifications: TestSpecification[],
options?: {
concurrency?: number
}
): Promise<TestModule[]>此方法将从规范数组中 收集测试。默认情况下,Vitest 一次仅运行 os.availableParallelism() 数量的规范,以减少潜在的性能下降。你可以在第二个参数中指定不同的数字。
experimental_clearCache 4.0.11+ experimental
function experimental_clearCache(): Promise<void>删除所有 Vitest 缓存,包括 experimental.fsModuleCache。
experimental_getSourceModuleDiagnostic 4.0.15+ experimental
export function experimental_getSourceModuleDiagnostic(
moduleId: string,
testModule?: TestModule,
): Promise<SourceModuleDiagnostic>类型
export interface ModuleDefinitionLocation {
line: number
column: number
}
export interface SourceModuleLocations {
modules: ModuleDefinitionDiagnostic[]
untracked: ModuleDefinitionDiagnostic[]
}
export interface ModuleDefinitionDiagnostic {
start: ModuleDefinitionLocation
end: ModuleDefinitionLocation
startIndex: number
endIndex: number
url: string
resolvedId: string
}
export interface ModuleDefinitionDurationsDiagnostic extends ModuleDefinitionDiagnostic {
selfTime: number
totalTime: number
external?: boolean
}
export interface UntrackedModuleDefinitionDiagnostic {
url: string
resolvedId: string
selfTime: number
totalTime: number
external?: boolean
}
export interface SourceModuleDiagnostic {
modules: ModuleDefinitionDurationsDiagnostic[]
untrackedModules: UntrackedModuleDefinitionDiagnostic[]
}返回模块的诊断信息。如果未提供 testModule,selfTime 和 totalTime 将在上次运行的所有测试中聚合。如果模块未转换或执行,诊断信息将为空。
WARNING
目前,不支持 浏览器 模块。
创建报告 5.0.0+
function createReport(scope: string): Report创建一个仅限于给定作用域的报告。Report 遵循 Vitest 关于 将工件存储在文件系统上 的规则。
Report 提供了一组用于在文件系统上写入测试结果、临时文件和其他工件的实用工具。它尤其适用于自定义报告器之类的第三方集成。
Report 的所有操作都仅限于给定的 scope。单个报告不能干扰其他报告。在内部,Vitest 会创建 .vitest 目录,其中每个 scope 都会创建自己的目录。这种 .vitest 目录约定减少了最终用户需要在 .gitignore 中指定的条目数量。
import type { Report } from 'vitest/node'
const scope = 'example-yaml-reporter'
// 如果目录尚不存在,则自动创建 `<project-root>/.vitest/example-yaml-reporter/`
// 目录
const report: Report = vitest.createReport(scope)Report.root
const root: string此作用域的根目录。
const report = vitest.createReport('my-json-reporter')
// 是 <project-root>/.vitest/my-json-reporter
const root = report.rootReport.clean
function clean(): Promise<void>清理此作用域的报告目录。
const report = vitest.createReport('my-json-reporter')
// 删除 <project-root>/.vitest/my-json-reporter/ 内的所有内容
await report.clean()Report.writeFile
function writeFile(
filename: string,
content: string | Uint8Array,
encoding?: BufferEncoding
): Promise<void>将文件写入此作用域的报告目录。默认情况下,文件将使用 UTF-8 编码写入。文件名相对于作用域目录。
const report = vitest.createReport('my-json-reporter')
// 将文件写入 .vitest/my-json-reporter/test-report.json
await report.writeFile('test-report.json', JSON.stringify(results))Report.readFile
function readFile(filename: string, encoding?: BufferEncoding): Promise<string>从此作用域的报告目录中读取文件。
const report = vitest.createReport('my-json-reporter')
// 从 .vitest/my-json-reporter/test-report.json 读取文件
const content: string = await report.readFile('test-report.json')Report.readdir
function readdir(): Promise<string[]>读取此作用域的报告目录内容。
const report = vitest.createReport('my-json-reporter')
// 读取 .vitest/my-json-reporter 中的内容
const filenames: string[] = await report.readdir()Report.delete
function delete(filename: string): Promise<void>从此作用域的报告目录中删除文件。
const report = vitest.createReport('my-json-reporter')
// 删除 .vitest/my-json-reporter/test-report.json 中的文件
await report.delete('test-report.json')