Регресійне тестування
Регресійне тестування — це практика швидко помічати регресію, тобто коли те, що працювало, перестає працювати, а ніхто не збирався його чіпати. Набір, який вона породжує, найкраще розуміти як памʼять організації: запис усього, чого систему вже навчили, у формі, яку можна відтворити. Складне тут не в написанні кейсів. Складне — вирішити, що заслуговує на постійне місце, що запускати, коли весь набір надто повільний, і що робити з кейсом, який падає без причини.
- Відповідає на
- Чи зламали ми минуле?
- Правило входу
- Це вже ставалося
- Правило виходу
- Поведінка зникла
Регресія — це порушена обіцянка, про яку ви не знали
Кожна робоча програма — це набір обіцянок. Частина записана як вимоги, частина живе в контракті з іншою командою, а дуже багато існує лише тому, що користувач збудував на них звичку. Регресія стається, коли зміна порушує одну з цих обіцянок без жодного наміру: розробник змінив правило округлення для рахунків, а нарахування бонусів, що тихо користувалося тим самим хелпером, почало платити на три копійки менше.
Цей приклад містить увесь механізм. Регресії виникають зі звʼязності, якої не видно з коду, що ви редагуєте: спільна функція, спільна таблиця, спільний кеш, неявний порядок, значення конфігурації, яке дві фічі читають із різних причин. Ніхто не є недбалим. Радіус ураження зміни просто не видно зсередини самої зміни, і він росте з кожним роком життя системи.
Що заслуговує на постійний кейс — і що заслуговує на видалення
Набір без правила входу росте за смаком, а смак не має верхньої межі. Працює вузьке правило: кейс заслуговує на постійність, коли поведінка вже довела свою вагу. Це доводять чотири речі, і «комусь здалося, що так ретельніше» серед них немає.
Баг, що дійшов до користувача
Найсильніше джерело з усіх. Уже доведено, що це може зламатися, що ніщо цього не спіймало і що заплатив хтось поза командою.
Розбір інциденту
Розбір називає умову, яку ніхто не перевіряв. Перетворення цього речення на кейс — єдина частина розбору, що переживає квартал.
Обіцяна поведінка
Опублікована форма відповіді API, договірний SLA, вимога регулятора. Обіцянка існує незалежно від тесту, — тож нехай тест теж існує.
Шлях, яким ідуть гроші
Оформлення, білінг, виплати, повернення. Збої тут ловлять не тікетами від користувачів, а бухгалтер через три тижні.
Правило виходу суворіше, і саме його команди роблять неправильно. Кейс залишає набір, коли поведінка залишає продукт: фічу прибрали, правило свідомо змінили, ендпоінт вивели з експлуатації. Він не залишає набір тому, що повільний, дратує чи впав сьогодні вранці, коли реліз — сьогодні. Видалення кейса з цих причин видаляє памʼять про баг, заради якого його писали, і тепер той баг може повернутися так, що на нього ніхто не дивиться.
Справжня проблема: набір надто повільний, щоб запускати весь
Кожен регресійний набір колись перетинає межу. Він росте щорелізу, майже ніколи не втрачає кейсів, і одного дня запуск усього на кожну зміну триває сорок хвилин — довше, ніж чекатиме розробник, тож люди перестають чекати. Відтоді цікаве питання вже не «що тестувати», а «яка підмножина запускається в який момент», і це рішення про ризик і швидкість зворотного звʼязку, а не рядок, який хтось колись вписав у CI.
| Стратегія відбору | Як вирішує | Чого вам коштує |
|---|---|---|
| Запускати все й завжди | Жодного рішення: увесь набір на кожну зміну. | Працює чудово, доки не перестає. Коли очікування перевищує терпіння, люди починають мерджити, не читаючи результат. |
| Рівні за частотою | Швидкий рівень на кожен коміт, середній — на кожен мердж, усе — щоночі й перед релізом. | Регресія може ховатися добу. Відповідь за замовчуванням для більшості команд і найлегша для пояснення. |
| Відбір за ризиком | Людина вирішує, які ділянки загрожує зачепити зміна, і запускає їх — виходячи з того, як система реально звʼязана. | Настільки добре, наскільки добра модель системи в голові людини, — і тихо псується, коли вона забуває або йде. |
| Аналіз впливу змін | Інструмент будує мапу, які тести виконують який код, і запускає лише ті, що торкаються змінених рядків. | Справжнє прискорення на великих кодових базах, але сліпий до звʼязності через дані, конфігурацію й час. |
| Розпаралелити замість відбирати | Розділити набір на багато машин, щоб усе завершувалося за час найповільнішого шарда. | Купує роки, не послаблюючи покриття, а натомість коштує грошей та ізольованих тестових даних. |
Корисне значення за замовчуванням: спершу паралелити, далі — рівні, і скептично ставитися до хитрого відбору. Купити машини дешевше, ніж інженер, що зʼясовує, чому регресія проскочила крізь розумну підмножину, — і кожна схема відбору сліпа в одному й тому ж місці: у звʼязності через спільні дані та спільну конфігурацію, а саме звідти й беруться регресії. Хоч що ви оберете, одне правило не обговорюється: повний набір запускається перед релізом, без винятків, бо цей запуск — останній момент, коли памʼять повна.
Нестабільність, тестові дані й витрати, яких ніхто не планує
Регресійний набір має вартість утримання, що приходить незалежно від того, чи хтось її планував. Кейси ламаються, коли редизайнять інтерфейс, коли API додає поле, коли зсуваються фікстури, коли дата переходить через межу року. Плануйте це утримання явно — частку кожного спринту, — бо альтернатива не є дешевшим набором. Альтернатива — набір, що псується, доки його не почнуть ігнорувати; це коштує стільки ж і не захищає нічого.
Карантин — правильний хід
- Кейс прибирають із блокувальних воріт того ж дня, коли підтвердили нестабільність.
- Він далі запускається і далі звітує — в окремий список із названим власником.
- До нього чіпляють дедлайн: полагодити за два тижні або покрити поведінку інакше.
- Набір лишається таким, якому вірять, — а це єдина властивість, що надає червоному результату сенсу.
Перезапускати до зеленого — пастка
- Сьогодні не коштує нічого — саме тому за місяць стає поведінкою за замовчуванням.
- Привчає всіх, що червоний результат означає «натисни ще раз», а не «зупинись».
- Ховає справжні плаваючі баги: гонки ззовні виглядають точно як нестабільні тести.
- Закінчується набором, якого ніхто не читає, і релізом, що спирається на сподівання.
Більшість нестабільності має одну з чотирьох причин, і назвати їх — значить перетворити містику на робочу задачу. Час: тест перевіряє, поки застосунок не завершив, — лікується очікуванням умови, а не тривалості. Спільний стан: два кейси користуються тим самим акаунтом чи рядком, тож окремо проходять, а разом падають. Середовище: повільна мережа, холодний кеш, сусід, що завантажив машину. І справжня недетермінованість у самому коді — це взагалі не проблема тесту: це баг, який тест знайшов, а всі вирішили назвати нестабільністю.
Антипатерни, які варто назвати
- Набір, що лише росте, без правила виходу: третина його тестує поведінку, якої в продукті вже немає.
- Регресія, запланована фазою перед релізом, а не запущена постійно: дефекти тоді знаходять у найгірший можливий момент.
- Кожен регресійний кейс написаний як браузерний тест, бо саме це належить QA, — навіть там, де API-тест довів би те саме в сто разів швидше.
- Список карантину без власника й дедлайну — це цвинтар із оптимістичнішою назвою.
- Міряти набір кількістю кейсів чи покриттям коду, а не дефектами, що втекли до користувачів, — а це єдине число, що описує, чи він працює.
Коли це застосовувати
Застосовуйте, коли
- Будь-яка система, яку ще змінюватимуть, — тобто кожна, яку не вимикають цього місяця.
- Одразу після виправлення бага: підтвердьте виправлення, а потім лишіть кейс назавжди, щоб баг не повернувся непоміченим.
- Навколо всього, до чого причеплена обіцянка: опублікованого API, договірного SLA, регуляторного розрахунку.
- Поділеним на рівні за частотою, щойно повний набір стає повільнішим за очікування, яке люди справді терплять.
Уникайте, коли
- Як фазу, що виконується лише перед релізом: знайдена тоді регресія знайдена в найдорожчий момент.
- Додавати кейс на кожен сценарій, який хтось уявив: вийде набір, надто повільний для запуску й надто великий для утримання.
- На рівні браузера для логіки, яку довів би API- чи юніт-тест: те саме покриття коштує в сто разів більше і в запуску, і в лагодженні.
- З нестабільними кейсами всередині блокувальних воріт: перший проігнорований червоний результат — це момент, коли набір перестав працювати.
Було корисно?
Поділіться з тим, хто працює над тією ж задачею.