Skip to content
Vitest 3
Main Navigation Guida & APIConfigurazioneModalità BrowserAPI avanzata
3.2.0
2.1.9
1.6.1
0.34.6

Italiano

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Polski
Türkçe
čeština
magyar

Italiano

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Polski
Türkçe
čeština
magyar

Aspetto

Sidebar Navigation

Introduzione

Perché Vitest

Per Iniziare

Caratteristiche

Configurazione di Vitest

API

Riferimento API di test

Funzioni Mock

Vi

expect

expectTypeOf

assert

assertType

Guida

Interfaccia a Riga di Comando

Filtro dei Test

Progetti di Test

Reporter

Copertura

Snapshot

Mocking

Parallelismo

Tipi di Test

Vitest UI

Test nel Codice Sorgente

Contesto di Test

Annotazioni dei Test

Ambiente di Test

Estensione dei Matcher

Integrazioni IDE

Debugging

Errori Comuni

Guida alla Migrazione

Migrazione a Vitest 3.0

Migrazione da Jest

Prestazioni

Profilazione delle prestazioni dei test

Ottimizzare le Prestazioni

Modalità Browser

API Avanzate

Confronto con Altri Test Runner

In questa pagina

Contesto di Test ​

Ispirato dalle Playwright Fixtures, il contesto di test di Vitest consente di definire utilità, stati e fixture riutilizzabili all'interno dei test.

Utilizzo ​

Il primo argomento di ogni callback di test è il contesto di test.

ts
import { it } from 'vitest';

it('dovrebbe funzionare', ({ task }) => {
  // Stampa il nome del test.
  console.log(task.name);
});

Contesto di Test Predefinito ​

task ​

Un oggetto di sola lettura contenente metadati sul test.

expect ​

L'API expect associata al test corrente:

ts
import { it } from 'vitest';

it('la matematica è facile', ({ expect }) => {
  expect(2 + 2).toBe(4);
});

Questa API è utile per eseguire test snapshot in parallelo, poiché l'expect globale non è in grado di tracciarli correttamente:

ts
import { it } from 'vitest';

it.concurrent('la matematica è facile', ({ expect }) => {
  expect(2 + 2).toMatchInlineSnapshot();
});

it.concurrent('la matematica è difficile', ({ expect }) => {
  expect(2 * 2).toMatchInlineSnapshot();
});

skip ​

ts
function skip(note?: string): never;
function skip(condition: boolean, note?: string): void;

Salta l'esecuzione del test successivo e lo contrassegna come ignorato:

ts
import { expect, it } from 'vitest';

it('la matematica è difficile', ({ skip }) => {
  skip();
  expect(2 + 2).toBe(5);
});

A partire da Vitest 3.1, accetta un parametro booleano per saltare il test condizionalmente:

ts
it('la matematica è difficile', ({ skip, mind }) => {
  skip(mind === 'foggy');
  expect(2 + 2).toBe(5);
});

annotate 3.2.0+ ​

ts
function annotate(
  message: string,
  attachment?: TestAttachment
): Promise<TestAnnotation>;

function annotate(
  message: string,
  type?: string,
  attachment?: TestAttachment
): Promise<TestAnnotation>;

Aggiunge un'annotazione di test che verrà visualizzata dal tuo reporter.

ts
test('API delle annotazioni', async ({ annotate }) => {
  await annotate('https://github.com/vitest-dev/vitest/pull/7953', 'issues');
});

signal 3.2.0+ ​

Un AbortSignal che può essere interrotto da Vitest. Il segnale viene interrotto nelle seguenti situazioni:

  • Il test va in timeout.
  • L'utente ha annullato manualmente l'esecuzione del test con Ctrl+C.
  • vitest.cancelCurrentRun è stato invocato programmaticamente.
  • Un altro test è fallito in parallelo e il flag bail è impostato.
ts
it('interrompi la richiesta quando il test va in timeout', async ({ signal }) => {
  await fetch('/resource', { signal });
}, 2000);

onTestFailed ​

L'hook onTestFailed legato al test corrente. Questa API è utile quando si eseguono test in parallelo e si necessita di una gestione speciale solo per questo test specifico.

onTestFinished ​

L'hook onTestFinished legato al test corrente. Questa API è utile quando si eseguono test in parallelo e si necessita di una gestione speciale solo per questo test specifico.

Estendere il Contesto di Test ​

Vitest offre due modi per estendere il contesto di test.

test.extend ​

Similmente a Playwright, puoi usare questo metodo per definire la tua API test con fixture personalizzate e riutilizzarla ovunque.

Ad esempio, creiamo prima l'oggetto test con due fixture: todos e archive.

ts
import { test as baseTest } from 'vitest';

const todos = [];
const archive = [];

