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:
- Capture: lors de la première exécution, Vitest capture la sortie et l’enregistre comme référence
- Comparaison: lors des exécutions suivantes, Vitest compare la sortie actuelle avec la référence
- 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
# Mettre à jour tous les snapshotsvitest -u
# Ou avec le nom completvitest --update
Mise à Jour Sélective
Pour mettre à jour uniquement certains snapshots:
# Mettre à jour les snapshots pour les tests correspondant au patternvitest -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
:
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:
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
- Gardez-les petits: testez des unités spécifiques plutôt que des structures entières
- Donnez-leur des noms descriptifs: utilisez des noms qui expliquent ce qui est testé
- Révisez les changements: examinez attentivement les modifications de snapshot lors des revues de code
- Préférez les snapshots inline pour les petites valeurs
- 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:
- En-tête du fichier: Les fichiers
.snap
de Vitest commencent par// Vitest Snapshot v1
- Prototypes de base:
printBasicPrototype
estfalse
par défaut dans Vitest - 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.