Référence de l'API des Tests
Les types suivants sont utilisés dans les signatures de type ci-dessous :
type Awaitable<T> = T | PromiseLike<T>;
type TestFunction = () => Awaitable<void>;
interface TestOptions {
/**
* Le test échouera si son exécution dépasse le temps imparti.
*/
timeout?: number;
/**
* Retentera le test un nombre spécifique de fois s'il échoue.
*
* @default 0
*/
retry?: number;
/**
* Répétera le même test plusieurs fois, même s'il échoue à chaque fois.
* Si l'option "retry" est activée et que le test échoue, chaque tentative sera utilisée à chaque cycle.
* Utile pour déboguer les défaillances aléatoires.
*
* @default 0
*/
repeats?: number;
}Lorsqu'une fonction de test renvoie une promesse, le runner attendra sa résolution pour collecter les attentes asynchrones. Si la promesse est rejetée, le test échouera.
TIP
Dans Jest, TestFunction peut aussi être de type (done: DoneCallback) => void. Si cette forme est utilisée, le test ne se terminera pas tant que done n'aura pas été appelé. Vous pouvez obtenir le même résultat en utilisant une fonction async. Voir la section Migration guide Done Callback pour plus d'informations.
Vous pouvez définir des options en chaînant des propriétés à une fonction :
import { test } from 'vitest';
test.skip('skipped test', () => {
// some logic that fails right now
});
test.concurrent.skip('skipped concurrent test', () => {
// some logic that fails right now
});Vous pouvez également fournir un objet comme deuxième argument :
import { test } from 'vitest';
test('skipped test', { skip: true }, () => {
// some logic that fails right now
});
test('skipped concurrent test', { skip: true, concurrent: true }, () => {
// some logic that fails right now
});Les deux méthodes fonctionnent exactement de la même manière. Le choix de l'une ou de l'autre est purement stylistique.
Notez que si vous fournissez le délai d'attente comme dernier argument, vous ne pouvez plus utiliser les options :
import { test } from 'vitest';
// ✅ cela fonctionne
test.skip('heavy test', () => {
// ...
}, 10_000);
// ❌ cela ne fonctionne pas
test(
'heavy test',
{ skip: true },
() => {
// ...
},
10_000
);Cependant, vous pouvez fournir un délai d'attente à l'intérieur de l'objet d'options :
import { test } from 'vitest';
// ✅ cela fonctionne
test('heavy test', { skip: true, timeout: 10_000 }, () => {
// ...
});test
- Alias :
it
test définit un ensemble d'attentes associées. Il prend en paramètres le nom du test et une fonction contenant les attentes à vérifier.
Optionnellement, vous pouvez spécifier un délai d'attente (en millisecondes) pour définir la durée maximale avant l'arrêt. La valeur par défaut est de 5 secondes et peut être configurée globalement avec testTimeout.
import { expect, test } from 'vitest';
test('should work as expected', () => {
expect(Math.sqrt(4)).toBe(2);
});test.extend
- Alias :
it.extend
Utilisez test.extend pour étendre le contexte de test avec des fixtures personnalisées. Cela renverra un nouveau test qui est également extensible, vous permettant ainsi de composer davantage de fixtures ou de remplacer celles existantes en l'étendant selon vos besoins. Voir Étendre le contexte de test pour plus d'informations.
import { expect, test } from 'vitest';
const todos = [];
const archive = [];
const myTest = test.extend({
todos: async ({ task }, use) => {
todos.push(1, 2, 3);
await use(todos);
todos.length = 0;
},
archive,
});
myTest('add item', ({ todos }) => {
expect(todos.length).toBe(3);
todos.push(4);
expect(todos.length).toBe(4);
});test.skip
- Alias :
it.skip
Si vous souhaitez ignorer l'exécution de certains tests sans supprimer leur code, vous pouvez utiliser test.skip pour les empêcher de s'exécuter.
import { assert, test } from 'vitest';
test.skip('skipped test', () => {
// Test ignoré, pas d'erreur
assert.equal(Math.sqrt(4), 3);
});Vous pouvez également ignorer un test en appelant skip sur son contexte dynamiquement :
import { assert, test } from 'vitest';
test('skipped test', context => {
context.skip();
// Test ignoré, pas d'erreur
assert.equal(Math.sqrt(4), 3);
});Depuis Vitest 3.1, si la condition est inconnue, vous pouvez la fournir à la méthode skip comme premier argument :
import { assert, test } from 'vitest';
test('skipped test', context => {
context.skip(Math.random() < 0.5, 'optional message');
// Test ignoré, pas d'erreur
assert.equal(Math.sqrt(4), 3);
});test.skipIf
- Alias :
it.skipIf
Dans certains cas, vous pouvez être amené à exécuter des tests plusieurs fois dans des environnements différents, et certains tests pourraient être spécifiques à l'environnement. Au lieu d'envelopper le code de test avec une condition if, vous pouvez utiliser test.skipIf pour ignorer le test si la condition est vraie.
import { assert, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
test.skipIf(isDev)('prod only test', () => {
// ce test ne s'exécute qu'en production
});WARNING
Vous ne pouvez pas utiliser cette syntaxe lorsque vous utilisez Vitest comme vérificateur de type.
test.runIf
- Alias :
it.runIf
L'opposé de test.skipIf.
import { assert, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
test.runIf(isDev)('dev only test', () => {
// ce test ne s'exécute qu'en développement
});WARNING
Vous ne pouvez pas utiliser cette syntaxe lorsque vous utilisez Vitest comme vérificateur de type.
test.only
- Alias :
it.only
Utilisez test.only pour n'exécuter que certains tests dans une suite donnée. C'est utile lors du débogage.
Optionnellement, vous pouvez fournir un délai d'attente (en millisecondes) pour spécifier combien de temps attendre avant de terminer. La valeur par défaut est de 5 secondes et peut être configurée globalement avec testTimeout.
import { assert, test } from 'vitest';
test.only('test', () => {
// Seul ce test (et les autres marqués avec only) sont exécutés
assert.equal(Math.sqrt(4), 2);
});Il est parfois très utile d'exécuter des tests only dans un certain fichier, en ignorant tous les autres tests de l'ensemble de la suite de tests, afin de ne pas surcharger la sortie.
Pour ce faire, exécutez vitest avec le fichier contenant les tests concernés.
# vitest interesting.test.tstest.concurrent
- Alias :
it.concurrent
test.concurrent indique que les tests consécutifs doivent être exécutés en parallèle. Il prend en paramètres le nom du test, une fonction asynchrone contenant les tests à exécuter, et un délai d'attente optionnel (en millisecondes).
import { describe, test } from 'vitest';
// Les deux tests marqués comme concurrents seront exécutés en parallèle
describe('suite', () => {
test('serial test', async () => {
/* ... */
});
test.concurrent('concurrent test 1', async () => {
/* ... */
});
test.concurrent('concurrent test 2', async () => {
/* ... */
});
});test.skip, test.only et test.todo fonctionnent avec les tests concurrents. Toutes les combinaisons suivantes sont valides :
test.concurrent(/* ... */);
test.skip.concurrent(/* ... */); // ou test.concurrent.skip(/* ... */)
test.only.concurrent(/* ... */); // ou test.concurrent.only(/* ... */)
test.todo.concurrent(/* ... */); // ou test.concurrent.todo(/* ... */)Lors de l'exécution de tests concurrents, les instantanés (Snapshots) et les assertions doivent utiliser expect du Contexte de Test local pour s'assurer que le bon test est détecté.
test.concurrent('test 1', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
test.concurrent('test 2', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});WARNING
Vous ne pouvez pas utiliser cette syntaxe lorsque vous utilisez Vitest comme vérificateur de type.
test.sequential
- Alias :
it.sequential
test.sequential marque un test comme séquentiel. C'est utile si vous voulez exécuter des tests en séquence au sein de describe.concurrent ou avec l'option de commande --sequence.concurrent.
import { describe, test } from 'vitest';
// avec l'option de configuration { sequence: { concurrent: true } }
test('concurrent test 1', async () => {
/* ... */
});
test('concurrent test 2', async () => {
/* ... */
});
test.sequential('sequential test 1', async () => {
/* ... */
});
test.sequential('sequential test 2', async () => {
/* ... */
});
// dans une suite concurrente
describe.concurrent('suite', () => {
test('concurrent test 1', async () => {
/* ... */
});
test('concurrent test 2', async () => {
/* ... */
});
test.sequential('sequential test 1', async () => {
/* ... */
});
test.sequential('sequential test 2', async () => {
/* ... */
});
});test.todo
- Alias :
it.todo
Utilisez test.todo pour marquer des tests à implémenter plus tard. Ces tests apparaîtront dans le rapport, vous indiquant ainsi le nombre de tests qu'il vous reste à implémenter.
// Une entrée sera affichée dans le rapport pour ce test
test.todo('unimplemented test');test.fails
- Alias :
it.fails
Utilisez test.fails pour indiquer qu'une assertion échouera explicitement.
import { expect, test } from 'vitest';
function myAsyncFunc() {
return new Promise(resolve => resolve(1));
}
test.fails('fail test', async () => {
await expect(myAsyncFunc()).rejects.toBe(1);
});WARNING
Vous ne pouvez pas utiliser cette syntaxe lorsque vous utilisez Vitest comme vérificateur de type.
test.each
- Alias :
it.each
TIP
Bien que test.each soit fourni pour la compatibilité Jest, Vitest dispose également de test.for qui offre une fonctionnalité supplémentaire pour l'intégration de TestContext.
Utilisez test.each lorsque vous avez besoin d'exécuter le même test avec des variables différentes. Vous pouvez injecter des paramètres en utilisant le formatage printf dans le nom du test, en respectant l'ordre des paramètres de la fonction de test.
%s: chaîne de caractères%d: nombre%i: entier%f: valeur à virgule flottante%j: json%o: objet%#: index de cas de test basé sur 0%$: index de cas de test basé sur 1%%: un seul signe pourcentage ('%')
import { expect, test } from 'vitest';
test.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', (a, b, expected) => {
expect(a + b).toBe(expected);
});
// cela retournera
// ✓ add(1, 1) -> 2
// ✓ add(1, 2) -> 3
// ✓ add(2, 1) -> 3Vous pouvez également accéder aux propriétés d'objet et aux éléments de tableau avec le préfixe $:
test.each([
{ a: 1, b: 1, expected: 2 },
{ a: 1, b: 2, expected: 3 },
{ a: 2, b: 1, expected: 3 },
])('add($a, $b) -> $expected', ({ a, b, expected }) => {
expect(a + b).toBe(expected);
});
// cela retournera
// ✓ add(1, 1) -> 2
// ✓ add(1, 2) -> 3
// ✓ add(2, 1) -> 3
test.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add($0, $1) -> $2', (a, b, expected) => {
expect(a + b).toBe(expected);
});
// cela retournera
// ✓ add(1, 1) -> 2
// ✓ add(1, 2) -> 3
// ✓ add(2, 1) -> 3Vous pouvez également accéder aux attributs d'objet avec ., si vous utilisez des objets comme arguments :
test.each`
a | b | expected
${{ val: 1 }} | ${'b'} | ${'1b'}
${{ val: 2 }} | ${'b'} | ${'2b'}
${{ val: 3 }} | ${'b'} | ${'3b'}
`('add($a.val, $b) -> $expected', ({ a, b, expected }) => {
expect(a.val + b).toBe(expected);
});
// cela retournera
// ✓ add(1, b) -> 1b
// ✓ add(2, b) -> 2b
// ✓ add(3, b) -> 3bÀ partir de Vitest 0.25.3, vous pouvez également utiliser une table de chaînes de caractères de modèle.
- La première ligne doit contenir les noms de colonnes, séparés par
|; - Une ou plusieurs lignes de données suivantes fournies sous forme d'expressions littérales de modèle utilisant la syntaxe
${value}.
import { expect, test } from 'vitest';
test.each`
a | b | expected
${1} | ${1} | ${2}
${'a'} | ${'b'} | ${'ab'}
${[]} | ${'b'} | ${'b'}
${{}} | ${'b'} | ${'[object Object]b'}
${{ asd: 1 }} | ${'b'} | ${'[object Object]b'}
`('returns $expected when $a is added $b', ({ a, b, expected }) => {
expect(a + b).toBe(expected);
});TIP
Vitest traite les $values avec la méthode format de Chai. Si la valeur est trop tronquée, vous pouvez augmenter chaiConfig.truncateThreshold dans votre fichier de configuration.
WARNING
Vous ne pouvez pas utiliser cette syntaxe lorsque vous utilisez Vitest comme vérificateur de type.
test.for
- Alias :
it.for
Alternative à test.each permettant de fournir TestContext.
La différence avec test.each réside dans la manière dont les tableaux sont fournis dans les arguments. Les arguments non-tableau de test.for (y compris l'utilisation de chaînes de caractères de modèle) fonctionnent exactement de la même manière que pour test.each.
// `each` déstructure les tableaux
test.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', (a, b, expected) => {
expect(a + b).toBe(expected);
});
// `for` ne déstructure pas les tableaux (notez les crochets autour des arguments)
test.for([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', ([a, b, expected]) => {
expect(a + b).toBe(expected);
});Le 2ème argument est TestContext et peut être utilisé pour les instantanés concurrents, par exemple :
test.concurrent.for([
[1, 1],
[1, 2],
[2, 1],
])('add(%i, %i)', ([a, b], { expect }) => {
expect(a + b).matchSnapshot();
});bench
- Type :
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
bench définit un benchmark. Dans les termes de Vitest, un benchmark est une fonction qui définit une série d'opérations. Vitest exécute cette fonction plusieurs fois pour afficher différents résultats de performance.
Vitest utilise la bibliothèque tinybench en interne, héritant de toutes ses options qui peuvent être passées comme troisième argument.
import { bench } from 'vitest';
bench(
'normal sorting',
() => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
},
{ time: 1000 }
);export interface Options {
/**
* Temps nécessaire pour exécuter une tâche de benchmark (millisecondes).
* @default 500
*/
time?: number;
/**
* Nombre de fois qu'une tâche doit s'exécuter même si le temps alloué est écoulé.
* @default 10
*/
iterations?: number;
/**
* Fonction pour obtenir l'horodatage actuel en millisecondes.
*/
now?: () => number;
/**
* Un AbortSignal pour annuler le benchmark.
*/
signal?: AbortSignal;
/**
* Lève une erreur si une tâche échoue (les événements ne fonctionneront pas si cette option est activée).
*/
throws?: boolean;
/**
* Temps de chauffe (millisecondes).
* @default 100ms
*/
warmupTime?: number;
/**
* Itérations de chauffe.
* @default 5
*/
warmupIterations?: number;
/**
* Fonction de configuration à exécuter avant chaque tâche de benchmark (cycle).
*/
setup?: Hook;
/**
* Fonction de nettoyage à exécuter après chaque tâche de benchmark (cycle).
*/
teardown?: Hook;
}Après l'exécution du cas de test, la structure des informations de sortie est la suivante :
name hz min max mean p75 p99 p995 p999 rme samples
· normal sorting 6,526,368.12 0.0001 0.3638 0.0002 0.0002 0.0002 0.0002 0.0004 ±1.41% 652638export interface TaskResult {
/*
* La dernière erreur qui a été levée lors de l'exécution de la tâche.
*/
error?: unknown;
/**
* Le temps total en millisecondes pour exécuter la tâche de benchmark (cycle).
*/
totalTime: number;
/**
* La valeur minimale dans les échantillons.
*/
min: number;
/**
* La valeur maximale dans les échantillons.
*/
max: number;
/**
* Le nombre d'opérations par seconde.
*/
hz: number;
/**
* La durée de chaque opération (ms).
*/
period: number;
/**
* Échantillons de temps pour chaque itération de tâche (ms).
*/
samples: number[];
/**
* Moyenne des échantillons (estimation de la moyenne de la population).
*/
mean: number;
/**
* Variance des échantillons (estimation de la variance de la population).
*/
variance: number;
/**
* Écart-type des échantillons (estimation de l'écart-type de la population).
*/
sd: number;
/**
* Erreur standard de la moyenne (également connue sous le nom d'écart-type de la distribution d'échantillonnage de la moyenne de l'échantillon).
*/
sem: number;
/**
* Degrés de liberté.
*/
df: number;
/**
* Valeur critique des échantillons.
*/
critical: number;
/**
* Marge d'erreur.
*/
moe: number;
/**
* Marge d'erreur relative.
*/
rme: number;
/**
* Déviation absolue médiane.
*/
mad: number;
/**
* Percentile p50/médiane.
*/
p50: number;
/**
* Percentile p75.
*/
p75: number;
/**
* Percentile p99.
*/
p99: number;
/**
* Percentile p995.
*/
p995: number;
/**
* Percentile p999.
*/
p999: number;
}bench.skip
- Type :
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
Vous pouvez utiliser la syntaxe bench.skip pour ignorer l'exécution de certains benchmarks.
import { bench } from 'vitest';
bench.skip('normal sorting', () => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
});bench.only
- Type :
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
Utilisez bench.only pour n'exécuter que certains benchmarks dans une suite donnée. C'est utile lors du débogage.
import { bench } from 'vitest';
bench.only('normal sorting', () => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
});bench.todo
- Type :
(name: string | Function) => void
Utilisez bench.todo pour marquer des benchmarks à implémenter plus tard.
import { bench } from 'vitest';
bench.todo('unimplemented test');describe
Lorsque vous utilisez test ou bench au niveau supérieur d'un fichier, ils sont inclus dans la suite implicite de celui-ci. En utilisant describe, vous pouvez définir une nouvelle suite dans le contexte actuel, regroupant des tests ou des benchmarks liés ainsi que d'autres suites imbriquées. Une suite vous permet d'organiser vos tests et benchmarks afin que les rapports soient plus clairs.
// basic.spec.ts
// organisation des tests
import { describe, expect, test } from 'vitest';
const person = {
isActive: true,
age: 32,
};
describe('person', () => {
test('person is defined', () => {
expect(person).toBeDefined();
});
test('is active', () => {
expect(person.isActive).toBeTruthy();
});
test('age limit', () => {
expect(person.age).toBeLessThanOrEqual(32);
});
});// basic.bench.ts
// organisation des benchmarks
import { bench, describe } from 'vitest';
describe('sort', () => {
bench('normal', () => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
});
bench('reverse', () => {
const x = [1, 5, 4, 2, 3];
x.reverse().sort((a, b) => {
return a - b;
});
});
});Vous pouvez également imbriquer des blocs describe si vous avez une hiérarchie de tests ou de benchmarks :
import { describe, expect, test } from 'vitest';
function numberToCurrency(value: number | string) {
if (typeof value !== 'number') {
throw new TypeError('Value must be a number');
}
return value
.toFixed(2)
.toString()
.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
describe('numberToCurrency', () => {
describe('pour un nombre invalide', () => {
test('qui n\'est pas un nombre doit lever une erreur', () => {
expect(() => numberToCurrency('abc')).toThrowError();
});
});
describe('pour un nombre valide', () => {
test('returns the correct currency format', () => {
expect(numberToCurrency(10000)).toBe('10,000.00');
});
});
});describe.skip
- Alias :
suite.skip
Utilisez describe.skip dans une suite pour éviter d'exécuter un bloc describe particulier.
import { assert, describe, test } from 'vitest';
describe.skip('skipped suite', () => {
test('sqrt', () => {
// Suite ignorée, pas d'erreur
assert.equal(Math.sqrt(4), 3);
});
});describe.skipIf
- Alias :
suite.skipIf
Dans certains cas, vous pouvez être amené à exécuter des suites plusieurs fois dans des environnements différents, et certaines d'entre elles pourraient être spécifiques à l'environnement. Au lieu d'envelopper la suite avec une condition if, vous pouvez utiliser describe.skipIf pour ignorer la suite si la condition est vraie.
import { describe, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
describe.skipIf(isDev)('prod only test suite', () => {
// cette suite de tests ne s'exécute qu'en production
});WARNING
Vous ne pouvez pas utiliser cette syntaxe lorsque vous utilisez Vitest comme vérificateur de type.
describe.runIf
- Alias :
suite.runIf
L'opposé de describe.skipIf.
import { assert, describe, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
describe.runIf(isDev)('dev only test suite', () => {
// cette suite de tests ne s'exécute qu'en développement
});WARNING
Vous ne pouvez pas utiliser cette syntaxe lorsque vous utilisez Vitest comme vérificateur de type.
describe.only
- Type :
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => void
Utilisez describe.only pour n'exécuter que certaines suites.
import { assert, describe, test } from 'vitest';
// Seule cette suite (et les autres marquées avec only) sont exécutées
describe.only('suite', () => {
test('sqrt', () => {
assert.equal(Math.sqrt(4), 3);
});
});
describe('other suite', () => {
// ... sera ignorée
});Il est parfois très utile d'exécuter des tests only dans un certain fichier, en ignorant tous les autres tests de l'ensemble de la suite de tests, afin de ne pas surcharger la sortie.
Pour ce faire, exécutez vitest avec le fichier contenant les tests concernés.
# vitest interesting.test.tsdescribe.concurrent
- Alias :
suite.concurrent
describe.concurrent exécute toutes les suites et tests internes en parallèle.
import { describe, test } from 'vitest';
// Toutes les suites et tests au sein de cette suite seront exécutés en parallèle
describe.concurrent('suite', () => {
test('concurrent test 1', async () => {
/* ... */
});
describe('concurrent suite 2', async () => {
test('concurrent test inner 1', async () => {
/* ... */
});
test('concurrent test inner 2', async () => {
/* ... */
});
});
test.concurrent('concurrent test 3', async () => {
/* ... */
});
});.skip, .only et .todo fonctionnent avec les suites concurrentes. Toutes les combinaisons suivantes sont valides :
describe.concurrent(/* ... */);
describe.skip.concurrent(/* ... */); // ou describe.concurrent.skip(/* ... */)
describe.only.concurrent(/* ... */); // ou describe.concurrent.only(/* ... */)
describe.todo.concurrent(/* ... */); // ou describe.concurrent.todo(/* ... */)Lors de l'exécution de tests concurrents, les instantanés (Snapshots) et les assertions doivent utiliser expect du Contexte de Test local pour s'assurer que le bon test est détecté.
describe.concurrent('suite', () => {
test('concurrent test 1', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
test('concurrent test 2', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
});WARNING
Vous ne pouvez pas utiliser cette syntaxe lorsque vous utilisez Vitest comme vérificateur de type.
describe.sequential
- Alias :
suite.sequential
describe.sequential dans une suite marque chaque test comme séquentiel. C'est utile si vous voulez exécuter des tests en séquence au sein de describe.concurrent ou avec l'option de commande --sequence.concurrent.
import { describe, test } from 'vitest';
describe.concurrent('suite', () => {
test('concurrent test 1', async () => {
/* ... */
});
test('concurrent test 2', async () => {
/* ... */
});
describe.sequential('', () => {
test('sequential test 1', async () => {
/* ... */
});
test('sequential test 2', async () => {
/* ... */
});
});
});describe.shuffle
- Alias :
suite.shuffle
Vitest offre un moyen d'exécuter tous les tests dans un ordre aléatoire via l'option CLI --sequence.shuffle ou l'option de configuration sequence.shuffle. Si vous souhaitez qu'une partie seulement de votre suite de tests exécute les tests dans un ordre aléatoire, vous pouvez la marquer avec cette option.
import { describe, test } from 'vitest';
// ou describe('suite', { shuffle: true }, ...)
describe.shuffle('suite', () => {
test('random test 1', async () => {
/* ... */
});
test('random test 2', async () => {
/* ... */
});
test('random test 3', async () => {
/* ... */
});
// `shuffle` est hérité
describe('still random', () => {
test('random 4.1', async () => {
/* ... */
});
test('random 4.2', async () => {
/* ... */
});
});
// désactiver l'ordre aléatoire à l'intérieur
describe('not random', { shuffle: false }, () => {
test('in order 5.1', async () => {
/* ... */
});
test('in order 5.2', async () => {
/* ... */
});
});
});
// l'ordre dépend de l'option sequence.seed dans la configuration (Date.now() par défaut).skip, .only et .todo fonctionnent avec les suites aléatoires.
WARNING
Vous ne pouvez pas utiliser cette syntaxe lorsque vous utilisez Vitest comme vérificateur de type.
describe.todo
- Alias :
suite.todo
Utilisez describe.todo pour marquer des suites à implémenter plus tard. Ces suites apparaîtront dans le rapport, vous indiquant ainsi le nombre de tests qu'il vous reste à implémenter.
// Une entrée sera affichée dans le rapport pour cette suite
describe.todo('unimplemented suite');describe.each
- Alias :
suite.each
TIP
Bien que describe.each soit fourni pour la compatibilité Jest, Vitest dispose également de describe.for qui simplifie les types d'arguments et s'aligne avec test.for.
Utilisez describe.each si plusieurs tests dépendent des mêmes données.
import { describe, expect, test } from 'vitest';
describe.each([
{ a: 1, b: 1, expected: 2 },
{ a: 1, b: 2, expected: 3 },
{ a: 2, b: 1, expected: 3 },
])('description de l\'objet add($a, $b)', ({ a, b, expected }) => {
test(`returns ${expected}`, () => {
expect(a + b).toBe(expected);
});
test(`la valeur retournée ne doit pas être supérieure à ${expected}`, () => {
expect(a + b).not.toBeGreaterThan(expected);
});
test(`la valeur retournée ne doit pas être inférieure à ${expected}`, () => {
expect(a + b).not.toBeLessThan(expected);
});
});À partir de Vitest 0.25.3, vous pouvez également utiliser une table de chaînes de caractères de modèle.
- La première ligne doit contenir les noms de colonnes, séparés par
|; - Une ou plusieurs lignes de données suivantes fournies sous forme d'expressions littérales de modèle utilisant la syntaxe
${value}.
import { describe, expect, test } from 'vitest';
describe.each`
a | b | expected
${1} | ${1} | ${2}
${'a'} | ${'b'} | ${'ab'}
${[]} | ${'b'} | ${'b'}
${{}} | ${'b'} | ${'[object Object]b'}
${{ asd: 1 }} | ${'b'} | ${'[object Object]b'}
`('description de la chaîne de modèle add($a, $b)', ({ a, b, expected }) => {
test(`returns ${expected}`, () => {
expect(a + b).toBe(expected);
});
});WARNING
Vous ne pouvez pas utiliser cette syntaxe lorsque vous utilisez Vitest comme vérificateur de type.
describe.for
- Alias :
suite.for
La différence avec describe.each réside dans la manière dont les arguments de type tableau sont fournis. Les autres types d'arguments non-tableau (y compris l'utilisation de chaînes de caractères de modèle) fonctionnent exactement de la même manière.
// `each` déstructure les arguments de type tableau
describe.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', (a, b, expected) => {
test('test', () => {
expect(a + b).toBe(expected);
});
});
// `for` ne déstructure pas les arguments de type tableau
describe.for([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', ([a, b, expected]) => {
test('test', () => {
expect(a + b).toBe(expected);
});
});Configuration et Nettoyage
Ces fonctions vous permettent de vous intégrer au cycle de vie des tests afin d'éviter de répéter le code de configuration et de nettoyage. Elles s'appliquent au contexte actuel : le fichier si elles sont utilisées au niveau supérieur ou la suite actuelle si elles sont à l'intérieur d'un bloc describe. Ces hooks ne sont pas appelés lorsque vous exécutez Vitest en tant que vérificateur de type.
beforeEach
- Type :
beforeEach(fn: () => Awaitable<void>, timeout?: number)
Enregistre une fonction de rappel qui sera appelée avant l'exécution de chacun des tests dans le contexte actuel. Si la fonction renvoie une promesse, Vitest attend que la promesse soit résolue avant d'exécuter le test.
Optionnellement, vous pouvez spécifier un délai d'attente (en millisecondes) définissant la durée maximale avant l'arrêt. La valeur par défaut est de 5 secondes.
import { beforeEach } from 'vitest';
beforeEach(async () => {
// Effacer les mocks et ajouter des données de test avant chaque exécution de test
await stopMocking();
await addUser({ name: 'John' });
});Ici, beforeEach garantit que les données utilisateur sont ajoutées pour chaque test.
beforeEach accepte également une fonction de nettoyage optionnelle (équivalente à afterEach).
import { beforeEach } from 'vitest';
beforeEach(async () => {
// appelé une fois avant chaque exécution de test
await prepareSomething();
// fonction de nettoyage, appelée une fois après chaque exécution de test
return async () => {
await resetSomething();
};
});afterEach
- Type :
afterEach(fn: () => Awaitable<void>, timeout?: number)
Enregistre une fonction de rappel qui sera appelée après que chacun des tests dans le contexte actuel soit terminé. Si la fonction renvoie une promesse, Vitest attend que la promesse soit résolue avant de continuer.
Optionnellement, vous pouvez fournir un délai d'attente (en millisecondes) pour spécifier combien de temps attendre avant de terminer. La valeur par défaut est de 5 secondes.
import { afterEach } from 'vitest';
afterEach(async () => {
await clearTestingData(); // effacer les données de test après chaque exécution de test
});Ici, afterEach garantit que les données de test sont effacées après chaque exécution de test.
TIP
Vitest 1.3.0 a ajouté le hook onTestFinished. Vous pouvez l'appeler pendant l'exécution du test pour nettoyer tout état une fois le test terminé.
beforeAll
- Type :
beforeAll(fn: () => Awaitable<void>, timeout?: number)
Enregistre une fonction de rappel qui sera appelée une fois avant de commencer l'exécution de tous les tests dans le contexte actuel. Si la fonction renvoie une promesse, Vitest attend que la promesse soit résolue avant d'exécuter les tests.
Optionnellement, vous pouvez fournir un délai d'attente (en millisecondes) pour spécifier combien de temps attendre avant de terminer. La valeur par défaut est de 5 secondes.
import { beforeAll } from 'vitest';
beforeAll(async () => {
await startMocking(); // appelé une fois avant l'exécution de tous les tests
});Ici, beforeAll garantit que les données de mock sont configurées avant l'exécution des tests.
beforeAll accepte également une fonction de nettoyage optionnelle (équivalente à afterAll).
import { beforeAll } from 'vitest';
beforeAll(async () => {
// appelé une fois avant l'exécution de tous les tests
await startMocking();
// fonction de nettoyage, appelée une fois après l'exécution de tous les tests
return async () => {
await stopMocking();
};
});afterAll
- Type :
afterAll(fn: () => Awaitable<void>, timeout?: number)
Enregistre une fonction de rappel qui sera appelée une fois après l'exécution de tous les tests dans le contexte actuel. Si la fonction renvoie une promesse, Vitest attend que la promesse soit résolue avant de continuer.
Optionnellement, vous pouvez fournir un délai d'attente (en millisecondes) pour spécifier combien de temps attendre avant de terminer. La valeur par défaut est de 5 secondes.
import { afterAll } from 'vitest';
afterAll(async () => {
await stopMocking(); // cette méthode est appelée après l'exécution de tous les tests
});Ici, afterAll garantit que la méthode stopMocking est appelée après l'exécution de tous les tests.
Hooks de Test
Vitest fournit quelques hooks que vous pouvez appeler pendant l'exécution du test pour nettoyer l'état une fois le test terminé.
WARNING
Ces hooks lèveront une erreur s'ils sont appelés en dehors du corps du test.
onTestFinished
Ce hook est toujours appelé une fois le test terminé. Il est appelé après les hooks afterEach car ils peuvent influencer le résultat du test. Il reçoit un objet ExtendedContext similaire à ceux de beforeEach et afterEach.
import { onTestFinished, test } from 'vitest';
test('performs a query', () => {
const db = connectDb();
onTestFinished(() => db.close());
db.query('SELECT * FROM users');
});WARNING
Si vous exécutez des tests en parallèle, vous devez toujours utiliser le hook onTestFinished du contexte de test, car Vitest ne gère pas les tests concurrents dans les hooks globaux :
import { test } from 'vitest';
test.concurrent('performs a query', ({ onTestFinished }) => {
const db = connectDb();
onTestFinished(() => db.close());
db.query('SELECT * FROM users');
});Ce hook est particulièrement utile lors de la création de logique réutilisable :
// cela peut être dans un fichier séparé
function getTestDb() {
const db = connectMockedDb();
onTestFinished(() => db.close());
return db;
}
test('performs a user query', async () => {
const db = getTestDb();
expect(await db.query('SELECT * from users').perform()).toEqual([]);
});
test('performs an organization query', async () => {
const db = getTestDb();
expect(await db.query('SELECT * from organizations').perform()).toEqual([]);
});TIP
Ce hook est toujours appelé dans l'ordre inverse et n'est pas affecté par l'option sequence.hooks.
onTestFailed
Ce hook est appelé uniquement après l'échec du test. Il est appelé après les hooks afterEach car ils peuvent influencer le résultat du test. Il reçoit un objet ExtendedContext similaire à ceux de beforeEach et afterEach. Ce hook est utile pour le débogage.
import { onTestFailed, test } from 'vitest';
test('performs a query', () => {
const db = connectDb();
onTestFailed(({ task }) => {
console.log(task.result.errors);
});
db.query('SELECT * FROM users');
});WARNING
Si vous exécutez des tests en parallèle, vous devez toujours utiliser le hook onTestFailed du contexte de test, car Vitest ne gère pas les tests concurrents dans les hooks globaux :
import { test } from 'vitest';
test.concurrent('performs a query', ({ onTestFailed }) => {
const db = connectDb();
onTestFailed(({ task }) => {
console.log(task.result.errors);
});
db.query('SELECT * FROM users');
});