export const test = baseTest.extend({
  todos: async ({}, use) => {
    // Imposta la fixture prima di ogni funzione di test.
    todos.push(1, 2, 3);

    // Utilizza il valore della fixture.
    await use(todos);

    // Pulisci la fixture dopo ogni funzione di test.
    todos.length = 0;
  },
  archive,
});

Quindi possiamo importarlo e usarlo.

ts
import { expect } from 'vitest';
import { test } from './my-test.js';

test('aggiungi elementi a todos', ({ todos }) => {
  expect(todos.length).toBe(3);

  todos.push(4);
  expect(todos.length).toBe(4);
});

test('sposta elementi da todos ad archive', ({ todos, archive }) => {
  expect(todos.length).toBe(3);
  expect(archive.length).toBe(0);

  archive.push(todos.pop());
  expect(todos.length).toBe(2);
  expect(archive.length).toBe(1);
});

Possiamo anche aggiungere più fixture o sovrascrivere quelle esistenti estendendo il nostro test.

ts
import { test as todosTest } from './my-test.js';

export const test = todosTest.extend({
  settings: {
    // ...
  },
});

Inizializzazione delle Fixture ​

Il runner di Vitest inizializzerà automaticamente le tue fixture e le inietterà nel contesto di test in base all'utilizzo.

ts
import { test as baseTest } from 'vitest';

const test = baseTest.extend<{
  todos: number[];
  archive: number[];
}>({
  todos: async ({ task }, use) => {
    await use([1, 2, 3]);
  },
  archive: [],
});

// "todos" non verrà eseguito
test('salta', () => {});
test('salta', ({ archive }) => {});

// "todos" verrà eseguito
test('esegui', ({ todos }) => {});

WARNING

Quando si usa test.extend() con le fixture, si dovrebbe sempre usare la destrutturazione dell'oggetto { todos } per accedere al contesto sia nella funzione fixture che nella funzione test.

ts
test('context must be destructured', (context) => { 
  expect(context.todos.length).toBe(2)
})

test('context must be destructured', ({ todos }) => { 
  expect(todos.length).toBe(2)
})

Fixture Automatica ​

Vitest supporta anche la sintassi delle tuple per le fixture, permettendoti di passare opzioni per ogni fixture. Ad esempio, puoi usarla per inizializzare esplicitamente una fixture, anche se non viene usata nei test.

ts
import { test as base } from 'vitest';

const test = base.extend({
  fixture: [
    async ({}, use) => {
      // Questa funzione sarà eseguita.
      setup();
      await use();
      teardown();
    },
    { auto: true }, // Marca come fixture automatica.
  ],
});

test('funziona correttamente');

Fixture Predefinita ​

A partire da Vitest 3, puoi fornire valori diversi per diversi progetti. Per abilitare questa funzionalità, passa { injected: true } nelle opzioni. Se la chiave non è specificata nella configurazione del progetto, verrà utilizzato il valore predefinito.

ts
import { test as base } from 'vitest';

const test = base.extend({
  url: [
    // Valore predefinito se "url" non è definito nella configurazione.
    '/default',
    // Marca la fixture come "injected" per consentire l'override.
    { injected: true },
  ],
});

test('funziona correttamente', ({ url }) => {
  // url è "/default" in "project-new"
  // url è "/full" in "project-full"
  // url è "/empty" in "project-empty"
});
ts
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    projects: [
      {
        test: {
          name: 'project-new',
        },
      },
      {
        test: {
          name: 'project-full',
          provide: {
            url: '/full',
          },
        },
      },
      {
        test: {
          name: 'project-empty',
          provide: {
            url: '/empty',
          },
        },
      },
    ],
  },
});

Ambito dei Valori per Suite 3.1.0+ ​

Da Vitest 3.1, puoi sovrascrivere i valori del contesto per una suite e i suoi figli usando l'API test.scoped:

ts
import { test as baseTest, describe, expect } from 'vitest';

const test = baseTest.extend({
  dependency: 'default',
  dependant: ({ dependency }, use) => use({ dependency }),
});

describe('usa valori con ambito', () => {
  test.scoped({ dependency: 'new' });

  test('usa valore con ambito', ({ dependant }) => {
    // `dependant` usa il nuovo valore sovrascritto che ha un ambito definito
    // per tutti i test in questa suite.
    expect(dependant).toEqual({ dependency: 'new' });
  });

  describe('continua a usare il valore con ambito', () => {
    test('usa valore con ambito', ({ dependant }) => {
      // La suite nidificata ha ereditato il valore.
      expect(dependant).toEqual({ dependency: 'new' });
    });
  });
});

test('continua a usare i valori predefiniti', ({ dependant }) => {
  // La `dependency` sta usando il valore predefinito
  // al di fuori della suite con .scoped.
  expect(dependant).toEqual({ dependency: 'default' });
});

Questa API è particolarmente utile se hai un valore di contesto che dipende da una variabile dinamica, come una connessione al database:

