扩展默认报告器
WARNING
这是高级 API。如果你只想要 运行测试,你可能不需要这个。它主要被库的作者使用。
你可以从 vitest/reporters 导入报告器并扩展它们以创建你的自定义报告器。
扩展内置报告器
一般来说,你不需要从头开始创建报告器。vitest 附带了几个可以扩展的默认报告程序。
ts
import { DefaultReporter } from 'vitest/reporters'
export default class MyDefaultReporter extends DefaultReporter {
// do something
}当然,你可以从头开始创建报告器。只需扩展 BaseReporter 类并实现你需要的方法即可。
这是自定义报告器的示例:
ts
import { BaseReporter } from 'vitest/reporters'
export default class CustomReporter extends BaseReporter {
onCollected() {
const files = this.ctx.state.getFiles(this.watchFilters)
this.reportTestSummary(files)
}
}或者实现 Reporter 接口:
ts
import { Reporter } from 'vitest/reporters'
export default class CustomReporter implements Reporter {
onCollected() {
// print something
}
}然后你可以在 vitest.config.ts 文件中使用自定义报告器:
ts
import { defineConfig } from 'vitest/config'
import CustomReporter from './custom-reporter.js'
export default defineConfig({
test: {
reporters: [new CustomReporter()],
},
})报告的任务
WARNING
这是一个试验性 API。破坏性更改可能不会跟进 SemVer。使用时请使用 Vitest 的版本。
你可以通过调用 vitest.state.getReportedEntity(runnerTask) 访问此 API:
ts
import type { } from 'vitest/node'
import type { } from 'vitest'
import type { , } from 'vitest/reporters'
class implements {
!:
(: ) {
this. =
}
(: []) {
for (const of ) {
// 请注意,旧的任务实现使用 “文件” 而不是 “模块”
const = this...() as
for (const of .children) {
.('finished', .type, .fullName)
}
}
}
}TestCase
TestCase 代表一次测试.
ts
declare class TestCase {
readonly type = 'test' | 'custom'
/**
* Task instance.
* @experimental Public task API 是试验性的,并不遵循 semver
*/
readonly task: RunnerTestCase | RunnerCustomCase
/**
* 与测试相关的项目
*/
readonly project: TestProject
/**
* 直接引用定义测试的测试文件
*/
readonly module: TestModule
/**
* 测试名称。
*/
readonly name: string
/**
* 测试的全名,包括用 `>` 分隔的所有父套件
*/
readonly fullName: string
/**
* 唯一标识符
* 该 ID 是确定的,多次运行时同一测试的 ID 将是相同的
* ID 基于项目名称、文件路径和测试位置
*/
readonly id: string
/**
* 文件中定义测试的位置
* 只有在配置中启用 `includeTaskLocation` 时,才会收集位置信息
*/
readonly location: { line: number, column: number } | undefined
/**
* 如果测试是在文件中直接调用的,则父套件将是文件
*/
readonly parent: TestSuite | TestModule
/**
* 启动测试时使用的选项
*/
readonly options: TaskOptions
/**
* 检查测试是否没有失败
* 如果测试尚未完成或被跳过,则返回 `true`
*/
ok(): boolean
/**
* 执行测试时附加到测试中的自定义元数据
*/
meta(): TaskMeta
/**
* 测试结果。如果测试尚未完成或刚刚收集,则将为`undefined`
*/
result(): TestResult | undefined
/**
* 有关测试的有用信息,如持续时间、内存使用情况等
*/
diagnostic(): TestDiagnostic | undefined
}
export type TestResult = TestResultPassed | TestResultFailed | TestResultSkipped
export interface TestResultPassed {
/**
* 测试已成功通过。
*/
state: 'passed'
/**
* 测试执行过程中出现的错误
*
* **Note**: 如果测试重试成功,仍会报告错误
*/
errors: TestError[] | undefined
}
export interface TestResultFailed {
/**
* 测试执行失败
*/
state: 'failed'
/**
* 测试执行过程中出现的错误
*/
errors: TestError[]
}
export interface TestResultSkipped {
/**
* 使用`only`、`skip` 或 `todo` 标志跳过测试
* 你可以在 `mode` 选项中看到使用的是哪一种
*/
state: 'skipped'
/**
* 跳过的测试没有错误
*/
errors: undefined
}
export interface TestDiagnostic {
/**
* 如果测试的持续时间高于 `slowTestThreshold`
*/
slow: boolean
/**
* 测试使用的内存量(字节)
* 只有使用 `logHeapUsage` 标志执行测试时,该值才可用。
*/
heap: number | undefined
/**
* 执行测试所需的时间(毫秒)
*/
duration: number
/**
* 测试开始的时间(毫秒)
*/
startTime: number
/**
* 测试重试的次数
*/
retryCount: number
/**
* 重复测试的次数,由 `repeats` 选项设置
* 如果测试在重复过程中失败,且未配置 `retry`,则该值可以更小
*/
repeatCount: number
/**
* 如果第二次重试时测试通过
*/
flaky: boolean
}TestSuite
TestSuite 表示包含测试和其他套件的单一套件。
ts
declare class TestSuite {
readonly type = 'suite'
/**
* 任务实例
* @experimental 公共任务 API 是实验性的,并不遵循 semver
*/
readonly task: RunnerTestSuite
/**
* 与测试相关的项目
*/
readonly project: TestProject
/**
* 直接引用定义套件的测试文件
*/
readonly module: TestModule
/**
* 测试套件名称
*/
readonly name: string
/**
* 套件的全名,包括用 `>` 分隔的所有父套件。
*/
readonly fullName: string
/**
* 唯一标识符
* 该 ID 是确定的,多次运行时同一测试的 ID 将是相同的
* ID 基于项目名称、文件路径和测试位置
*/
readonly id: string
/**
* 文件中定义套件的位置
* 只有在配置中启用 `includeTaskLocation` 时,才会收集位置信息
*/
readonly location: { line: number, column: number } | undefined
/**
* 套件和属于该套件的测试的集合
*/
readonly children: TaskCollection
/**
* 启动套件时使用的选项
*/
readonly options: TaskOptions
}TestModule
TestModule 表示包含套件和测试的单个文件。
ts
declare class TestModule extends SuiteImplementation {
readonly type = 'module'
/**
* 任务实例
* @experimental 公共任务 API 是实验性的,并不遵循 semver
*/
readonly task: RunnerTestFile
/**
* 属于该文件的套件和测试集合
*/
readonly children: TestCollection
/**
* 这通常是一个绝对的 Unix 文件路径。
* 如果文件不在磁盘上,它可以是一个虚拟 ID
* 该值对应于 Vite 的 `ModuleGraph` id
*/
readonly moduleId: string
/**
* 有关文件的有用信息,如持续时间、内存使用情况等。
* 如果文件尚未执行,所有诊断值都将返回 `0`。
*/
diagnostic(): ModuleDiagnostic
}
export interface ModuleDiagnostic {
/**
* 导入和启动环境所需的时间
*/
environmentSetupDuration: number
/**
* Vitest 设置测试工具(运行程序、模拟等)所需的时间
*/
prepareDuration: number
/**
* 导入测试文件所需的时间
* 这包括导入文件中的所有内容和执行套件回调
*/
collectDuration: number
/**
* 导入设置文件所需的时间
*/
setupDuration: number
/**
* 文件中所有测试和钩子的累计持续时间
*/
duration: number
}TestCollection
TestCollection 表示套件和测试的集合。它还提供了迭代自身的有用方法。
ts
declare class TestCollection {
/**
* 返回数组中特定索引处的测试或套件
*/
at(index: number): TestCase | TestSuite | undefined
/**
* 集合中测试和套件的数量
*/
size: number
/**
* 以数组形式返回集合,以便于操作
*/
array(): (TestCase | TestSuite)[]
/**
* 过滤属于此集合及其子集合的所有套件
*/
allSuites(): IterableIterator<TestSuite>
/**
* 过滤属于此集合及其子集合的所有测试
*/
allTests(state?: TestResult['state'] | 'running'): IterableIterator<TestCase>
/**
* 只筛选属于该集合的测试
*/
tests(state?: TestResult['state'] | 'running'): IterableIterator<TestCase>
/**
* 仅筛选属于该系列的套件
*/
suites(): IterableIterator<TestSuite>;
[Symbol.iterator](): IterableIterator<TestSuite | TestCase>
}例如,你可以通过调用 testFile.children.allTests() 遍历文件中的所有测试:
ts
function onFileCollected(testModule: TestModule): void {
console.log('collecting tests in', testModule.moduleId)
// 遍历模块中的所有测试用例和测试套件
for (const task of testModule.children.allTests()) {
console.log('collected', task.type, task.fullName)
}
}TestProject
TestProject 是与模块关联的项目。该模块内的每个测试和测试套件都会引用同一个项目。
项目可用于获取配置或提供的上下文。
ts
declare class TestProject {
/**
* 全局 vitest 实例
* @experimental Vitest 公共 API 目前处于实验阶段,并不遵循 semver
*/
readonly vitest: Vitest
/**
* 该测试项目关联的工作区
* @experimental Vitest 公共 API 目前处于实验阶段,并不遵循 semver
*/
readonly workspaceProject: WorkspaceProject
/**
* Vite 开发服务器实例。每个工作区都有其独立的开发服务器实例
*/
readonly vite: ViteDevServer
/**
* 已解析的项目配置
*/
readonly config: ResolvedProjectConfig
/**
* 已解析的全局配置。若不存在工作区项目,则该配置将与 `config` 相同
*/
readonly globalConfig: ResolvedConfig
/**
* 序列化的项目配置。这是测试接收到的配置
*/
get serializedConfig(): SerializedConfig
/**
* 项目名称,未设置时返回空字符串
*/
name(): string
/**
* 提供给项目的自定义上下文
*/
context(): ProvidedContext
/**
* 为项目提供可序列化的自定义上下文。该上下文将在测试运行时可用
*/
provide<T extends keyof ProvidedContext & string>(key: T, value: ProvidedContext[T]): void
}导出报告器
vitest 附带了一些 内置报告器 ,可以开箱即用。
内置报告器:
BasicReporterDefaultReporterDotReporterJsonReporterVerboseReporterTapReporterJUnitReporterTapFlatReporterHangingProcessReporter
基础抽象报告器:
BaseReporter
报告器接口: #interface-reporters
Reporter