Skip to content

测试项目 3.0.0+

WARNING

本指南描述了高级 Node.js API。如果你只是想定义项目,请遵循 "测试项目" 指南。

name

name 是用户分配或由 Vitest 解释的唯一字符串。如果用户没有提供 name,Vitest 会尝试加载项目根目录中的 package.json 并从中获取 name 属性。如果没有 package.json,Vitest 默认使用文件夹的 name。内联项目使用数字作为 name(转换为字符串)。

ts
import { createVitest } from 'vitest/node'

const vitest = await createVitest('test')
vitest.projects.map(p => p.name) === [
  '@pkg/server',
  'utils',
  '2',
  'custom'
]
ts
import { defineConfig } from 'vitest/config'

export default defineConfig({
  test: {
    projects: [
      './packages/server', // 拥有包含 "@pkg/server" 的 package.json
      './utils', // 没有 package.json 文件
      {
        // 没有自定义 name
        test: {
          pool: 'threads',
        },
      },
      {
        // 自定义了 name
        test: {
          name: 'custom',
        },
      },
    ],
  },
})

INFO

如果 根项目 不是用户项目的一部分,其 name 将不会被解析。

vitest

vitest 引用全局 Vitest 进程。

serializedConfig

这是测试进程接收的配置。Vitest 通过手动移除所有无法序列化的函数和属性来 序列化配置。由于该值在测试和 node 中都可用,其类型从主入口点导出。

ts
import type { SerializedConfig } from 'vitest'

const config: SerializedConfig = vitest.projects[0].serializedConfig

WARNING

serializedConfig 属性是一个 getter。每次访问它时,Vitest 都会再次序列化配置,以防它被更改。这也意味着它总是返回不同的引用:

ts
project.serializedConfig === project.serializedConfig // ❌

globalConfig

Vitest 初始化时的测试配置。如果这是 根项目globalConfigconfig 将引用同一个对象。此配置适用于无法在项目级别设置的值,如 coveragereporters

ts
import type { ResolvedConfig } from 'vitest/node'

vitest.config === vitest.projects[0].globalConfig

配置

这是项目的解析后测试配置。

hash 3.2.0+

此项目的唯一 hash。此值在重新运行之间保持一致。

它基于项目的根目录及其名称。请注意,根路径在不同操作系统之间不一致,因此 hash 也会不同。

vite

这是项目的 ViteDevServer。请注意,该服务器不一定专属于此项目:当 sharedViteServer 选项适用时,其他项目也可以复用它;同一集群中的浏览器实例共享一个浏览器服务器。

sharedViteServer

ts
const sharedViteServer: boolean

当项目复用声明该项目的配置所使用的 Vite 服务器,而不是解析自己的 Vite 服务器时为 true(参见 sharedViteServer 选项)。拥有该服务器的项目即使被其他项目复用,也会报告 false。要检测任意两个共享同一服务器的项目(包括浏览器实例),请比较它们的 vite 引用。

browser

仅当测试在浏览器中运行时才会设置此值。如果启用了 browser,但测试尚未运行,这将为 undefined。如果你需要检查项目是否支持浏览器测试,请使用 project.isBrowserEnabled() 方法。

WARNING

浏览器 API 更具实验性,且不遵循 SemVer。浏览器 API 将与其他 API 分开标准化。

provide

ts
function provide<T extends keyof ProvidedContext & string>(
  key: T,
  value: ProvidedContext[T],
): void

一种向测试提供自定义值的方法,除了 config.provide 字段之外。所有值在存储前都会使用 structuredClone 进行验证,但 providedContext 上的值本身不会被克隆。

ts
import { createVitest } from 'vitest/node'

const vitest = await createVitest('test')
const project = vitest.projects.find(p => p.name === 'custom')
project.provide('key', 'value')
await vitest.start()
ts
import { inject } from 'vitest'
const value = inject('key')

值可以动态提供。测试中提供的值将在下次运行时更新。

TIP

此方法也可用于 全局设置文件,适用于无法使用公共 API 的情况:

js
export default function setup({ provide }) {
  provide('wsPort', 3000)
}

getProvidedContext

ts
function getProvidedContext(): ProvidedContext

这返回上下文对象。每个项目也继承由 vitest.provide 设置的全局上下文。

ts
import { createVitest } from 'vitest/node'

const vitest = await createVitest('test')
vitest.provide('global', true)
const project = vitest.projects.find(p => p.name === 'custom')
project.provide('key', 'value')

// { global: true, key: 'value' }
const context = project.getProvidedContext()

TIP

项目上下文值将始终覆盖根项目的上下文。

createSpecification