ts
const test = baseTest.extend<{
  db: Database;
  schema: string;
}>({
  db: async ({ schema }, use) => {
    const db = await createDb({ schema });
    await use(db);
    await cleanup(db);
  },
  schema: '',
});

describe('un tipo di schema', () => {
  test.scoped({ schema: 'schema-1' });

  // ... test
});

describe('un altro tipo di schema', () => {
  test.scoped({ schema: 'schema-2' });

  // ... test
});

Contesto per Ambito 3.2.0+ ​

Puoi definire un contesto che verrà inizializzato una volta per file o per worker. Viene inizializzato allo stesso modo di una normale fixture con un parametro oggetto:

ts
import { test as baseTest } from 'vitest';

export const test = baseTest.extend({
  perFile: [({}, { use }) => use([]), { scope: 'file' }],
  perWorker: [({}, { use }) => use([]), { scope: 'worker' }],
});

Il valore viene inizializzato la prima volta che un test vi accede, a meno che le opzioni della fixture non abbiano auto: true - in questo caso il valore viene inizializzato prima che qualsiasi test venga eseguito.

ts
const test = baseTest.extend({
  perFile: [
    ({}, { use }) => use([]),
    {
      scope: 'file',
      // Esegui sempre questo hook prima di qualsiasi test.
      auto: true,
    },
  ],
});

Lo scope worker eseguirà la fixture una volta per worker. Il numero di worker attivi dipende da vari fattori. Per impostazione predefinita, ogni file viene eseguito in un worker separato, quindi gli scope file e worker funzionano allo stesso modo.

Tuttavia, se disabiliti l'isolamento, il numero di worker è limitato dalla configurazione maxWorkers o poolOptions.

Nota che specificare scope: 'worker' quando si eseguono test in vmThreads o vmForks avrà lo stesso effetto di specificare scope: 'file'. Questa limitazione esiste perché ogni file di test ha il proprio contesto VM, quindi se Vitest dovesse inizializzarlo una volta, un contesto potrebbe fuoriuscire in un altro e creare molte inconsistenze di riferimento (ad esempio, le istanze della stessa classe farebbero riferimento a costruttori diversi).

TypeScript ​

Per fornire i tipi di fixture per tutti i tuoi contesti personalizzati, puoi passare il tipo di fixture come generico.

ts
interface MyFixtures {
  todos: number[];
  archive: number[];
}

const test = baseTest.extend<MyFixtures>({
  todos: [],
  archive: [],
});

test('i tipi sono definiti correttamente', ({ todos, archive }) => {
  expectTypeOf(todos).toEqualTypeOf<number[]>();
  expectTypeOf(archive).toEqualTypeOf<number[]>();
});

Inferenza dei Tipi

Nota che Vitest non supporta l'inferenza dei tipi quando la funzione use viene chiamata. È sempre preferibile passare l'intero tipo di contesto come tipo generico quando test.extend viene chiamato:

ts
import { test as baseTest } from 'vitest';

const test = baseTest.extend<{
  todos: number[];
  schema: string;
}>({
  todos: ({ schema }, use) => use([]),
  schema: 'test',
});

test('i tipi sono corretti', ({
  todos, // number[]
  schema, // string
}) => {
  // ...
});

beforeEach e afterEach ​

Deprecato

Questo è un modo obsoleto di estendere il contesto e non funzionerà quando test viene esteso con test.extend.

I contesti sono diversi per ogni test. Puoi accedervi ed estenderli all'interno degli hook beforeEach e afterEach.

ts
import { beforeEach, it } from 'vitest';

beforeEach(async context => {
  // Estendi il contesto.
  context.foo = 'bar';
});

it('dovrebbe funzionare', ({ foo }) => {
  console.log(foo); // 'bar'
});

TypeScript ​

Per fornire i tipi di proprietà per tutti i tuoi contesti personalizzati, puoi estendere il tipo TestContext aggiungendo:

ts
declare module 'vitest' {
  export interface TestContext {
    foo?: string;
  }
}

Se vuoi fornire i tipi di proprietà solo per specifici hook beforeEach, afterEach, it e test, puoi passare il tipo come generico.

ts
interface LocalTestContext {
  foo: string;
}

beforeEach<LocalTestContext>(async context => {
  // typeof context è 'TestContext & LocalTestContext'
  context.foo = 'bar';
});

it<LocalTestContext>('dovrebbe funzionare', ({ foo }) => {
  // typeof foo è 'string'
  console.log(foo); // 'bar'
});
Pager
Pagina precedenteTest nel Codice Sorgente
Pagina successivaAnnotazioni dei Test

Rilasciato sotto la licenza MIT.

Copyright (c) 2021-Present Vitest Team

https://vitest.dev/guide/test-context

Rilasciato sotto la licenza MIT.

Copyright (c) 2021-Present Vitest Team