Snapshot
Erfahren Sie mehr über Snapshots im Video von Vue SchoolSnapshot-Tests sind ein äußerst nützliches Werkzeug, um sicherzustellen, dass sich die Ausgabe Ihrer Funktionen nicht unerwartet ändert.
Bei der Verwendung von Snapshots erstellt Vitest einen Snapshot des angegebenen Wertes und vergleicht ihn anschließend mit einer Referenz-Snapshot-Datei, die zusammen mit dem Test gespeichert ist. Der Test schlägt fehl, wenn die beiden Snapshots nicht übereinstimmen: Entweder ist die Änderung unerwartet, oder der Referenz-Snapshot muss auf die neue Version des Ergebnisses aktualisiert werden.
Snapshots verwenden
Um einen Wert als Snapshot zu speichern, können Sie toMatchSnapshot()
aus der expect()
API verwenden:
import { expect, it } from 'vitest';
it('toUpperCase', () => {
const result = toUpperCase('foobar');
expect(result).toMatchSnapshot();
});
Wenn dieser Test zum ersten Mal ausgeführt wird, erstellt Vitest eine Snapshot-Datei, die so aussieht:
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports['toUpperCase 1'] = '"FOOBAR"';
Das Snapshot-Artefakt sollte zusammen mit den Codeänderungen committet und im Rahmen Ihres Code-Review-Prozesses überprüft werden. Bei späteren Testdurchläufen vergleicht Vitest die gerenderte Ausgabe mit dem vorherigen Snapshot. Wenn sie übereinstimmen, besteht der Test. Wenn sie nicht übereinstimmen, hat der Test-Runner entweder einen Fehler in Ihrem Code gefunden, der behoben werden sollte, oder die Implementierung hat sich geändert und der Snapshot muss aktualisiert werden.
WARNING
Bei der Verwendung von Snapshots mit asynchronen, gleichzeitigen Tests muss expect
aus dem lokalen Test Context verwendet werden, um sicherzustellen, dass der richtige Test erkannt wird.
Inline-Snapshots
Ähnlich können Sie toMatchInlineSnapshot()
verwenden, um den Snapshot direkt in der Testdatei zu speichern.
import { expect, it } from 'vitest';
it('toUpperCase', () => {
const result = toUpperCase('foobar');
expect(result).toMatchInlineSnapshot();
});
Anstatt eine Snapshot-Datei zu erstellen, ändert Vitest die Testdatei direkt, um den Snapshot als String zu aktualisieren:
import { expect, it } from 'vitest';
it('toUpperCase', () => {
const result = toUpperCase('foobar');
expect(result).toMatchInlineSnapshot('"FOOBAR"');
});
Dadurch können Sie die erwartete Ausgabe direkt sehen, ohne zwischen verschiedenen Dateien wechseln zu müssen.
WARNING
Bei der Verwendung von Snapshots mit asynchronen, gleichzeitigen Tests muss expect
aus dem lokalen Test Context verwendet werden, um sicherzustellen, dass der richtige Test erkannt wird.
Snapshots aktualisieren
Wenn der empfangene Wert nicht mit dem Snapshot übereinstimmt, schlägt der Test fehl und zeigt Ihnen den Unterschied zwischen ihnen. Wenn die Änderung des Snapshots erwartet wird, möchten Sie ihn möglicherweise aus dem aktuellen Zustand aktualisieren.
Im Überwachungsmodus können Sie im Terminal die Taste u
drücken, um den fehlgeschlagenen Snapshot direkt zu aktualisieren.
Oder Sie können das --update
oder -u
Flag in der CLI verwenden, damit Vitest Snapshots aktualisiert.
vitest -u
Datei-Snapshots
Beim Aufruf von toMatchSnapshot()
speichern wir alle Snapshots in einer formatierten Snapshot-Datei. Das bedeutet, dass wir einige Zeichen, wie das doppelte Anführungszeichen "
und den Backtick `
, im Snapshot-String escapen müssen. Gleichzeitig könnten Sie das Syntax-Highlighting für den Snapshot-Inhalt verlieren (falls dieser in einer bestimmten Sprache ist).
Aus diesem Grund haben wir toMatchFileSnapshot()
eingeführt, um explizit mit einer Datei abzugleichen. Dies ermöglicht es Ihnen, dem Snapshot-Dateinamen eine beliebige Dateierweiterung zuzuweisen und die Dateien lesbarer zu machen.
import { expect, it } from 'vitest';
it('render basic', async () => {
const result = renderHTML(h('div', { class: 'foo' }));
await expect(result).toMatchFileSnapshot('./test/basic.output.html');
});
Der Inhalt wird mit ./test/basic.output.html
verglichen und kann mit dem --update
Flag zurückgeschrieben werden.
Bild-Snapshots
Es ist auch möglich, Bilder als Snapshot mit jest-image-snapshot
zu speichern.
npm i -D jest-image-snapshot
test('image snapshot', () => {
expect(readFileSync('./test/stubs/input-image.png')).toMatchImageSnapshot();
});
Benutzerdefinierter Serializer
Sie können Ihre eigene Logik hinzufügen, um die Serialisierung Ihrer Snapshots zu ändern. Wie Jest verfügt auch Vitest über Standard-Serializer für integrierte JavaScript-Typen, HTML-Elemente, ImmutableJS und React-Elemente.
Sie können einen benutzerdefinierten Serializer explizit hinzufügen, indem Sie die API expect.addSnapshotSerializer
verwenden.
expect.addSnapshotSerializer({
serialize(val, config, indentation, depth, refs, printer) {
// `printer` ist eine Funktion, die einen Wert mit vorhandenen Plugins serialisiert.
return `Pretty foo: ${printer(val.foo, config, indentation, depth, refs)}`;
},
test(val) {
return val && Object.prototype.hasOwnProperty.call(val, 'foo');
},
});
Wir unterstützen auch die Option snapshotSerializers, um implizit benutzerdefinierte Serializer hinzuzufügen.
import { SnapshotSerializer } from 'vitest';
export default {
serialize(val, config, indentation, depth, refs, printer) {
// `printer` ist eine Funktion, die einen Wert mit vorhandenen Plugins serialisiert.
return `Pretty foo: ${printer(val.foo, config, indentation, depth, refs)}`;
},
test(val) {
return val && Object.prototype.hasOwnProperty.call(val, 'foo');
},
} satisfies SnapshotSerializer;
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
snapshotSerializers: ['path/to/custom-serializer.ts'],
},
});
Nachdem Sie einen Test wie diesen hinzugefügt haben:
test('foo snapshot test', () => {
const bar = {
foo: {
x: 1,
y: 2,
},
};
expect(bar).toMatchSnapshot();
});
Sie erhalten den folgenden Snapshot:
Pretty foo: Object {
"x": 1,
"y": 2,
}
Für die Serialisierung nutzen wir Jests pretty-format
. Weitere Informationen finden Sie hier: pretty-format.
Unterschiede zu Jest
Vitest bietet eine nahezu kompatible Snapshot-Funktion mit Jests mit einigen Ausnahmen:
1. Der Kommentar-Header in der Snapshot-Datei ist anders {#_1-comment-header-in-the-snapshot-file-is-different}
- // Jest Snapshot v1, https://goo.gl/fbAQLP
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
Dies beeinflusst die Funktionalität nicht wirklich, könnte aber Ihren Commit-Diff bei der Migration von Jest beeinträchtigen.
2. printBasicPrototype
ist standardmäßig false
{#_2-printbasicprototype-is-default-to-false}
Sowohl Jests als auch Vitests Snapshots werden von pretty-format
unterstützt. In Vitest setzen wir printBasicPrototype
standardmäßig auf false
, um eine sauberere Snapshot-Ausgabe zu erzielen, während es in Jest <29.0.0 standardmäßig true
ist.
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",
},
]
`);
});
Wir halten dies für eine bessere Standardeinstellung hinsichtlich Lesbarkeit und Entwicklerfreundlichkeit. Falls Sie das Jest-Verhalten bevorzugen, können Sie Ihre Konfiguration ändern:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
snapshotFormat: {
printBasicPrototype: true,
},
},
});
3. Chevron >
wird als Trennzeichen anstelle von Doppelpunkt :
für benutzerdefinierte Nachrichten verwendet {#_3-chevron-is-used-as-a-separator-instead-of-colon-for-custom-messages}
Vitest verwendet den Chevron >
als Trennzeichen anstelle des Doppelpunkts :
zur besseren Lesbarkeit, wenn eine benutzerdefinierte Nachricht bei der Erstellung einer Snapshot-Datei übergeben wird.
Für den folgenden Beispieltestcode:
test('toThrowErrorMatchingSnapshot', () => {
expect(() => {
throw new Error('error');
}).toThrowErrorMatchingSnapshot('hint');
});
In Jest wird der Snapshot wie folgt aussehen:
exports[`toThrowErrorMatchingSnapshot: hint 1`] = `"error"`;
In Vitest wird der entsprechende Snapshot wie folgt aussehen:
exports[`toThrowErrorMatchingSnapshot > hint 1`] = `[Error: error]`;
4. Der Standard-Error
-Snapshot ist für toThrowErrorMatchingSnapshot
und toThrowErrorMatchingInlineSnapshot
unterschiedlich {#_4-default-error-snapshot-is-different-for-tothrowerrormatchingsnapshot-and-tothrowerrormatchinginlinesnapshot}
import { expect, test } from 'vitest'
test('snapshot', () => {
// in Jest und Vitest
expect(new Error('error')).toMatchInlineSnapshot(`[Error: error]`)
// Jest erstellt Snapshots von `Error.message` für `Error`-Instanzen.
// Vitest gibt den gleichen Wert wie `toMatchInlineSnapshot` aus.
expect(() => {
throw new Error('error')
}).toThrowErrorMatchingInlineSnapshot(`"error"`)
}).toThrowErrorMatchingInlineSnapshot(`[Error: error]`)
})