Passer au contenu

Tests de Snapshots avec Vitest

Les tests de snapshots sont un outil puissant pour vérifier que la sortie de vos fonctions ou composants ne change pas de manière inattendue. Plutôt que d’écrire manuellement des assertions, vous pouvez capturer automatiquement le résultat et le comparer lors des exécutions ultérieures.

Principe des Snapshots

Un test de snapshot fonctionne en 3 étapes:

  1. Capture: lors de la première exécution, Vitest capture la sortie et l’enregistre comme référence
  2. Comparaison: lors des exécutions suivantes, Vitest compare la sortie actuelle avec la référence
  3. Validation/Mise à jour: si les sorties diffèrent, vous devez soit corriger le code, soit mettre à jour le snapshot

Snapshots de Base

Pour créer un snapshot, utilisez la méthode toMatchSnapshot():

import { expect, it } from 'vitest'
it('rend le texte correctement', () => {
const result = renderText('Hello, World!');
expect(result).toMatchSnapshot();
});

Lors de la première exécution, Vitest génère un fichier .snap à côté de votre fichier de test:

// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports['rend le texte correctement 1'] = '"Hello, World!"';

Création vs Validation

  • Première exécution: le snapshot est créé et le test réussit
  • Exécutions suivantes:
    • Si la sortie correspond → test réussi
    • Si la sortie diffère → test échoué (nécessite correction ou mise à jour)

Snapshots Inline

Les snapshots inline stockent la valeur attendue directement dans votre code de test plutôt que dans un fichier séparé:

import { expect, it } from 'vitest'
it('formate correctement la date', () => {
const date = new Date('2023-01-01');
const result = formatDate(date);
expect(result).toMatchInlineSnapshot('"01/01/2023"');
});

L’avantage est que vous pouvez voir immédiatement la valeur attendue sans naviguer entre les fichiers. Pour la première exécution, omettez l’argument:

expect(result).toMatchInlineSnapshot(); // Vitest ajoutera la valeur

Mise à Jour des Snapshots

Lorsqu’une modification intentionnelle change la sortie, vous devez mettre à jour le snapshot:

En Mode Watch

En mode watch (lancé avec vitest), appuyez sur la touche u lorsqu’un test de snapshot échoue pour mettre à jour tous les snapshots.

Via la Ligne de Commande

Fenêtre de terminal
# Mettre à jour tous les snapshots
vitest -u
# Ou avec le nom complet
vitest --update

Mise à Jour Sélective

Pour mettre à jour uniquement certains snapshots:

Fenêtre de terminal
# Mettre à jour les snapshots pour les tests correspondant au pattern
vitest -u -t "mon-test"

Snapshots de Fichiers

Pour les sorties complexes (comme du HTML ou du CSS), vous pouvez utiliser toMatchFileSnapshot() qui compare avec un fichier externe:

import { expect, it } from 'vitest'
it('génère le bon HTML', async () => {
const html = renderComponent({ title: 'Mon Titre' });
await expect(html).toMatchFileSnapshot('./tests/snapshots/composant.html');
});

Cela permet de:

  • Maintenir la syntaxe dans un fichier dédié (avec coloration syntaxique dans l’éditeur)
  • Éviter les problèmes d’échappement de caractères spéciaux
  • Mieux gérer les contenus volumineux

Snapshots d’Images

Pour tester des sorties graphiques, vous pouvez utiliser les snapshots d’images via jest-image-snapshot:

Fenêtre de terminal
npm i -D jest-image-snapshot
import { readFileSync } from 'fs';
import { expect, it } from 'vitest';
import { toMatchImageSnapshot } from 'jest-image-snapshot';
// Ajout du matcher personnalisé
expect.extend({ toMatchImageSnapshot });
it('génère la bonne image', () => {
const image = renderGraph({ data: [1, 2, 3] });
expect(image).toMatchImageSnapshot();
});

Personnalisation des Snapshots

Sérialisation Personnalisée

Vous pouvez personnaliser la façon dont vos objets sont convertis en snapshots:

// Ajout d'un sérialiseur personnalisé
expect.addSnapshotSerializer({
test: (val) => val && val.hasOwnProperty('_customType'),
serialize: (val, config, indentation, depth, refs, printer) => {
return `CustomType(${printer(val.value)})`;
}
});
it('sérialise correctement', () => {
const obj = { _customType: true, value: 42 };
expect(obj).toMatchSnapshot();
// Dans le snapshot: "CustomType(42)"
});

Configuration Globale

Vous pouvez configurer les sérialiseurs de snapshot au niveau du projet:

vitest.config.js
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
snapshotSerializers: ['./path/to/my-serializer.js'],
snapshotFormat: {
printBasicPrototype: false,
escapeString: true,
}
},
})

Bonnes Pratiques

Quand Utiliser les Snapshots

Les snapshots sont particulièrement utiles pour:

  • Composants UI: capturer le rendu HTML/JSX
  • Objets complexes: vérifier la structure de grands objets
  • Données formatées: tester le formatage de dates, nombres, etc.
  • Messages d’erreur: s’assurer que les messages d’erreur restent cohérents

Conseils pour des Tests de Snapshots Efficaces

  1. Gardez-les petits: testez des unités spécifiques plutôt que des structures entières
  2. Donnez-leur des noms descriptifs: utilisez des noms qui expliquent ce qui est testé
  3. Révisez les changements: examinez attentivement les modifications de snapshot lors des revues de code
  4. Préférez les snapshots inline pour les petites valeurs
  5. Utilisez les snapshots de fichiers pour les résultats complexes ou volumineux

À Éviter

  • Ne créez pas de snapshots excessivement grands qui capturent trop de détails
  • Ne vous fiez pas uniquement aux snapshots; combinez-les avec des assertions classiques
  • N’utilisez pas de données dynamiques (dates actuelles, nombres aléatoires) dans les snapshots

Différences avec Jest

Vitest est largement compatible avec les snapshots de Jest, avec quelques différences mineures:

  1. En-tête du fichier: Les fichiers .snap de Vitest commencent par // Vitest Snapshot v1
  2. Prototypes de base: printBasicPrototype est false par défaut dans Vitest
  3. Séparateur de messages: Vitest utilise > au lieu de : pour les messages personnalisés

Ces différences n’affectent généralement pas la migration de Jest vers Vitest, mais sont utiles à connaître.

Conclusion

Les snapshots offrent un moyen efficace de détecter les changements inattendus dans vos applications, mais doivent être utilisés judicieusement. Combinés avec des tests traditionnels, ils peuvent améliorer considérablement la fiabilité de votre suite de tests.