Тестування з допомогою знімків
Тестування з використанням знімків - це дуже корисний інструмент, коли ви хочете бути впевнені, що у вашому UI не відбулося несподіваних змін.
Типовий тестовий сценарій для тестування знімками виконує рендер UI компонента, робить знімок файлової системи та порівнює його з файлом знімку, який зберігається разом з тестом. Тест викличе помилку, якщо два зображення не збігаються: відбулась неочікувана зміна або знімок повинен бути оновлений відповідно до нової версії UI компонента.
Тестування знімками з Jest
Аналогі чний підіхід може бути використано, коли заходить мова про тестування React компонентів. Замість рендеру грфічного UI, що може вимагати збирання всього додатку, ви можете використати тестовий рендерер, щоб швидко згенерувати дерево компонентів React, яке можна серіалізувати. Consider this example test for a Link component:
import renderer from 'react-test-renderer';
import Link from '../Link';
it('renders correctly', () => {
const tree = renderer
.create(<Link page="http://www.facebook.com">Facebook</Link>)
.toJSON();
expect(tree).toMatchSnapshot();
});
Під час першого запуску цього тесту, Jest створює снепшот файл, який виглядає наступним чином:
exports[`renders correctly 1`] = `
<a
className="normal"
href="http://www.facebook.com"
onMouseEnter={[Function]}
onMouseLeave={[Function]}
>
Facebook
</a>
`;
Знімок повинен бути доданий до системи конролю версій разом зі змінами коду, що дозволить переглянути його в процесі code review. Jest uses pretty-format to make snapshots human-readable during code review. Під час наступних запусків тесту, Jest порівняє результат роботи компонента зі збереженим знімком. Якщо вони співпадуть, тест пройде. Якщо ж вони будуть різні, то або тест знайшов проблему у вашому коді (в цьому випадку, в компоненті <Link>
) і вона має бути виправлена, або реалізація компонента змінилася і знімок має бути оновлений.
Знімок знаходиться в тій же ж області, що й дані, які ви рендерите, — у нашому прикладі, компонент <Link>
з переданою йому властивістю page
. Через це, навіть якщо будь-якому іншому файлу бракує властивостей (скажімо, App.js
) в компоненті <Link>
, тест все одно пройде успішно, бо він не має інформації про використання компоненту <Link>
та прив'язаний лише до контексту Link.js
. Also, rendering the same component with different props in other snapshot tests will not affect the first one, as the tests don't know about each other.
Більше інформації про те, як працює тестування знімками можна знайти в блог пості. Ми рекомендуємо прочитатицей блог пост, щоб зрозуміти, коли вам варто використовувати тестування знімками. Ми також рекомендуємо переглянути відео на Egghead про тестування знімками з Jest.
Оновлення знімків
Дуже просто помітити, коли тест з використанням знімків падає після того, як з’явилася помилка в коді. Коли таке трапляється, просто виправте помилку і переконайтеся, що ваші тести знову проходять успішно. Тепер давайте поговоримо про випадок, коли тест зі знімком падає внаслідок навмисної зміни коду.
Така ситуація може виникнути, якщо ми навмисно змінимо адресу, на яку вказує компонент Link з нашого прикладу.
// Оновлений тестовий сценарій з Link для іншої адреси
it('renders correctly', () => {
const tree = renderer
.create(<Link page="http://www.instagram.com">Instagram</Link>)
.toJSON();
expect(tree).toMatchSnapshot();
});
В цьому випадку Jest видасть наступний вивід:
Оскільки ми щойно оновили наш компонент, щоб він вказував на іншу адресу, логічно очікувати зміну знімка цього компонента. Наш тест зі знімком падає, оскільки знімок для оновленого компонента більше не співпадає зі збереженим знімком для цього теста.
To resolve this, we will need to update our snapshot artifacts. You can run Jest with a flag that will tell it to re-generate snapshots:
jest --updateSnapshot
Просто прийміть зміни запустивши команду вище. Ви також можете використати еквівалентий параметр -u
для перегенерації знімків. Це перегенерує знімки для всіх тестів, які впали через неспівпадіння знімків. Якби у нас були тести зі знімками, які падали через помилку в коді, нам варто було б виправити ці проблеми до перегенерації знімків, щоб запобігти створенню знімків для неправильної поведінки.
Якщо ви хочете обмежити список тестів, для яких потрібно перегенерувати знімки, ви можете вказати параметр --testNamePattern
, щоб повторно записати знімки тільки для тестів, які відповідають вказаному шаблону.
You can try out this functionality by cloning the snapshot example, modifying the Link
component, and running Jest.
Інтерактивний режим знімка
Failed snapshots can also be updated interactively in watch mode:
Once you enter Interactive Snapshot Mode, Jest will step you through the failed snapshots one test at a time and give you the opportunity to review the failed output.
From here you can choose to update that snapshot or skip to the next:
Once you're finished, Jest will give you a summary before returning back to watch mode:
Вбудовані знімки
Inline snapshots behave identically to external snapshots (.snap
files), except the snapshot values are written automatically back into the source code. This means you can get the benefits of automatically generated snapshots without having to switch to an external file to make sure the correct value was written.
Example:
First, you write a test, calling .toMatchInlineSnapshot()
with no arguments:
it('renders correctly', () => {
const tree = renderer
.create(<Link page="https://example.com">Example Site</Link>)
.toJSON();
expect(tree).toMatchInlineSnapshot();
});
The next time you run Jest, tree
will be evaluated, and a snapshot will be written as an argument to toMatchInlineSnapshot
:
it('renders correctly', () => {
const tree = renderer
.create(<Link page="https://example.com">Example Site</Link>)
.toJSON();
expect(tree).toMatchInlineSnapshot(`
<a
className="normal"
href="https://example.com"
onMouseEnter={[Function]}
onMouseLeave={[Function]}
>
Example Site
</a>
`);
});