Instantané (Snapshot)
Apprenez les instantanés grâce à une vidéo de Vue SchoolLes tests d'instantanés sont un outil puissant pour garantir que le résultat de vos fonctions ne change pas de manière inattendue.
Lorsqu'un test d'instantané est exécuté, Vitest capture un instantané de la valeur à tester et le compare à un fichier d'instantané de référence stocké à côté du test. Le test échoue si les deux instantanés ne correspondent pas, indiquant soit une modification inattendue, soit la nécessité de mettre à jour l'instantané de référence avec la nouvelle version du résultat.
Utiliser les instantanés
Pour créer un instantané d'une valeur, utilisez la méthode toMatchSnapshot()
de l'API expect()
:
import { expect, it } from 'vitest';
it('toUpperCase', () => {
const result = toUpperCase('foobar');
expect(result).toMatchSnapshot();
});
Lors de la première exécution de ce test, Vitest crée un fichier d'instantané similaire à celui-ci :
// Vitest Snapshot v1, https://www.getbook.com/fr/book/vitest-0/guide/snapshot
exports['toUpperCase 1'] = '"FOOBAR"';
L'instantané créé doit être validé en même temps que les modifications du code et examiné dans le cadre de votre processus de revue de code. Lors des exécutions de test suivantes, Vitest comparera le résultat obtenu avec l'instantané précédent. Si les deux correspondent, le test réussit. Sinon, cela signifie soit qu'un bug a été introduit dans le code et doit être corrigé, soit que l'implémentation a été modifiée et que l'instantané doit être mis à jour.
WARNING
Lorsque vous utilisez des instantanés avec des tests asynchrones concurrents, utilisez la fonction expect
du Contexte de Test local pour garantir que le bon test est ciblé.
Instantanés en ligne (Inline Snapshots)
Vous pouvez également utiliser toMatchInlineSnapshot()
pour stocker l'instantané directement dans le fichier de test.
import { expect, it } from 'vitest';
it('toUpperCase', () => {
const result = toUpperCase('foobar');
expect(result).toMatchInlineSnapshot();
});
Au lieu de créer un fichier d'instantané séparé, Vitest modifiera directement le fichier de test pour y insérer l'instantané sous forme de chaîne :
import { expect, it } from 'vitest';
it('toUpperCase', () => {
const result = toUpperCase('foobar');
expect(result).toMatchInlineSnapshot('"FOOBAR"');
});
Cela permet de visualiser le résultat attendu directement dans le code, sans avoir à naviguer entre plusieurs fichiers.
WARNING
Lorsque vous utilisez des instantanés avec des tests asynchrones concurrents, utilisez la fonction expect
du Contexte de Test local pour garantir que le bon test est ciblé.
Mettre à jour les instantanés
Lorsqu'une valeur obtenue ne correspond pas à l'instantané, le test échoue et affiche la différence. Si la modification de l'instantané est intentionnelle, vous pouvez le mettre à jour pour qu'il corresponde à l'état actuel.
En mode de surveillance, vous pouvez appuyer sur la touche u
dans le terminal pour mettre à jour directement l'instantané qui a échoué.
Vous pouvez également utiliser l'option --update
ou -u
dans la CLI pour que Vitest mette à jour les instantanés.
vitest -u
Instantanés de fichiers
Lorsque vous appelez toMatchSnapshot()
, tous les instantanés sont stockés dans un fichier formaté. Cela implique d'échapper certains caractères, notamment les guillemets doubles "
et l'accent grave ``` dans la chaîne d'instantané. De plus, la coloration syntaxique du contenu de l'instantané peut être perdue (si celui-ci est écrit dans un langage spécifique).
Pour améliorer cette situation, la méthode toMatchFileSnapshot()
permet de créer explicitement un instantané dans un fichier. Cela permet d'attribuer n'importe quelle extension de fichier au fichier d'instantané, et de le rendre plus lisible.
import { expect, it } from 'vitest';
it('render basic', async () => {
const result = renderHTML(h('div', { class: 'foo' }));
await expect(result).toMatchFileSnapshot('./test/basic.output.html');
});
Le résultat sera comparé au contenu de ./test/basic.output.html
. Le fichier peut être réécrit avec l'option --update
.
Instantanés d'images
Il est également possible de créer des instantanés d'images à l'aide de jest-image-snapshot
.
npm i -D jest-image-snapshot
test('image snapshot', () => {
expect(readFileSync('./test/stubs/input-image.png')).toMatchImageSnapshot();
});
Vous trouverez un exemple complet dans examples/image-snapshot
.
Sérialiseur personnalisé
Vous pouvez définir votre propre logique pour modifier la façon dont vos instantanés sont sérialisés. Comme Jest, Vitest propose des sérialiseurs par défaut pour les types JavaScript intégrés, les éléments HTML, ImmutableJS et les éléments React.
Exemple de module de sérialiseur :
expect.addSnapshotSerializer({
serialize(val, config, indentation, depth, refs, printer) {
// `printer` est une fonction qui sérialise une valeur en utilisant les plugins existants.
return `Pretty foo: ${printer(val.foo)}`;
},
test(val) {
return val && Object.prototype.hasOwnProperty.call(val, 'foo');
},
});
Après avoir ajouté un test comme celui-ci :
test('foo snapshot test', () => {
const bar = {
foo: {
x: 1,
y: 2,
},
};
expect(bar).toMatchSnapshot();
});
Vous obtiendrez l'instantané suivant :
Pretty foo: Object {
"x": 1,
"y": 2,
}
Vitest utilise pretty-format
de Jest pour sérialiser les instantanés. Pour en savoir plus, consultez la documentation de pretty-format.
Différences par rapport à Jest
Vitest propose une fonctionnalité d'instantané presque entièrement compatible avec celle de Jest, à quelques exceptions près.
1. L'en-tête de commentaire dans le fichier d'instantané est différent {#_1-comment-header-in-the-snapshot-file-is-different}
- // Jest Snapshot v1, https://goo.gl/fbAQLP
+ // Vitest Snapshot v1, https://www.getbook.com/fr/book/vitest-0/guide/snapshot
Cela n'affecte pas la fonctionnalité elle-même, mais peut influencer votre diff de commit lors d'une migration depuis Jest.
2. printBasicPrototype
est par défaut à false
{#_2-printbasicprototype-is-default-to-false}
Les instantanés de Jest et Vitest sont gérés par pretty-format
. Dans Vitest, printBasicPrototype
est défini par défaut sur false
pour fournir une sortie d'instantané plus propre, tandis que dans Jest <29.0.0, il est true
par défaut.
import { expect, test } from 'vitest';
test('snapshot', () => {
const bar = [
{
foo: 'bar',
},
];
// in Jest
expect(bar).toMatchInlineSnapshot(`
Array [
Object {
"foo": "bar",
},
]
`);
// in Vitest
expect(bar).toMatchInlineSnapshot(`
[
{
"foo": "bar",
},
]
`);
});
Nous estimons qu'il s'agit d'une valeur par défaut plus pertinente pour la lisibilité et l'expérience utilisateur globale. Si vous préférez le comportement de Jest, vous pouvez modifier votre configuration :
// vitest.config.js
export default defineConfig({
test: {
snapshotFormat: {
printBasicPrototype: true,
},
},
});
3. Le chevron >
est utilisé comme séparateur au lieu du deux-points :
pour les messages personnalisés {#_3-chevron-is-used-as-a-separator-instead-of-colon-for-custom-messages}
Vitest utilise le chevron >
comme séparateur au lieu des deux-points :
pour améliorer la lisibilité, lorsqu'un message personnalisé est transmis lors de la création d'un fichier d'instantané.
Pour l'exemple de code de test suivant :
test('toThrowErrorMatchingSnapshot', () => {
expect(() => {
throw new Error('error');
}).toThrowErrorMatchingSnapshot('hint');
});
Dans Jest, l'instantané sera :
exports[`toThrowErrorMatchingSnapshot: hint 1`] = `"error"`;
Dans Vitest, l'instantané équivalent sera :
exports[`toThrowErrorMatchingSnapshot > hint 1`] = `"error"`;