Наскрізне тестування (E2E)
Наскрізний тест проходить зібрану систему так, як це зробила б людина: крізь справжній інтерфейс, через усі сервіси, зі справжньою конфігурацією, до справжнього результату. Це єдиний рівень, здатний довести, що частини тримаються разом, — і водночас найповільніший, найдорожчий в утриманні й найсхильніший падати з причин, не повʼязаних із вашою зміною. Обидві половини цього речення правдиві одночасно, і саме тому правильна кількість E2E-тестів мала, а не нульова.
- Доводить
- Що частини тримаються
- Ціна кейса
- Найвища серед рівнів
- Правильна кількість
- Мала, не нульова
Єдине, чого не доведе жоден інший рівень
Кожен рівень нижче за наскрізний тестує щось у контрольованих умовах. Юніт-тест замінює сусідів підробками. Інтеграційний бере справжню базу, але заглушений платіжний провайдер. Контрактний тест доводить, що два сервіси згодні щодо форми повідомлення, — і жоден із них не запускає інший. Усе це цінне, і ніщо з цього не скаже вам, що розгорнута система з її справжньою маршрутизацією, справжніми змінними середовища, справжніми сесіями та справжньою збіркою фронтенду дозволяє людині завершити те, заради чого вона прийшла.
Ця прогалина не теоретична. Класичний дефект, що втікає з добре протестованої системи, — не хибний розрахунок, а неправильний редирект, прапорець cookie, що ламає сесію в справжньому браузері, фіче-флаг, увімкнений на стейджингу й вимкнений у продакшні, заголовок CORS, який важить лише тоді, коли фронтенд віддається зі свого справжнього домену. Кожне з цього має повне зелене покриття на всіх нижчих рівнях, бо кожен нижчий рівень підмінив саме те, що зламалося.
Чого насправді коштує місце на вершині
Час виконання — очевидна вартість і найменш важлива. Справжня витрата — відстань між падінням і його причиною. Коли падає юніт-тест, ви дивитеся на одну функцію. Коли падає наскрізний, ви дивитеся на браузер, фронтенд, три сервіси, чергу, базу й середовище, і винним може бути будь-хто з них — включно з ніким, бо тест міг просто відпрацювати швидше за застосунок.
| Чому E2E став червоним | Типова частка падінь | Що це насправді означає |
|---|---|---|
| Застосунок справді зламаний | Меншість | Причина, заради якої тест існує. Усе нижче — податок за збереження цього сигналу. |
| Тест перевірив раніше, ніж застосунок завершив | Найбільша окрема причина | Помилка часу в тесті. Очікування умови замість тривалості прибирає майже все. |
| Дані були не такими, як припускав тест | Дуже часто | Проблема спільного середовища. Кейси, що створюють власні дані й прибирають, це спиняють. |
| Селектор змінився при редизайні | Часто | Утримання, не дефект. Стабільні test-id переносять цю ціну з кожного релізу на один раз. |
| Третя сторона повільна або лежить | Час від часу й дратівливо | Відкладене рішення: які залежності є частиною тесту, а які заглушені на межі мережі. |
Читайте цю таблицю як бюджет, а не як скаргу. Набір із шістдесяти наскрізних кейсів із двовідсотковою ймовірністю падіння кожного стає червоним приблизно у двох запусках із трьох, навіть коли все гаразд, — тому «просто додамо ретраї» є хибним першим кроком, а той самий набір удесятеро більший не вдесятеро цінніший, а вдесятеро ймовірніше проігнорований.
Обирайте шляхи, а не фічі
Помилка відбору, якої припускається майже кожна команда, — писати по одному наскрізному тесту на фічу. Фічі — це те, як влаштований беклог; це не те, як людина рухається продуктом, і покриття їх одна за одною дає сотні повільних кейсів, які здебільшого повторно доводять логіку, вже доведену нижче. Обирайте натомість шляхи: невелику кількість маршрутів, які користувач справді проходить, і кожен перетинає кілька сервісів — саме цей перетин і є предметом тесту.
Шлях грошей
Перегляд, кошик, оплата, підтвердження. Якщо E2E-тест лише один, то це він: він перетинає кожен сервіс, від якого залежить бізнес.
Увійти й лишитися
Реєстрація, підтвердження, вхід, збереження сесії після перезавантаження. Поведінка сесій і cookie невидима для всіх нижчих рівнів.
Шлях через межу
Дія у вебзастосунку, яку завершує фоновий воркер і підтверджує лист. Ніщо нижче не доведе, що передача справді стається в реальному розгортанні.
Шлях із жорстким правилом
Межа доступу, перевірка віку, обовʼязкове розкриття. Там, де помилка є юридичною подією, а не тікетом у підтримку.
Корисна евристика розміру: один кейс на маршрут, втрати якого бізнес не пережив би, плюс один на кожен інтеграційний шов, що існує лише в розгорнутій системі. Для більшості продуктів це десь від десяти до сорока кейсів. Якщо у вас сотні — набір не ретельніший за інші: він тягне роботу, місце якої на два рівні нижче, і платить за це найвищу в кодовій базі ціну за кейс.
Як зробити малий набір таким, якому вірять
Наскрізний набір, якому вірять, — це не питання кращих перевірок. Він виникає з усунення всіх джерел варіації, крім тієї поведінки, що тестується, і пʼять із них варто прибрати свідомо.
- Чекайте на умову, ніколи на тривалість. Фіксована пауза або надто коротка на завантаженій машині, або витрачена даремно на швидкій; очікування елемента, відповіді чи стану і швидше, і стабільніше.
- Дайте кожному кейсу власні дані. Він створює потрібні акаунт, замовлення, документ — і прибирає їх після себе. Кейс, що залежить від рядка, створеного кимось іншим, — це кейс, що падає у вівторок без причини.
- Обирайте елементи за тим, що існує для тестування: стабільний test-id або доступна роль та імʼя, — і ніколи за CSS-класом чи позицією в DOM: обидва змінюються щоразу, коли дизайнер торкається сторінки.
- Явно вирішіть, які треті сторони входять у тест. Пісочниця платежів зазвичай так; поштовий провайдер, картографічний API та аналітика — зазвичай ні, і заглушка на межі мережі тримає тест про вашу систему.
- Збирайте при падінні достатньо, щоб діагностувати без відтворення: трасу, відео, мережевий лог і консоль браузера. Ціна падіння E2E — це розслідування, і саме артефакти його скорочують.
Ретраї потребують політики, а не значення за замовчуванням. Повтор усього кейса ховає справжні плаваючі баги, бо гонка у вашому застосунку ззовні виглядає точно як нестабільний тест, — і повтор перетворює справжній дефект на зелену галочку. Захисний варіант: не більше одного повтору, кожен повтор записується як повноцінний сигнал, а кейс, якому знадобився повтор двічі за тиждень, іде в карантин. Набір, чий зелений результат тримається на ретраях, не зелений — він невиміряний.
Антипатерни, які варто назвати
- Один довгий кейс на пʼятнадцять екранів: коли він падає, ви дізнаєтеся лише, що щось із пʼятнадцяти екранів зламане.
- Кейси, що залежать від порядку запуску: падіння третього каскадом валить ще шість, і звіт не описує нічого.
- Запуск набору лише щоночі: регресію приписують дню мерджів, а не конкретному коміту.
- Набір проти вручну доглянутого середовища, яке ніхто не може перезібрати: він падає з причин середовища частіше, ніж коду.
- Паузи, розсипані кодом як стандартний засіб від нестабільності: ви міняєте хвилини часу на проблему, що все одно повертається.
Коли це застосовувати
Застосовуйте, коли
- Для жменьки маршрутів, втрати яких бізнес не пережив би, — кожен перетинає кілька сервісів у розгорнутій системі.
- Для поведінки, що існує лише коли справжні частини зʼєднані: сесії, редиректи, конфігурація, результат збірки фронтенду.
- Проти середовища, перезібраного з того самого артефакту, що їде в реліз, — щоб проходження щось казало про продакшн.
- Розділеним на паралельні воркери, щоб набір був досить швидким для запуску на кожен мердж, а не раз на ніч.
Уникайте, коли
- Для правил валідації, текстів помилок, сортування й арифметики — усього, що компонентний чи API-тест доводить за мілісекунди.
- Як основне тіло набору тестів: тут найвища ціна за кейс і найбільша відстань від падіння до причини.
- Проти спільного довгоживучого середовища з даними, зробленими руками: тоді кожен результат залежить від того, що колега зробив годину тому.
- Зі суцільними ретраями заради зеленого пайплайна: так справжні плаваючі дефекти перетворюються на успішні запуски.
Було корисно?
Поділіться з тим, хто працює над тією ж задачею.