Rozszerzanie Reporterów
Możesz importować reporterów z vitest/reporters
i rozszerzać je, aby tworzyć własne reportery.
Rozszerzanie Wbudowanych Reporterów
Zazwyczaj nie ma potrzeby tworzenia reportera od zera. vitest
udostępnia kilka domyślnych reporterów, które można rozszerzyć.
import { DefaultReporter } from 'vitest/reporters';
export default class MyDefaultReporter extends DefaultReporter {
// wykonaj coś
}
Oczywiście, możesz również stworzyć własnego reportera od podstaw. Wystarczy rozszerzyć klasę BaseReporter
i zaimplementować wymagane metody.
Poniżej przykład niestandardowego reportera:
// ./custom-reporter.js
import { BaseReporter } from 'vitest/reporters';
export default class CustomReporter extends BaseReporter {
onCollected() {
const files = this.ctx.state.getFiles(this.watchFilters);
this.reportTestSummary(files);
}
}
Alternatywnie, możesz zaimplementować interfejs Reporter
:
// ./custom-reporter.js
import { Reporter } from 'vitest/reporters';
export default class CustomReporter implements Reporter {
onCollected() {
// wyświetl coś
}
}
Następnie możesz użyć swojego niestandardowego reportera w pliku vitest.config.ts
:
import { defineConfig } from 'vitest/config';
import CustomReporter from './custom-reporter.js';
export default defineConfig({
test: {
reporters: [new CustomReporter()],
},
});
Zgłoszone Zadania
WARNING
To jest eksperymentalne API. Zmiany mogą nie być zgodne z SemVer. Prosimy o przypięcie wersji Vitest podczas korzystania z niego.
Możesz uzyskać dostęp do tego API, wywołując vitest.state.getReportedEntity(runnerTask)
:
import type { Vitest } from 'vitest/node';
import type { RunnerTestFile } from 'vitest';
import type { Reporter, TestModule } from 'vitest/reporters';
class MyReporter implements Reporter {
ctx!: Vitest;
onInit(ctx: Vitest) {
this.ctx = ctx;
}
onFinished(files: RunnerTestFile[]) {
for (const fileTask of files) {
// zauważ, że stara implementacja zadania używa "file" zamiast "module"
const testModule = this.ctx.state.getReportedEntity(
fileTask
) as TestModule;
for (const task of testModule.children) {
// ^?
console.log('finished', task.type, task.fullName);
}
}
}
}
Planujemy ustabilizować to API w Vitest 2.1.
TestCase
TestCase
reprezentuje pojedynczy test.
declare class TestCase {
readonly type = 'test' | 'custom';
/**
* Instancja zadania.
* @experimental Publiczne API zadań jest eksperymentalne i nie jest zgodne z semver.
*/
readonly task: RunnerTestCase | RunnerCustomCase;
/**
* Projekt powiązany z testem.
*/
readonly project: TestProject;
/**
* Bezpośrednie odniesienie do modułu testowego, w którym zdefiniowano test.
*/
readonly module: TestModule;
/**
* Nazwa testu.
*/
readonly name: string;
/**
* Pełna nazwa testu, w tym wszystkie nadrzędne zestawy oddzielone znakiem `>`.
*/
readonly fullName: string;
/**
* Unikalny identyfikator.
* Ten identyfikator jest deterministyczny i będzie taki sam dla tego samego testu w wielu przebiegach.
* Identyfikator jest oparty na nazwie projektu, identyfikatorze modułu i pozycji testu.
*/
readonly id: string;
/**
* Lokalizacja w module, w której zdefiniowano test.
* Lokalizacje są zbierane tylko wtedy, gdy w konfiguracji włączono `includeTaskLocation`.
*/
readonly location: { line: number; column: number } | undefined;
/**
* Nadrzędny zestaw. Jeśli test został wywołany bezpośrednio w module, rodzicem będzie sam moduł.
*/
readonly parent: TestSuite | TestModule;
/**
* Opcje, z którymi zainicjowano test.
*/
readonly options: TaskOptions;
/**
* Sprawdza, czy test nie spowodował niepowodzenia zestawu.
* Jeśli test jeszcze się nie zakończył lub został pominięty, zwróci `true`.
*/
ok(): boolean;
/**
* Niestandardowe metadane, które zostały dołączone do testu podczas jego wykonywania.
*/
meta(): TaskMeta;
/**
* Wyniki testu. Będą `undefined`, jeśli test jeszcze się nie zakończył lub został dopiero zebrany.
*/
result(): TestResult | undefined;
/**
* Przydatne informacje o teście, takie jak czas trwania, zużycie pamięci itp.
*/
diagnostic(): TestDiagnostic | undefined;
}
export type TestResult =
| TestResultPassed
| TestResultFailed
| TestResultSkipped;
export interface TestResultPassed {
/**
* Test zakończył się pomyślnie.
*/
state: 'passed';
/**
* Błędy, które wystąpiły podczas wykonywania testu.
*
* **Uwaga**: Jeśli test został pomyślnie ponowiony, błędy nadal będą zgłaszane.
*/
errors: TestError[] | undefined;
}
export interface TestResultFailed {
/**
* Test nie powiódł się.
*/
state: 'failed';
/**
* Błędy, które wystąpiły podczas wykonywania testu.
*/
errors: TestError[];
}
export interface TestResultSkipped {
/**
* Test został pominięty z flagą `only`, `skip` lub `todo`.
* Możesz zobaczyć, która z nich została użyta w opcji `mode`.
*/
state: 'skipped';
/**
* Pomięte testy nie mają błędów.
*/
errors: undefined;
}
export interface TestDiagnostic {
/**
* Jeśli czas trwania testu przekracza `slowTestThreshold`.
*/
slow: boolean;
/**
* Ilość pamięci użytej przez test w bajtach.
* Ta wartość jest dostępna tylko wtedy, gdy test został wykonany z flagą `logHeapUsage`.
*/
heap: number | undefined;
/**
* Czas potrzebny na wykonanie testu w ms.
*/
duration: number;
/**
* Czas w ms, kiedy test się rozpoczął.
*/
startTime: number;
/**
* Ilość razy, gdy test został ponowiony.
*/
retryCount: number;
/**
* Ilość razy, gdy test został powtórzony zgodnie z konfiguracją opcji `repeats`.
* Ta wartość może być niższa, jeśli test nie powiódł się podczas powtórzenia i nie skonfigurowano `retry`.
*/
repeatCount: number;
/**
* Jeśli test przeszedł przy drugiej próbie.
*/
flaky: boolean;
}
TestSuite
TestSuite
reprezentuje pojedynczy zestaw, który zawiera testy i inne zestawy.
declare class TestSuite {
readonly type = 'suite';
/**
* Instancja zadania.
* @experimental Publiczne API zadań jest eksperymentalne i nie jest zgodne z semver.
*/
readonly task: RunnerTestSuite;
/**
* Projekt powiązany z testem.
*/
readonly project: TestProject;
/**
* Bezpośrednie odniesienie do modułu testowego, w którym zdefiniowano zestaw.
*/
readonly module: TestModule;
/**
* Nazwa zestawu.
*/
readonly name: string;
/**
* Pełna nazwa zestawu, w tym wszystkie nadrzędne zestawy oddzielone znakiem `>`.
*/
readonly fullName: string;
/**
* Unikalny identyfikator.
* Ten identyfikator jest deterministyczny i będzie taki sam dla tego samego testu w wielu przebiegach.
* Identyfikator jest oparty na nazwie projektu, identyfikatorze modułu i pozycji testu.
*/
readonly id: string;
/**
* Lokalizacja w module, w której zdefiniowano zestaw.
* Lokalizacje są zbierane tylko wtedy, gdy w konfiguracji włączono `includeTaskLocation`.
*/
readonly location: { line: number; column: number } | undefined;
/**
* Kolekcja zestawów i testów, które są częścią tego zestawu.
*/
readonly children: TaskCollection;
/**
* Opcje, z którymi zainicjowano zestaw.
*/
readonly options: TaskOptions;
}
TestModule
TestModule
reprezentuje pojedynczy plik, który zawiera zestawy i testy.
declare class TestModule extends SuiteImplementation {
readonly type = 'module';
/**
* Instancja zadania.
* @experimental Publiczne API zadań jest eksperymentalne i nie jest zgodne z semver.
*/
readonly task: RunnerTestFile;
/**
* Kolekcja zestawów i testów, które są częścią tego modułu.
*/
readonly children: TestCollection;
/**
* Zazwyczaj jest to bezwzględna ścieżka pliku Unix.
* Może to być wirtualny identyfikator, jeśli plik nie znajduje się na dysku.
* Ta wartość odpowiada identyfikatorowi `ModuleGraph` z Vite.
*/
readonly moduleId: string;
/**
* Przydatne informacje o module, takie jak czas trwania, zużycie pamięci itp.
* Jeśli moduł nie został jeszcze wykonany, wszystkie wartości diagnostyczne zwrócą `0`.
*/
diagnostic(): ModuleDiagnostic;
}
export interface ModuleDiagnostic {
/**
* Czas potrzebny na zaimportowanie i zainicjowanie środowiska.
*/
environmentSetupDuration: number;
/**
* Czas potrzebny Vitest na skonfigurowanie uprzęży testowej (runner, mocki itp.).
*/
prepareDuration: number;
/**
* Czas potrzebny na zaimportowanie modułu testowego.
* Obejmuje to importowanie wszystkiego w module i wykonywanie wywołań zwrotnych zestawu.
*/
collectDuration: number;
/**
* Czas potrzebny na zaimportowanie modułu konfiguracyjnego.
*/
setupDuration: number;
/**
* Skumulowany czas trwania wszystkich testów i hooków w module.
*/
duration: number;
}
TestCollection
TestCollection
reprezentuje kolekcję zestawów i testów. Udostępnia również przydatne metody do iteracji po sobie.
declare class TestCollection {
/**
* Zwraca test lub zestaw o określonym indeksie w tablicy.
*/
at(index: number): TestCase | TestSuite | undefined;
/**
* Liczba testów i zestawów w kolekcji.
*/
size: number;
/**
* Zwraca kolekcję w formie tablicy dla łatwiejszej manipulacji.
*/
array(): (TestCase | TestSuite)[];
/**
* Filtruje wszystkie zestawy, które są częścią tej kolekcji i jej dzieci.
*/
allSuites(): IterableIterator<TestSuite>;
/**
* Filtruje wszystkie testy, które są częścią tej kolekcji i jej dzieci.
*/
allTests(state?: TestResult['state'] | 'running'): IterableIterator<TestCase>;
/**
* Filtruje tylko testy, które są częścią tej kolekcji.
*/
tests(state?: TestResult['state'] | 'running'): IterableIterator<TestCase>;
/**
* Filtruje tylko zestawy, które są częścią tej kolekcji.
*/
suites(): IterableIterator<TestSuite>;
[Symbol.iterator](): IterableIterator<TestSuite | TestCase>;
}
Na przykład, możesz iterować po wszystkich testach w module, wywołując testModule.children.allTests()
:
function onFileCollected(testModule: TestModule): void {
console.log('collecting tests in', testModule.moduleId);
// iteruj po wszystkich testach i zestawach w module
for (const task of testModule.children.allTests()) {
console.log('collected', task.type, task.fullName);
}
}
TestProject
TestProject
to projekt powiązany z modułem. Każdy test i zestaw w tym module będzie odwoływał się do tego samego projektu.
Projekt jest przydatny do uzyskania konfiguracji lub dostarczonego kontekstu.
declare class TestProject {
/**
* Globalna instancja vitest.
* @experimental Publiczne API Vitest jest eksperymentalne i nie jest zgodne z semver.
*/
readonly vitest: Vitest;
/**
* Projekt obszaru roboczego, z którym powiązany jest ten projekt testowy.
* @experimental Publiczne API Vitest jest eksperymentalne i nie jest zgodne z semver.
*/
readonly workspaceProject: WorkspaceProject;
/**
* Instancja serwera deweloperskiego Vite. Każdy projekt obszaru roboczego ma swój własny serwer.
*/
readonly vite: ViteDevServer;
/**
* Rozwiązana konfiguracja projektu.
*/
readonly config: ResolvedProjectConfig;
/**
* Rozwiązana konfiguracja globalna. Jeśli nie ma projektów obszaru roboczego, będzie taka sama jak `config`.
*/
readonly globalConfig: ResolvedConfig;
/**
* Zserializowana konfiguracja projektu. Jest to konfiguracja, którą otrzymują testy.
*/
get serializedConfig(): SerializedConfig;
/**
* Nazwa projektu lub pusty ciąg, jeśli nie ustawiono.
*/
name(): string;
/**
* Niestandardowy kontekst dostarczony do projektu.
*/
context(): ProvidedContext;
/**
* Dostarcz niestandardowy serializowalny kontekst do projektu. Ten kontekst będzie dostępny dla testów po ich uruchomieniu.
*/
provide<T extends keyof ProvidedContext & string>(
key: T,
value: ProvidedContext[T]
): void;
}
Eksportowane Reportery
vitest
zawiera kilka wbudowanych reporterów, których możesz używać od razu.
Wbudowane reportery:
BasicReporter
DefaultReporter
DotReporter
JsonReporter
VerboseReporter
TapReporter
JUnitReporter
TapFlatReporter
HangingProcessReporter
Abstrakcyjne reportery bazowe:
BaseReporter
Reportery interfejsowe:
Reporter