ts
function createSpecification(
  moduleId: string,
  locations?: number[],
): TestSpecification

创建一个 测试规范,可用于 vitest.runTestSpecifications。规范将测试文件范围限定到特定的 project 和测试 locations(可选)。测试 locations 是源代码中定义测试的代码行。如果提供了 locations,Vitest 将只运行在这些行上定义的测试。请注意,如果定义了 testNamePattern,它也将被应用。

ts
import { createVitest } from 'vitest/node'
import { resolve } from 'node:path/posix'

const vitest = await createVitest('test')
const project = vitest.projects[0]
const specification = project.createSpecification(
  resolve('./example.test.ts'),
  [20, 40], // 可选的测试行
)
await vitest.runTestSpecifications([specification])

WARNING

createSpecification 期望解析后的 模块 ID。它不会自动解析文件或检查它是否存在于文件系统中。

还要注意 project.createSpecification 总是返回一个新实例。

isRootProject

ts
function isRootProject(): boolean

检查当前项目是否为根项目。你也可以通过调用 vitest.getRootProject() 获取根项目。

globTestFiles

ts
function globTestFiles(filters?: string[]): {
  /**
   * 匹配过滤器的测试文件。
   */
  testFiles: string[]
  /**
   * 匹配过滤器的类型检查测试文件。除非 `typecheck.enabled` 为 `true`,否则这将为空。
   */
  typecheckTestFiles: string[]
}

匹配所有测试文件。此函数返回一个包含常规测试和类型检查测试的对象。

此方法接受 filters。与 Vitest 实例上的其他方法不同,过滤器只能是文件路径的一部分:

js
project.globTestFiles(['foo']) // ✅
project.globTestFiles(['basic/foo.js:10']) // ❌

TIP

Vitest 使用 fast-glob 来查找测试文件。test.dirtest.rootrootprocess.cwd() 定义 cwd 选项。

此方法查看几个配置选项:

  • test.includetest.exclude 用于查找常规测试文件
  • test.includeSourcetest.exclude 用于查找源内测试
  • test.typecheck.includetest.typecheck.exclude 用于查找类型检查测试

matchesTestGlob

ts
function matchesTestGlob(
  moduleId: string,
  source?: () => string
): boolean

此方法检查文件是否为常规测试文件。它使用与 globTestFiles 相同的配置属性进行验证。

此方法还接受第二个参数,即源代码。这用于验证文件是否为源内测试。如果你为多个项目多次调用此方法,建议读取文件一次并直接传递下去。如果文件不是测试文件,但匹配 includeSource glob,除非提供了 source,否则 Vitest 将同步读取文件。

ts
import { createVitest } from 'vitest/node'
import { resolve } from 'node:path/posix'

const vitest = await createVitest('test')
const project = vitest.projects[0]

project.matchesTestGlob(resolve('./basic.test.ts')) // true
project.matchesTestGlob(resolve('./basic.ts')) // false
project.matchesTestGlob(resolve('./basic.ts'), () => `
if (import.meta.vitest) {
  // ...
}
`) // 如果设置了 `includeSource` 则为 true

import

ts
function import<T>(moduleId: string): Promise<T>

使用 Vite 模块运行器导入文件。文件将由 Vite 使用提供的项目配置进行转换,并在单独的上下文中执行。请注意 moduleId 将相对于 config.root

DANGER

project.import 复用 Vite 的模块图,因此使用常规导入导入相同的模块将返回不同的模块:

ts
import * as staticExample from './example.js'
const dynamicExample = await project.import('./example.js')

dynamicExample !== staticExample // ✅

INFO

内部而言,Vitest 使用此方法导入全局设置、自定义覆盖率提供程序和自定义报告器,意味着只要它们属于同一个 Vite 服务器,它们都共享相同的模块图。

onTestsRerun

ts
function onTestsRerun(cb: OnTestsRerunHandler): void

这是 project.vitest.onTestsRerun 的简写。它接受一个回调,当测试被计划重新运行时(通常是由于文件更改),该回调将被等待。

ts
project.onTestsRerun((specs) => {
  console.log(specs)
})

isBrowserEnabled

ts
function isBrowserEnabled(): boolean

如果此项目在浏览器中运行测试,则返回 true

关闭

ts
function close(): Promise<void>

关闭项目及其所有关联资源。此方法只能调用一次;关闭 Promise 会被缓存,直到服务器重启。如果需要再次使用这些资源,请创建一个新项目。

具体来说,此方法会关闭 Vite 服务器,停止类型检查服务,如果浏览器正在运行则关闭它,删除存放源代码的临时目录,并重置提供的上下文。