Повне end-to-end покриття коштує дорого — і ще дорожче в підтримці: кожен додатковий сценарій це ще одна річ, яка може стати flaky, ще кілька хвилин на кожен pull request, ще одна причина, чому інженери починають ігнорувати червоний CI. Smoke-набір, який виконується за хвилини, виявляє саме ті збої, що реально блокують запуск: зламаний login, непрацюючий платіжний формуляр, регресія навігації. Це інша мета, ніж «протестувати все», і вона впливає на те, як набір проєктується з першого ж тесту.
Десять сценаріїв, а не сотня
Ми обираємо потоки, що напряму впливають на дохід або утримання: реєстрацію, login, ключову дію в dashboard, заради якої продукт існує, зміну налаштувань і payment або booking — якщо це актуально для продукту. Кожен тест незалежний і за можливості створює власні тестові дані, тому падіння третього тесту ніколи не каскадується у хибні падіння тестів з четвертого по десятий.
Число тут менш важливе за принцип. Десять сфокусованих сценаріїв, яким команда повністю довіряє, кращі за шістдесят, які ніхто не встигає розбирати. Якщо в продукті з'являється новий критичний шлях — новий крок у checkout, новий onboarding-флоу — він отримує місце в smoke-наборі; якщо старий перестає використовуватись, його тест видаляють, а не залишають гнити в статус «на потім», про який ніхто вже не пам'ятає, що погоджував.
Запуск на кожному pull request
Smoke-тести блокують merge у main. У CI вони запускаються в headed-режимі з trace-артефактами при падінні — щоб рев'юери бачили скриншоти й покроковий trace без потреби локально відтворювати збій. Це різниця між п'ятихвилинним поглядом на артефакт CI й двадцятихвилинним відволіканням на те, щоб витягнути гілку й прогнати все вручну.
Блокування merge цим набором працює лише тоді, коли він достатньо швидкий і надійний, щоб інженери не почали сприймати його як шум. Ми тримаємо ціль у межах п'яти хвилин на весь smoke-пакет, паралелізований по воркерах, — саме для того, щоб він ніколи не перетворився на крок, якого чекають з роздратуванням: щойно перевірка починає відчуватись як податок замість страховки, команди знаходять спосіб її обійти.
Стабільні селектори замість хитромудрого XPath
Ми віддаємо перевагу атрибутам data-testid або доступним ролям, погодженим з інженерами, а не CSS-класам чи позиційному XPath, які ламаються від першого ж перепорядкування div'ів дизайнером. Селектори, прив'язані до деталей реалізації, перетворюють будь-який непов'язаний рефакторинг на хвилю падінь тестів, які не мають жодного стосунку до реальної поведінки, яку вони мали перевіряти.
Flaky-тести виправляють або видаляють, а не заговорюють повторними прогонами. Тест, що падає раз на п'ять запусків і проходить кнопкою «re-run», привчає команду взагалі не читати результати CI — червоний пайплайн, який усі ігнорують, строго гірший за відсутність тесту, бо коштує стільки ж підтримки, не даючи натомість жодної впевненості.
Поєднуємо з API-перевірками для payments
Браузерні тести підтверджують те, що бачить користувач: платіжна форма приймає картку, екран підтвердження рендериться, booking з'являється у списку. Вони не той інструмент, щоб перевіряти, що відбувається далі — доставку webhook'ів, зміну стану підписки, логіку повторної спроби після невдалого списання. Для цього окремі API-тести на staging у Stripe test mode або з mock-провайдерами, де побічні ефекти дешево перевіряти й безпечно ламати.
Такий поділ також тримає smoke-набір швидким. UI-тест, що чекає на реальний round-trip webhook'а, — це повільний і подекуди flaky тест з причин, які не мають нічого спільного з інтерфейсом, — саме той тип тестів, який підриває довіру до всього набору.
Ширший нічний набір — опційно
Глибші регресійні пакети — крайові випадки, менш поширені комбінації браузерів і пристроїв, довші користувацькі сценарії — можна запускати вночі на staging, де повільніший набір нікому не блокує день. У день релізу покладаються на smoke плюс коротке вікно ручного exploratory-тестування саме на тих пристроях і браузерах, які автоматизоване покриття охоплює погано — старіші версії Safari, вбудовані webview.
Саме цей поділ — швидко й вузько на кожному PR, ширше й повільніше вночі — дозволяє команді релізити кілька разів на день, не пропускаючи тести й не чекаючи на них.
Що ми свідомо не робимо
Smoke-набір навмисно вузький, і назвати те, чого він не покриває, так само важливо, як і те, що покриває — інакше «у нас є тести» непомітно читається як «у нас повне покриття», а це задає неправильні очікування всім, хто далі по пайплайну на це покладається.
- Pixel-perfect visual regression. Порівняння скриншотів кожного компонента з еталонним зображенням дає стіну хибних спрацювань через різницю в рендерингу шрифтів і антиаліасингу між CI та локальними машинами — заради категорії багів (кілька пікселів не там), яка рідко блокує реліз так, як зламаний login.
- Повна крос-браузерна матриця в CI. Прогін усього smoke-набору на кожній комбінації браузера й ОС на кожному pull request множить час CI заради спадної віддачі; таке покриття має місце в нічному пакеті або періодичних ручних прогонах, а не в блокуванні кожного merge.
- Ціль у 100% покриття кодом. Відсоток покриття показує, які рядки виконались, а не чи справді перевірена поведінка, яка має значення. Гонитва за відсотком заохочує писати тести, що торкаються коду, а не тести, що ловлять збої, які реально зашкодили б релізу.
Пропуск цього — не скорочення шляху, а те, що тримає smoke-набір достатньо швидким, щоб запускати його на кожному без винятку pull request, не викликаючи роздратування, — і саме ця властивість робить його корисним.
Хороший QA — це не максимальне покриття. Це правильні перевірки на правильному етапі пайплайну, які запускаються достатньо послідовно, щоб команда справді довіряла зеленому білду.
