Недавно я выступал с докладом на мероприятии сообщества BerlinJS, где хотел поделиться своим недавним опытом тестирования снимков. Несомненно, вы слышали этот термин с тех пор, как он недавно стал популярен в среде тестирования Jest.

Подход к тестированию снимков не является чем-то новым. Впервые я услышал об этом в известной книге М. Фезерса Работа с устаревшим кодом. Подход символьного тестирования нашел у меня отклик, поскольку он прост и идеально подходит для тестирования сложных систем. Однако на тот момент не было хороших инструментов, которые позволили бы легко интегрировать этот подход в процесс разработки.

Позже Ллевеллин Фалько выпустил свою структуру Approval Testing. С моей точки зрения, это был первый подход, позволивший улучшить UX при тестировании снимков.

Давайте немного поговорим об основах тестирования моментальных снимков и увидим, что его применение выходит далеко за рамки простого тестирования компонентов React.

Государство и представительство

При тестировании снимков все сводится к пониманию состояния системы и представления состояния (выходных данных системы).

В зависимости от типа системы у вас есть разные понятия для состояния и представления, чтобы сделать его немного более ясным, я бы попытался описать его для трех разных ролей разработчиков - внешнего интерфейса, внутреннего интерфейса и мобильного.

Front-end люди

В случае приложения на основе Redux состояние - это состояние Redux. Итак, это один большой объект, который содержит значения всех элементов управления пользовательского интерфейса и данные, поступающие с сервера. Если вы используете шаблон MVC для создания приложений, состояние вашего приложения - это комбинация моделей, которые поддерживает приложение.

Представлением состояния является фактический код HTML / CSS (например, созданный React), который отображается браузером как пользовательский интерфейс приложения.

Back-end люди

Очень часто состояние системы представляет собой комбинацию баз данных, памяти, файлов и других служб, к которым система имеет доступ. Итак, все входы / выходы участвуют в поведении системы, формируя ее состояние.

Представление состояния - JSON / HTML / XML или любой другой формат, в котором конечная точка отвечает.

Мобильные люди

Я думаю, это очень похоже на интерфейс, где состояние - это модель (или набор моделей), которую приложение хранит в памяти (или в локальных хранилищах, на основе ключа-значения или на основе SQL).

Состояние отображается в пользовательском интерфейсе, отображаемом мобильной платформой.

Суть тестирования снимков

По сути, тестирование снимков - это способность «заморозить» состояние и получить представление системы (снимок), сериализованное в форме, удобной для компьютеров и людей.

Если система изменилась, мы делаем следующий снимок и сравниваем его с предыдущим.

Если снимки разные, тест станет «красным». Мы решаем, является ли разница «правильным» или «неправильным», и либо «одобряем» следующий снимок, либо исправляем проблему, вызывая регресс.

Позвольте мне объяснить формулу немного подробнее,

f() - функция, поведение системы;

State - состояние, данные, поступающие в систему на входе;

R - представление вывода системы;

Самая важная вещь для тестирования моментальных снимков - это иметь возможность получить представление в форме, которую легко понять (прочитать) и сравнить с предыдущим состоянием (diff).

Читаемость

Несмотря на модульное тестирование с утверждениями, где вы выражаете ожидаемый результат как,

expect(result).toEqual(something);

Со снимками вы не знаете, что такое «что-то». Однако вы видите, как «это похоже». Поскольку вы должны сделать вывод, правильно ли представление снимка или нет, его удобочитаемость становится решающей.

Способность различать

В то же время формат представления должен быть пригоден для разграничения.

Итак, вот и проблема,

Чем лучше читаемый формат, тем меньше он несовместим с другими.

Давайте рассмотрим пару примеров.

1. У нас есть система бухгалтерской отчетности, которая представляет собой базу данных со всеми счетами-фактурами, расходами, клиентами и т. Д., А на выходе получается файл PDF для годового отчета. PDF-файл легко читать, но, поскольку это двоичный формат, трудно различать и, кроме того, понять, что именно изменилось, прочитав разницу.

2. У нас есть веб-приложение с набором различных компонентов на экране, мы можем представить состояние как реальный HTML-код, который идеально подходит для различий, но наш мозг не является браузером, поэтому сложно визуализировать этот HTML-код в уме, поэтому даже если мы сможем его прочитать, то трудно сделать вывод, что он «выглядит» правильно.

Поэтому важно поддерживать правильный баланс между этими двумя свойствами.

К счастью, на практике мы имеем дело с простыми представлениями небольших файлов JSON или HTML, которые легко понять и сравнить.

Преимущества тестирования снимков

  1. Как я упоминал выше, подход к тестированию более простой со снимками состояния. Да, это больше не метод «сначала тестирование», а метод «тестирование после». Вы пишете код; вы проверяете это; вы получаете представление и замораживаете его до следующего тестового прогона.
  2. Он подходит для сложных представлений в виде больших выходных данных JSON и HTML, поэтому вместо сотен assert() вызовов у вас есть один .toMatchSnapshot() вызов.
  3. Снимок становится визуализацией изменений кода. В рамках базы кода и запросов на вытягивание вы сразу видите, что делают изменения кода, просматривая изменения в моментальных снимках.

Слайды этого выступления доступны здесь:

https://speakerdeck.com/alexbeletsky/snapshot-testing-going-beyond-ui

Если вас интересует тестирование снимков с помощью Mocha, ознакомьтесь с моей предыдущей статьей:

https://medium.com/blogfoster-engineering/how-to-use-the-power-of-jests-snapshot-testing-without-using-jest-eff3239154e5