Тестування з допомогою знімків
Тестування з використанням знімків - це дуже корисний інструмент, коли ви хочете бути певні, що ваш UI не змінився несподівано.
Типовий тестовий сценарій для тестування знімками виконує рендер UI компонента, робить знімок екрана і порівнює його з зображенням, яке зберігається разом з тестом. Тест падає, якщо два зображення не співпадають: відбуласа неочікувана зміна або знімок повинен бути оновлений до нової версії UI компонента.
Тестування знімками з Jest #
Аналогічний підіхід може бути використано, коли заходить мова про тестування React компонентів. Замість рендеру грфічного UI, що може вимагати збирання всього додатку, ви можете використати тестовий рендерер, щоб швидко згенерувати дерево компонентів React, яке можна серіалізувати. Розглянемо цей приклад тесту для простого компонету Link:
import React from 'react'; import Link from '../Link.react'; import renderer from 'react-test-renderer'; 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 використовує pretty-format, щоб зробити знімки зручними для читаня під час code-review. Під час наступних запусків теста Jest просто порівняє результат роботи компонента зі збереженим знімком. Якщо вони співпадуть, тест пройде. Якщо ж вони будуть різні, то або тест знайшов проблему у вашому коді і вона має бути виправлена, або реалізація компонента змінилася і змімок має бути оновлений.
Більше інформації про те, як працює тестування знімками можна знайти в блог пості. Ми рекомендуємо прочитатицей блог пост, щоб зрозуміти, коли вам варто використовувати тестування знімками. Ми також рекомендуємо переглянути відео на Egghead про тестування знімками з 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
для перегенерації знімків. Це перегенерує знімки для всіх тестів, які впали через неспівпадіння знімків. Якби у нас були тести зі знімками, які падали через помилку в коді, нам варто було б виправити ці проблеми до перегенерації знімків, щоб запобігти створенню знімків для неправильної поведінки.
Якщо ви хочете обмежити список тестів, для яких потрібно перегенерувати знімки, ви можете вказати параметр --testNamePattern
, щоб повторно записати знімки тільки для тестів, які відповідають вказаному шаблону.
Ви можете спробувати цей функціонал, якщо зклонуєте приклад зі знімками, зміните компонент Link
і запустите Jest.
Тести повинні бути детерміновані #
Ваші тести повинні бути детерміновані. Тобто, запуск однакових тестів декілька разів для компонента, що не змінився, повині давати щоразу однаковий результат. Ви відповідальні за те, щоб ваші знімки не включали в себе специфічні для конкретної платформи або інші недетерміновані дані.
Наприклад, якщо у вас є компонент Clock, який використовує Date.now()
,то знімок, згенерований для цього компонента, буде різний кожного разу під час запуску теста. В такому випадку ми можемо імітувати метод Date.now(), щоб повертати однакове значення кожного разу, коли запускається тест:
Date.now = jest.fn(() => 1482363367071);
Тепер кожного разу, під час виконання тесту зі знімком, Date.now()
повертатиме 1482363367071
. Це призведе до того, що знімок буде однаковим завжди, незалежно від того, коли запущений тест.
Знімки не створюються атоматично на системах безперервної інтеграції (CI) #
Починаючи з Jest 20, знімки не створюються автоматично, коли Jest запускається на системах безперервної інтеграції без явного вказання параметра --updateSnapshot
. Очікується, що всі знімки — це частина коду, який виконується на CI і тому, хоча тести з новими знімки автоматично проходять, вони не повинні проходити на CI. Ми рекомендуємо завжди додавати всі знімки в систему контролю версій.
Часті запитання #
Чи потрібно комітити снепшот файли? #
Так, усі файли зі знімками потрібно додавати в систему контролю версій разом із модулями, які вони покривають та їхніми тестами. До них потрібно ставитися як до частини тестів, схожих на значення будь-якого твердження в Jest. Знімки відображають стан модулів на певний час. Таким чином, коли модулі змінюються, Jest може сказати, які зміни відбулися у порівнянні з попередньою версією. Вони також можуть надати додатковий контекст для code review, завдяки чому рев’ювери можуть краще зрозуміти внесені зміни.
Чи снепшо тестування працює тільки для React компонентів? #
React та React Native компоненти - це вдалі приклади для тестування знімками. Однак, знімки можуть містити будь-яке серіалізоване значення і можуть використовуватись будь-де, де ціллю є тестування того чи вихідні значення правильні. В репозиторії Jest є багато прикладів тестування виводу самого Jest, виводу бібліотеки стверджень Jest і довгих повідомлень з різних частин кодової бази Jest. Перегляньте приклад знімків консольного виводу в репозиторії Jest.
Яка різниця між тестуванням знімками та візуальним регресивним тестуванням? #
Тестування знімками і візуальне регресивне тестування — це два різні способи тестування UI, які слугують різним цілям. Інструменти візуального регресивного тестування роблять знімки веб сторінок і порівнюють результат піксель за пікселем. З тестуванням знімками значення серіалізовані, зберігаються в текстових файлах і поівнюються diff алритмом. Існують різні компроміси для розгляду і ми перерахували причини, чому тестування знімками було створено, в блозі Jest.
Чи замінює тестування знімками юніт тести? #
Тестування знімками — це лише одне з більш ніж 20 тверджень, які надає Jest. Ціль тестування знімками — не замінити існуючі юніт тести, а надати додаткові можливості і зробити тестування безболісним. В деяких сценаріях тестування знімками потенційно може прибрати необхідність юніт тестування для конкретного набору функціональності (анприклад React компонентів), але вони можуть чудово працювати разом.
Яка продуктивність тестування знімками стосовно швидкості і розміру згенерованих файлів? #
Jest було переписано з акцентом на швидкодію і тестування знімками не виключення. Оскільки знімки зберігаються в текстових файлах, цей спосіб тестування швидкий і надійний. Jest генерує новий файл для кожного файлу з тестами, в якому використовується матчер toMatchSnapshot
. Розмір знімків досить маленький: наприклад розмір всіх знімків в кодовій базі Jest менший за 300 КБ.
Як вирішувати конфлікти в файлах зі знімками? #
Файли зі знімками повинні завжди представляти поточний стан модулів, які вони покривають. Таким чином, якщо ви об’єднуєте дві гілки і стикаєтеся з конфліктом в файлах зі знімками, ви можете або вирішити конфлікти вручну або оновити знімки запустивши Jest і переглянувши результат.
Чи можна застосовувати принципи розробки через тестування з тестуванням знімками? #
Хоча і існує можливість писати файли знімків вручну, це все ж недосяжно. Знімки допомагають зрозуміти чи змінився вивід модулів, покритих тестами, а не давати вказівки для дизайну коду модуля.
Чи працює перевірка покриття коду тестами разом з тестуванням знімками? #
Так, так само, як і для будь-яких інших тестів.