Estendendo Reporters
Você pode importar reporters de vitest/reporters
e estendê-los para criar seus reporters personalizados.
Estendendo Reporters Integrados
Em geral, você não precisa criar seu reporter do zero. O vitest
vem com vários reporters padrão que você pode estender.
import { DefaultReporter } from 'vitest/reporters';
export default class MyDefaultReporter extends DefaultReporter {
// implemente algo
}
Claro, você pode criar seu reporter do zero. Basta estender a classe BaseReporter
e implementar os métodos que você precisa.
E aqui está um exemplo de um reporter personalizado:
// ./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);
}
}
Ou implemente a interface Reporter
:
// ./custom-reporter.js
import { Reporter } from 'vitest/reporters';
export default class CustomReporter implements Reporter {
onCollected() {
// exiba algo
}
}
Então você pode usar seu reporter personalizado no arquivo vitest.config.ts
:
import { defineConfig } from 'vitest/config';
import CustomReporter from './custom-reporter.js';
export default defineConfig({
test: {
reporters: [new CustomReporter()],
},
});
Tarefas Reportadas
WARNING
Esta é uma API experimental. Mudanças significativas podem não seguir o SemVer. Por favor, fixe a versão do Vitest ao usá-la.
Você pode ter acesso a esta API chamando 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) {
// note que a implementação antiga da tarefa usa "file" em vez de "module"
const testModule = this.ctx.state.getReportedEntity(
fileTask
) as TestModule;
for (const task of testModule.children) {
// ^?
console.log('finished', task.type, task.fullName);
}
}
}
}
Estamos planejando estabilizar esta API no Vitest 2.1.
TestCase
TestCase
representa um único teste.
declare class TestCase {
readonly type = 'test' | 'custom';
/**
* Instância da tarefa.
* @experimental A API pública de tarefas é experimental e não segue o SemVer.
*/
readonly task: RunnerTestCase | RunnerCustomCase;
/**
* O projeto associado ao teste.
*/
readonly project: TestProject;
/**
* Referência direta ao módulo de teste onde o teste é definido.
*/
readonly module: TestModule;
/**
* Nome do teste.
*/
readonly name: string;
/**
* Nome completo do teste, incluindo todas as suítes pai separadas por `>`.
*/
readonly fullName: string;
/**
* Identificador único.
* Este ID é determinístico e será o mesmo para o mesmo teste em várias execuções.
* O ID é baseado no nome do projeto, ID do módulo e posição do teste.
*/
readonly id: string;
/**
* Localização no módulo onde o teste foi definido.
* As localizações são coletadas apenas se `includeTaskLocation` estiver habilitado na configuração.
*/
readonly location: { line: number; column: number } | undefined;
/**
* Suíte pai. Se o teste foi chamado diretamente dentro do módulo, o pai será o próprio módulo.
*/
readonly parent: TestSuite | TestModule;
/**
* Opções com as quais o teste foi iniciado.
*/
readonly options: TaskOptions;
/**
* Verifica se o teste não falhou na suíte.
* Se o teste ainda não terminou ou foi ignorado, retornará `true`.
*/
ok(): boolean;
/**
* Metadados personalizados que foram anexados ao teste durante sua execução.
*/
meta(): TaskMeta;
/**
* Resultados do teste. Será `undefined` se o teste ainda não terminou ou foi apenas coletado.
*/
result(): TestResult | undefined;
/**
* Informações úteis sobre o teste, como duração, uso de memória, etc.
*/
diagnostic(): TestDiagnostic | undefined;
}
export type TestResult =
| TestResultPassed
| TestResultFailed
| TestResultSkipped;
export interface TestResultPassed {
/**
* O teste passou com sucesso.
*/
state: 'passed';
/**
* Erros que foram lançados durante a execução do teste.
*
* **Nota**: Se o teste foi retentado com sucesso, os erros ainda serão reportados.
*/
errors: TestError[] | undefined;
}
export interface TestResultFailed {
/**
* O teste falhou ao executar.
*/
state: 'failed';
/**
* Erros que foram lançados durante a execução do teste.
*/
errors: TestError[];
}
export interface TestResultSkipped {
/**
* O teste foi ignorado com a flag `only`, `skip` ou `todo`.
* Você pode ver qual foi usada na opção `mode`.
*/
state: 'skipped';
/**
* Testes ignorados não têm erros.
*/
errors: undefined;
}
export interface TestDiagnostic {
/**
* Se a duração do teste estiver acima de `slowTestThreshold`.
*/
slow: boolean;
/**
* A quantidade de memória usada pelo teste em bytes.
* Este valor está disponível apenas se o teste foi executado com a flag `logHeapUsage`.
*/
heap: number | undefined;
/**
* O tempo que leva para executar o teste em ms.
*/
duration: number;
/**
* O tempo em ms em que o teste começou.
*/
startTime: number;
/**
* A quantidade de vezes que o teste foi retentado.
*/
retryCount: number;
/**
* A quantidade de vezes que o teste foi repetido conforme configurado pela opção `repeats`.
* Este valor pode ser menor se o teste falhou durante a repetição e nenhum `retry` estiver configurado.
*/
repeatCount: number;
/**
* Se o teste passou em uma segunda tentativa.
*/
flaky: boolean;
}
TestSuite
TestSuite
representa uma única suíte que contém testes e outras suítes.
declare class TestSuite {
readonly type = 'suite';
/**
* Instância da tarefa.
* @experimental A API pública de tarefas é experimental e não segue o SemVer.
*/
readonly task: RunnerTestSuite;
/**
* O projeto associado ao teste.
*/
readonly project: TestProject;
/**
* Referência direta ao módulo de teste onde a suíte é definida.
*/
readonly module: TestModule;
/**
* Nome da suíte.
*/
readonly name: string;
/**
* Nome completo da suíte, incluindo todas as suítes pai separadas por `>`.
*/
readonly fullName: string;
/**
* Identificador único.
* Este ID é determinístico e será o mesmo para o mesmo teste em várias execuções.
* O ID é baseado no nome do projeto, ID do módulo e posição do teste.
*/
readonly id: string;
/**
* Localização no módulo onde a suíte foi definida.
* As localizações são coletadas apenas se `includeTaskLocation` estiver habilitado na configuração.
*/
readonly location: { line: number; column: number } | undefined;
/**
* Coleção de suítes e testes que fazem parte desta suíte.
*/
readonly children: TaskCollection;
/**
* Opções com as quais a suíte foi iniciada.
*/
readonly options: TaskOptions;
}
TestModule
TestModule
representa um único arquivo que contém suítes e testes.
declare class TestModule extends SuiteImplementation {
readonly type = 'module';
/**
* Instância da tarefa.
* @experimental A API pública de tarefas é experimental e não segue o SemVer.
*/
readonly task: RunnerTestFile;
/**
* Coleção de suítes e testes que fazem parte deste módulo.
*/
readonly children: TestCollection;
/**
* Geralmente é um caminho de arquivo Unix absoluto.
* Pode ser um ID virtual se o arquivo não estiver no disco.
* Este valor corresponde ao ID do `ModuleGraph` do Vite.
*/
readonly moduleId: string;
/**
* Informações úteis sobre o módulo, como duração, uso de memória, etc.
* Se o módulo ainda não foi executado, todos os valores de diagnóstico retornarão `0`.
*/
diagnostic(): ModuleDiagnostic;
}
export interface ModuleDiagnostic {
/**
* O tempo que leva para importar e iniciar um ambiente.
*/
environmentSetupDuration: number;
/**
* O tempo que leva para o Vitest configurar o ambiente de teste (runner, mocks, etc.).
*/
prepareDuration: number;
/**
* O tempo que leva para importar o módulo de teste.
* Isso inclui importar tudo no módulo e executar os callbacks da suíte.
*/
collectDuration: number;
/**
* O tempo que leva para importar o módulo de configuração.
*/
setupDuration: number;
/**
* Duração acumulada de todos os testes e hooks no módulo.
*/
duration: number;
}
TestCollection
TestCollection
representa uma coleção de suítes e testes. Também fornece métodos úteis para iterar sobre si mesma.
declare class TestCollection {
/**
* Retorna o teste ou a suíte em um índice específico do array.
*/
at(index: number): TestCase | TestSuite | undefined;
/**
* A quantidade de testes e suítes na coleção.
*/
size: number;
/**
* Retorna a coleção em formato de array para facilitar a manipulação.
*/
array(): (TestCase | TestSuite)[];
/**
* Filtra todas as suítes que pertencem a esta coleção e seus filhos.
*/
allSuites(): IterableIterator<TestSuite>;
/**
* Filtra todos os testes que fazem parte desta coleção e seus filhos.
*/
allTests(state?: TestResult['state'] | 'running'): IterableIterator<TestCase>;
/**
* Filtra apenas os testes que fazem parte desta coleção.
*/
tests(state?: TestResult['state'] | 'running'): IterableIterator<TestCase>;
/**
* Filtra apenas as suítes que fazem parte desta coleção.
*/
suites(): IterableIterator<TestSuite>;
[Symbol.iterator](): IterableIterator<TestSuite | TestCase>;
}
Por exemplo, você pode iterar sobre todos os testes dentro de um módulo chamando testModule.children.allTests()
:
function onFileCollected(testModule: TestModule): void {
console.log('collecting tests in', testModule.moduleId);
// itera sobre todos os testes e suítes no módulo
for (const task of testModule.children.allTests()) {
console.log('collected', task.type, task.fullName);
}
}
TestProject
TestProject
é um projeto associado ao módulo. Cada teste e suíte dentro desse módulo fará referência ao mesmo projeto.
O projeto é útil para obter a configuração ou o contexto fornecido.
declare class TestProject {
/**
* A instância global do Vitest.
* @experimental A API pública do Vitest é experimental e não segue o SemVer.
*/
readonly vitest: Vitest;
/**
* O projeto do workspace com o qual este projeto de teste está associado.
* @experimental A API pública do Vitest é experimental e não segue o SemVer.
*/
readonly workspaceProject: WorkspaceProject;
/**
* Instância do servidor de desenvolvimento do Vite. Cada projeto do workspace tem seu próprio servidor.
*/
readonly vite: ViteDevServer;
/**
* Configuração do projeto resolvida.
*/
readonly config: ResolvedProjectConfig;
/**
* Configuração global resolvida. Se não houver projetos de workspace, será o mesmo que `config`.
*/
readonly globalConfig: ResolvedConfig;
/**
* Configuração serializada do projeto. Esta é a configuração que os testes recebem.
*/
get serializedConfig(): SerializedConfig;
/**
* O nome do projeto ou uma string vazia se não estiver definido.
*/
name(): string;
/**
* Contexto personalizado fornecido ao projeto.
*/
context(): ProvidedContext;
/**
* Fornece um contexto serializável personalizado ao projeto. Este contexto estará disponível para os testes assim que forem executados.
*/
provide<T extends keyof ProvidedContext & string>(
key: T,
value: ProvidedContext[T]
): void;
}
Reporters Exportados
O vitest
vem com alguns reporters integrados que você pode usar imediatamente.
Reporters integrados:
BasicReporter
DefaultReporter
DotReporter
JsonReporter
VerboseReporter
TapReporter
JUnitReporter
TapFlatReporter
HangingProcessReporter
Reporters Abstratos Base:
BaseReporter
Reporters de Interface:
Reporter