Тестирование при помощи снимков
Тестирование с использованием снимков это очень полезный инструмент в ситуациях где вы хотите быть уверены, что ваш пользовательский интерфейс не изменяется неожиданным образом.
Типичный тест с использованием снимков сначала рендерит ваш UI-компонент, создает снимок на основе рендера, затем сранивает его с эталонным снимком, который хранится вместе с тестом. Тест считается проваленным, если снимки не совпадают: либо измне ние непредвиденно, либо снимок нуждается в обновлении до акутальной версии UI-компонента.
Тестирование с использованием снимков в Jest
Похожий подход может быть использован, когда дело доходит до тестирования React компонентов. Вместо отображения графического пользовательского интерфейса, что потребует сборки всего приложения, разработчик может использовать специализированный модуль для генерации сериализуемого значения для конкретного 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();
});
The first time this test is run, Jest creates a snapshot file that looks like this:
exports[`отображается корректно 1`] = `
<a
className="normal"
href="http://www.facebook.com"
onMouseEnter={[Function]}
onMouseLeave={[Function]}
>
Facebook
</a>
`;
Данный артефакт снимка следует занести в систему контроля версий наряду с изменениями в коде как часть вашего процесса по ревью кода. Jest uses pretty-format to make snapshots human-readable during code review. При последующих запусках теста, Jest будет сравнивать сгенерированный вывод с предыдущим артефактом снимка. Если они совпадают, то тест успешно завершится. Если они не совпадают или программа для запуска тестов находит ошибку в вашем коде (в данном случае компонент <Link>
), которые следует исправить, или реализация была изменена и артефакт снимка нуждается в обновлении.
The snapshot is directly scoped to the data you render – in our example the <Link>
component with page
prop passed to it. This implies that even if any other file has missing props (say, App.js
) in the <Link>
component, it will still pass the test as the test doesn't know the usage of <Link>
component and it's scoped only to the 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.
Более подробную информацию о том как тестирование с использованием снимков работает и почему мы ее реализовали можно найти в данной записи нашего блога. Ме рекомендуем ознакомиться со следующей записью, чтобы получить хорошее представление о том, когда использовать тестирование с использованием снимков. We also recommend watching this egghead video on Snapshot Testing with Jest.
Обновление снимков
Если был введен баг, то довольно просто обнаружить тест со снимком, который проваливается. Когда такое происходит, устраните проблему и убедитесь, что ваши тесты завершаются успешно. А теперь давайте поговорим о случае, когда тест проваливается по причине осознанных изменений в реализации.
Подобная ситуация може возникнуть если мы намеренно внесем изменения в адрес ссылки внутри компонента Link в нашем примере.
// Updated test case with a Link to a different address
it('renders correctly', () => {
const tree = renderer
.create(<Link page="http://www.instagram.com">Instagram</Link>)
.toJSON();
expect(tree).toMatchSnapshot();
});
В этом случае Jest выведет следующее сообщение:
Так как мы только что изменили наш компонент так, чтобы он указывал на другой адрес, то разумно ожидать изменений в снимке этого компонента. Наш тест с использованием снимка проваливается потому, что текущий снимок более не совпадает с сохраненным.
Чтобы решить эту проблему, нам нужно будет обновить сохраненный снимок. Вы можете запустить Jest с флагом, который укажет на необходимость повторной генерации снимков:
jest --updateSnapshot
Не ждите и примените внесенные изменения, выполнив команду указанную выше. Вы также можете использовать эквивалентный односимвольный флаг -u
для повторного создания снимков, если предпочитаете. Это создаст и сохранит новый снимок для всех проваливающихся тестов использующих снимки. Если бы существовали дополнительные проваливающиеся тесты ввиду непреднамеренных неполадок, нам бы понадобилось исправить неполадки перед обновлением снимков, чтобы избежать сохранения снимков с неполадками в поведении.
Если вы хотите ограничить то, какие снимки будут сохранены заново, вы можете указать дополнительный флаг --testNamePatter
для сохранения снимков лишь для тех тестов, которые совпадают с указанным шаблоном.
You can try out this functionality by cloning the snapshot example, modifying the Link
component, and running Jest.
Interactive Snapshot Mode
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
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.
Пример:
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();
});