Snapshot
Obejrzyj lekcję wideo o snapshotach na Vue SchoolTesty migawkowe są niezwykle przydatne, gdy chcesz upewnić się, że wynik działania twoich funkcji nie zmienia się w nieoczekiwany sposób.
Podczas korzystania ze snapshotów, Vitest tworzy migawkę danej wartości, a następnie porównuje ją z referencyjnym plikiem migawki przechowywanym obok testu. Test zakończy się niepowodzeniem, jeśli te dwie migawki nie pasują do siebie: albo zmiana jest nieoczekiwana, albo referencyjna migawka musi zostać zaktualizowana do nowej wersji wyniku.
Używanie snapshotów
Aby utworzyć migawkę dla wartości, możesz użyć toMatchSnapshot()
z API expect()
:
import { expect, it } from 'vitest';
it('toUpperCase', () => {
const result = toUpperCase('foobar');
expect(result).toMatchSnapshot();
});
Podczas pierwszego uruchomienia tego testu, Vitest utworzy plik migawki, który wygląda następująco:
// Vitest Snapshot v1, https://www.getbook.com/pl/book/vitest-0/guide/snapshot
exports['toUpperCase 1'] = '"FOOBAR"';
Migawka powinna być commitowana wraz ze zmianami w kodzie i sprawdzana w ramach procesu przeglądu kodu. Przy kolejnych uruchomieniach testów, Vitest porówna wygenerowany wynik z zapisaną migawką. Jeśli są zgodne, test zakończy się pomyślnie. Jeśli nie są zgodne, albo program testowy znalazł błąd w twoim kodzie, który należy naprawić, albo implementacja uległa zmianie i migawka musi zostać zaktualizowana.
WARNING
Podczas korzystania ze snapshotów w asynchronicznych testach współbieżnych, należy użyć expect
z lokalnego Kontekstu Testowego, aby upewnić się, że właściwy test jest wykrywany.
Snapshoty wbudowane
Alternatywnie, możesz użyć toMatchInlineSnapshot()
, aby zapisać migawkę bezpośrednio w pliku testowym.
import { expect, it } from 'vitest';
it('toUpperCase', () => {
const result = toUpperCase('foobar');
expect(result).toMatchInlineSnapshot();
});
Zamiast tworzyć oddzielny plik migawki, Vitest zmodyfikuje bezpośrednio plik testowy, aby zaktualizować migawkę jako ciąg znaków:
import { expect, it } from 'vitest';
it('toUpperCase', () => {
const result = toUpperCase('foobar');
expect(result).toMatchInlineSnapshot('"FOOBAR"');
});
Umożliwia to bezpośrednie zobaczenie oczekiwanego wyniku, bez konieczności przełączania się między różnymi plikami.
WARNING
Podczas korzystania ze snapshotów w asynchronicznych testach współbieżnych, należy użyć expect
z lokalnego Kontekstu Testowego, aby upewnić się, że właściwy test jest wykrywany.
Aktualizowanie snapshotów
Gdy otrzymana wartość nie pasuje do migawki, test kończy się niepowodzeniem i wyświetla różnicę między nimi. Jeśli zmiana migawki jest zamierzona, możesz zaktualizować migawkę do bieżącego stanu.
W trybie watch, możesz nacisnąć klawisz u
w terminalu, aby bezpośrednio zaktualizować nieudaną migawkę.
Możesz też użyć flagi --update
lub -u
w CLI, aby Vitest zaktualizował migawki.
vitest -u
Snapshoty plików
Podczas wywoływania toMatchSnapshot()
, wszystkie migawki są przechowywane w sformatowanym pliku .snap
. Oznacza to, że musimy stosować znaki ucieczki dla niektórych znaków (takich jak podwójny cudzysłów "
i backtick ```) w ciągu migawki. Może to również spowodować utratę podświetlania składni dla zawartości migawki (np. kodu w określonym języku).
Aby rozwiązać ten problem, wprowadzamy toMatchFileSnapshot()
, która umożliwia zapisywanie migawek bezpośrednio w plikach. Pozwala to przypisać dowolne rozszerzenie pliku migawki, zwiększając jego czytelność.
import { expect, it } from 'vitest';
it('render basic', async () => {
const result = renderHTML(h('div', { class: 'foo' }));
await expect(result).toMatchFileSnapshot('./test/basic.output.html');
});
Porównuje zawartość z plikiem ./test/basic.output.html
. Użyj flagi --update
, aby zapisać zmiany.
Snapshoty obrazów
Można również tworzyć snapshoty obrazów za pomocą jest-image-snapshot
.
npm i -D jest-image-snapshot
test('image snapshot', () => {
expect(readFileSync('./test/stubs/input-image.png')).toMatchImageSnapshot();
});
Możesz dowiedzieć się więcej z przykładu examples/image-snapshot
.
Niestandardowy Serializer
Możesz dodać własną logikę, aby zmienić sposób serializacji snapshotów. Podobnie jak w Jest, Vitest ma domyślne serializatory dla wbudowanych typów JavaScript, elementów HTML, ImmutableJS i elementów React.
Przykładowy moduł serializatora:
expect.addSnapshotSerializer({
serialize(val, config, indentation, depth, refs, printer) {
// `printer` to funkcja, która serializuje wartość za pomocą istniejących wtyczek.
return `Pretty foo: ${printer(val.foo)}`;
},
test(val) {
return val && Object.prototype.hasOwnProperty.call(val, 'foo');
},
});
Po dodaniu testu takiego jak ten:
test('foo snapshot test', () => {
const bar = {
foo: {
x: 1,
y: 2,
},
};
expect(bar).toMatchSnapshot();
});
Otrzymasz następującą migawkę:
Pretty foo: Object {
"x": 1,
"y": 2,
}
Vitest wykorzystuje pretty-format
z Jesta do serializacji snapshotów. Więcej informacji znajdziesz tutaj: pretty-format.
Różnice w porównaniu z Jestem
Vitest zapewnia niemal w pełni kompatybilną funkcjonalność snapshotów z Jestem, z kilkoma wyjątkami:
1. Nagłówek komentarza w pliku snapshotu jest inny {#_1-comment-header-in-the-snapshot-file-is-different}
- // Jest Snapshot v1, https://goo.gl/fbAQLP
+ // Vitest Snapshot v1, https://www.getbook.com/pl/book/vitest-0/guide/snapshot
To w rzeczywistości nie wpływa na funkcjonalność, ale może wpłynąć na różnicę w zatwierdzeniu (commit diff) podczas migracji z Jesta.
2. printBasicPrototype
domyślnie ustawione na false
{#_2-printbasicprototype-is-default-to-false}
Migawki zarówno Jesta, jak i Vitesta są oparte na pretty-format
. W Vitest domyślnie ustawiamy printBasicPrototype
na false
, aby zapewnić czystszy wynik snapshotu, podczas gdy w Jest <29.0.0 domyślnie jest to true
.
import { expect, test } from 'vitest';
test('snapshot', () => {
const bar = [
{
foo: 'bar',
},
];
// w Jest
expect(bar).toMatchInlineSnapshot(`
Array [
Object {
"foo": "bar",
},
]
`);
// w Vitest
expect(bar).toMatchInlineSnapshot(`
[
{
"foo": "bar",
},
]
`);
});
Uważamy, że to bardziej rozsądna wartość domyślna dla czytelności i ogólnego DX. Jeśli nadal wolisz zachowanie Jesta, możesz zmienić konfigurację:
// vitest.config.js
export default defineConfig({
test: {
snapshotFormat: {
printBasicPrototype: true,
},
},
});
3. Znak >
jest używany jako separator zamiast dwukropka :
dla niestandardowych wiadomości {#_3-chevron-is-used-as-a-separator-instead-of-colon-for-custom-messages}
Vitest używa znaku >
zamiast dwukropka :
jako separatora w niestandardowych wiadomościach podczas tworzenia migawek, co poprawia czytelność.
Dla następującego przykładowego kodu testowego:
test('toThrowErrorMatchingSnapshot', () => {
expect(() => {
throw new Error('error');
}).toThrowErrorMatchingSnapshot('hint');
});
W Jest, migawka będzie wyglądać następująco:
exports[`toThrowErrorMatchingSnapshot: hint 1`] = `"error"`;
W Vitest, równoważna migawka będzie wyglądać następująco:
exports[`toThrowErrorMatchingSnapshot > hint 1`] = `"error"`;