Estensione dei Reporter
Puoi importare i reporter da vitest/reporters
ed estenderli per creare i tuoi reporter personalizzati.
Estensione dei Reporter Integrati
In generale, non è necessario creare il tuo reporter da zero. vitest
include diversi reporter predefiniti che puoi estendere.
import { DefaultReporter } from 'vitest/reporters';
export default class MyDefaultReporter extends DefaultReporter {
// implementa la logica necessaria
}
Naturalmente, puoi creare il tuo reporter da zero. Basta estendere la classe BaseReporter
e implementare i metodi di cui hai bisogno.
Ed ecco un esempio di un reporter personalizzato:
// ./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);
}
}
Oppure implementare l'interfaccia Reporter
:
// ./custom-reporter.js
import { Reporter } from 'vitest/reporters';
export default class CustomReporter implements Reporter {
onCollected() {
// visualizza qualcosa
}
}
Quindi puoi usare il tuo reporter personalizzato nel file vitest.config.ts
:
import { defineConfig } from 'vitest/config';
import CustomReporter from './custom-reporter.js';
export default defineConfig({
test: {
reporters: [new CustomReporter()],
},
});
Task Riportati
WARNING
Questa è un'API sperimentale. Le modifiche che introducono interruzioni potrebbero non seguire SemVer. Si consiglia di bloccare la versione di Vitest quando la si utilizza.
È possibile accedere a questa API chiamando 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) {
// nota: la vecchia implementazione del task usa "file" invece di "module"
const testModule = this.ctx.state.getReportedEntity(
fileTask
) as TestModule;
for (const task of testModule.children) {
// ^?
console.log('finished', task.type, task.fullName);
}
}
}
}
Stiamo pianificando di stabilizzare questa API in Vitest 2.1.
TestCase
TestCase
rappresenta un singolo test.
declare class TestCase {
readonly type = 'test' | 'custom';
/**
* Istanza del task.
* @experimental L'API pubblica dei task è sperimentale e non segue SemVer.
*/
readonly task: RunnerTestCase | RunnerCustomCase;
/**
* Il progetto associato al test.
*/
readonly project: TestProject;
/**
* Riferimento diretto al modulo di test in cui è definito il test.
*/
readonly module: TestModule;
/**
* Nome del test.
*/
readonly name: string;
/**
* Nome completo del test, inclusi tutti i suite padre, separati da `>`.
*/
readonly fullName: string;
/**
* Identificatore univoco.
* Questo ID è deterministico e sarà lo stesso per lo stesso test in esecuzioni multiple.
* L'ID si basa sul nome del progetto, sull'ID del modulo e sulla posizione del test.
*/
readonly id: string;
/**
* Posizione nel modulo in cui è stato definito il test.
* Le posizioni vengono raccolte solo se `includeTaskLocation` è abilitato nella configurazione.
*/
readonly location: { line: number; column: number } | undefined;
/**
* Suite padre. Se il test è stato chiamato direttamente all'interno del modulo, il padre sarà il modulo stesso.
*/
readonly parent: TestSuite | TestModule;
/**
* Opzioni con cui è stato avviato il test.
*/
readonly options: TaskOptions;
/**
* Verifica se il test non è fallito.
* Se il test non è ancora finito o è stato saltato, restituirà `true`.
*/
ok(): boolean;
/**
* Metadati personalizzati allegati al test durante la sua esecuzione.
*/
meta(): TaskMeta;
/**
* Risultati del test. Sarà `undefined` se il test non è ancora terminato o è stato appena raccolto.
*/
result(): TestResult | undefined;
/**
* Informazioni utili sul test, come durata, utilizzo della memoria, ecc.
*/
diagnostic(): TestDiagnostic | undefined;
}
export type TestResult =
| TestResultPassed
| TestResultFailed
| TestResultSkipped;
export interface TestResultPassed {
/**
* Il test è passato con successo.
*/
state: 'passed';
/**
* Errori che sono stati lanciati durante l'esecuzione del test.
*
* **Nota**: Se il test è stato ritentato con successo, gli errori verranno comunque riportati.
*/
errors: TestError[] | undefined;
}
export interface TestResultFailed {
/**
* Il test è fallito.
*/
state: 'failed';
/**
* Errori che sono stati lanciati durante l'esecuzione del test.
*/
errors: TestError[];
}
export interface TestResultSkipped {
/**
* Il test è stato saltato con il flag `only`, `skip` o `todo`.
* Puoi vedere quale è stato usato nell'opzione `mode`.
*/
state: 'skipped';
/**
* I test saltati non presentano errori.
*/
errors: undefined;
}
export interface TestDiagnostic {
/**
* Indica se la durata del test è superiore a `slowTestThreshold`.
*/
slow: boolean;
/**
* La quantità di memoria utilizzata dal test, in byte.
* Questo valore è disponibile solo se il test è stato eseguito con il flag `logHeapUsage`.
*/
heap: number | undefined;
/**
* Il tempo impiegato per eseguire il test, in ms.
*/
duration: number;
/**
* Il tempo, in ms, in cui il test è iniziato.
*/
startTime: number;
/**
* Il numero di volte in cui il test è stato ritentato.
*/
retryCount: number;
/**
* Il numero di volte in cui il test è stato ripetuto, come configurato dall'opzione `repeats`.
* Questo valore può essere inferiore se il test è fallito durante la ripetizione e non è configurato alcun `retry`.
*/
repeatCount: number;
/**
* Indica se il test è passato al secondo tentativo.
*/
flaky: boolean;
}
TestSuite
TestSuite
rappresenta una singola suite che contiene test e altre suite.
declare class TestSuite {
readonly type = 'suite';
/**
* Istanza del task.
* @experimental L'API pubblica dei task è sperimentale e non segue SemVer.
*/
readonly task: RunnerTestSuite;
/**
* Il progetto associato al test.
*/
readonly project: TestProject;
/**
* Riferimento diretto al modulo di test in cui è definita la suite.
*/
readonly module: TestModule;
/**
* Nome della suite.
*/
readonly name: string;
/**
* Nome completo della suite, inclusi tutti i suite padre, separati da `>`.
*/
readonly fullName: string;
/**
* Identificatore univoco.
* Questo ID è deterministico e sarà lo stesso per lo stesso test in esecuzioni multiple.
* L'ID si basa sul nome del progetto, sull'ID del modulo e sulla posizione del test.
*/
readonly id: string;
/**
* Posizione nel modulo in cui è stata definita la suite.
* Le posizioni vengono raccolte solo se `includeTaskLocation` è abilitato nella configurazione.
*/
readonly location: { line: number; column: number } | undefined;
/**
* Collezione di suite e test che fanno parte di questa suite.
*/
readonly children: TaskCollection;
/**
* Opzioni con cui è stata avviata la suite.
*/
readonly options: TaskOptions;
}
TestModule
TestModule
rappresenta un singolo file che contiene suite e test.
declare class TestModule extends SuiteImplementation {
readonly type = 'module';
/**
* Istanza del task.
* @experimental L'API pubblica dei task è sperimentale e non segue SemVer.
*/
readonly task: RunnerTestFile;
/**
* Collezione di suite e test che fanno parte di questo modulo.
*/
readonly children: TestCollection;
/**
* Questo è solitamente un percorso di file Unix assoluto.
* Può essere un ID virtuale se il file non è sul disco.
* Questo valore corrisponde all'ID `ModuleGraph` di Vite.
*/
readonly moduleId: string;
/**
* Informazioni utili sul modulo, come durata, utilizzo della memoria, ecc.
* Se il modulo non è ancora stato eseguito, tutti i valori diagnostici restituiranno `0`.
*/
diagnostic(): ModuleDiagnostic;
}
export interface ModuleDiagnostic {
/**
* Il tempo impiegato per importare e avviare un ambiente.
*/
environmentSetupDuration: number;
/**
* Il tempo impiegato da Vitest per configurare l'ambiente di test (runner, mock, ecc.).
*/
prepareDuration: number;
/**
* Il tempo impiegato per importare il modulo di test.
* Questo include l'importazione di tutto nel modulo e l'esecuzione dei callback delle suite.
*/
collectDuration: number;
/**
* Il tempo impiegato per importare il modulo di setup.
*/
setupDuration: number;
/**
* Durata accumulata di tutti i test e gli hook nel modulo.
*/
duration: number;
}
TestCollection
TestCollection
rappresenta una collezione di suite e test. Fornisce anche metodi utili per iterare su se stessa.
declare class TestCollection {
/**
* Restituisce il test o la suite a un indice specifico nell'array.
*/
at(index: number): TestCase | TestSuite | undefined;
/**
* Il numero di test e suite nella collezione.
*/
size: number;
/**
* Restituisce la collezione in forma di array per una manipolazione più semplice.
*/
array(): (TestCase | TestSuite)[];
/**
* Filtra tutte le suite che fanno parte di questa collezione e dei suoi figli.
*/
allSuites(): IterableIterator<TestSuite>;
/**
* Filtra tutti i test che fanno parte di questa collezione e dei suoi figli.
*/
allTests(state?: TestResult['state'] | 'running'): IterableIterator<TestCase>;
/**
* Filtra solo i test che fanno parte di questa collezione.
*/
tests(state?: TestResult['state'] | 'running'): IterableIterator<TestCase>;
/**
* Filtra solo le suite che fanno parte di questa collezione.
*/
suites(): IterableIterator<TestSuite>;
[Symbol.iterator](): IterableIterator<TestSuite | TestCase>;
}
Ad esempio, puoi iterare su tutti i test all'interno di un modulo utilizzando testModule.children.allTests()
:
function onFileCollected(testModule: TestModule): void {
console.log('collecting tests in', testModule.moduleId);
// itera su tutti i test e le suite nel modulo
for (const task of testModule.children.allTests()) {
console.log('collected', task.type, task.fullName);
}
}
TestProject
TestProject
è un progetto associato al modulo. Ogni test e suite all'interno di quel modulo farà riferimento allo stesso progetto.
Il progetto è utile per ottenere la configurazione o il contesto fornito.
declare class TestProject {
/**
* L'istanza globale di vitest.
* @experimental L'API pubblica di Vitest è sperimentale e non segue SemVer.
*/
readonly vitest: Vitest;
/**
* Il progetto workspace a cui è associato questo progetto di test.
* @experimental L'API pubblica di Vitest è sperimentale e non segue SemVer.
*/
readonly workspaceProject: WorkspaceProject;
/**
* Istanza del server di sviluppo di Vite. Ogni progetto workspace ha il proprio server.
*/
readonly vite: ViteDevServer;
/**
* Configurazione del progetto risolta.
*/
readonly config: ResolvedProjectConfig;
/**
* Configurazione globale risolta. Se non ci sono progetti workspace, sarà uguale a `config`.
*/
readonly globalConfig: ResolvedConfig;
/**
* Configurazione del progetto serializzata. Questa è la configurazione che i test ricevono.
*/
get serializedConfig(): SerializedConfig;
/**
* Il nome del progetto o una stringa vuota se non impostato.
*/
name(): string;
/**
* Contesto personalizzato fornito al progetto.
*/
context(): ProvidedContext;
/**
* Fornisce un contesto serializzabile personalizzato al progetto. Questo contesto sarà disponibile per i test una volta eseguiti.
*/
provide<T extends keyof ProvidedContext & string>(
key: T,
value: ProvidedContext[T]
): void;
}
Reporter Esportati
vitest
include alcuni reporter integrati che puoi utilizzare subito.
Reporter integrati:
BasicReporter
DefaultReporter
DotReporter
JsonReporter
VerboseReporter
TapReporter
JUnitReporter
TapFlatReporter
HangingProcessReporter
Reporter astratti di base:
BaseReporter
Reporter di interfaccia:
Reporter