Досвідні техніки: передбачення помилок і чеклисти
Зміст
Класи еквівалентності, граничні значення, таблиці рішень — усі ці техніки працюють від специфікації: є вимога, з неї виводяться перевірки. Але частина багів живе там, де специфікація мовчить. Ніде не написано «поле не повинно падати від емодзі» чи «подвійний клік по "Оплатити" не має списати гроші двічі» — це вважається очевидним, тому в вимоги не потрапляє і з вимог не виводиться. Досвідчений тестувальник відкриває нову форму і за десять хвилин знаходить те, що команда пропускала тижнями. Виглядає як магія, а насправді це стиснута статистика: сотні побачених багів перетворилися на здогадки «тут зазвичай ламається».
Досвідні техніки (experience-based test techniques) — це спосіб зняти таку статистику з конкретної голови і зробити з неї робочий інструмент: гіпотези, списки типових дефектів, атаки, чеклисти. На співбесіді тема виринає у формулюваннях «як тестувати без вимог», «звідки береш ідеї для негативних перевірок» і в класичному «протестуйте поле вводу» — там очікують саме мікс системних технік із досвідними (розбір таких задач — у главі «Класичні задачі співбесід»).
Error guessing: звідки береться «нюх»
Передбачення помилок (error guessing) — техніка, у якій тестувальник вгадує, де в продукті ховаються дефекти, спираючись на досвід: як цей застосунок ламався раніше, які помилки типово роблять розробники, як падали схожі системи. Формально це найпростіша з технік — «подумай, де може бути баг, і перевір». Уся цінність — у якості здогадок.
Ключова відмінність від специфікаційних технік — напрямок виведення. Класи еквівалентності відповідають на питання «що обіцяє вимога і як це перевірити». Error guessing відповідає на інше: «де розробник найімовірніше помилився, навіть якщо вимога виконана буквально». Тобто одиниця роботи тут — не вимога, а гіпотеза про дефект: «тут, мабуть, забули обрізати пробіли», «цей список, певно, не тестували на порожньому стані», «дата з іншої таймзони цю логіку зламає».
Звідки беруться гіпотези — тобто той самий «нюх»:
- Власна історія багів. Кожен знайдений дефект — це не тільки тікет, а й патерн: якщо один раз бачив, як пошук падає від лапки в запиті, наступного разу перевіриш лапку першою.
- Баг-трекер команди. Найшвидший спосіб для джуна «купити» чужий досвід — прочитати останні пару сотень закритих багів свого проєкту. Стане видно, які модулі й типи помилок повторюються (принцип скупчення дефектів працює й тут).
- Знання типових помилок розробки. Помилки на одиницю (off-by-one) на межах, необроблений null, порожня колекція, конкурентний доступ, помилки округлення float, час і таймзони, кодування рядків. Ці класи не залежать від проєкту.
- Знання платформи. Для веба це, наприклад, розуміння, що «тест бачить стару версію сторінки» — це найчастіше кеш, а «залогінило не того користувача» — cookie й сесії. Досвідна гіпотеза тим точніша, чим краще знаєш механіку під капотом.
Практичний висновок: «нюх» — не талант, а накопичення. Його можна прискорити: розбирати причини чужих багів, а не лише свої; після кожного пропущеного в прод дефекту питати «яка перевірка його б зловила»; і користуватися готовими списками — про них далі.
Таксономії дефектів: чужий досвід списком
Таксономія дефектів (defect taxonomy) — класифікований перелік типових видів помилок. Це той самий досвід, тільки вже зібраний і розкладений по категоріях кимось до тебе. Замість того щоб роками набивати власні ґулі, береш готовий каталог і проходиш ним по своїй фічі, питаючи біля кожного пункту: «а тут таке можливе?»
Класичні приклади — таксономія Бориса Бейзера у «Software Testing Techniques» і додаток «Common Software Errors» до книги «Testing Computer Software» Канера, Фолка і Нгуєна: каталог на кілька сотень типових дефектів, згрупованих за категоріями — обробка вводу, обчислення, стан і дані, обробка помилок, навантаження, документація тощо.
Для щоденної роботи вистачає компактної таксономії під свій тип продукту. Для типової веб-форми вона може виглядати так:
- Ввід: порожнє значення, самі пробіли, максимальна довжина і довжина понад максимум, юнікод та емодзі, HTML-теги і лапки, невидимі символи з копіпасту;
- Дії: подвійний клік по сабміту, кнопка «назад» після відправлення, оновлення сторінки посеред флоу, дві вкладки з однією формою;
- Стан: порожній список, рівно один елемент, дуже багато елементів, протухла сесія посеред заповнення;
- Час і локаль: межа доби і року, інша таймзона, формат дати й розділювач дробової частини в іншій локалі.
Кожен рядок такого списку — згорнута гіпотеза error guessing. Розгортання пунктів у конкретні значення — це вже тема тестових даних.
Сенс таксономії не в повноті, а в передаваності: особистий нюх лишається в голові, таксономія — артефакт, який можна дати новачкові, обговорити на рев'ю і поповнювати.
Систематизовані атаки
Наступний крок формалізації — атака (fault attack): цілеспрямована спроба викликати конкретний клас відмови. ISTQB описує це як методичний підхід до error guessing — скласти перелік можливих помилок, дефектів і відмов, а тоді спроєктувати тести, які ці відмови спровокують. Канонічне джерело — книга Джеймса Віттекера «How to Break Software», де тестування описане саме як набір атак на ввід, вивід, дані й обчислення.
Атака відрізняється від «потикати навмання» трьома речами: у неї є мішень (конкретний клас дефекту), метод (що саме робимо) і очікуваний симптом (як зрозуміти, що влучили). Кілька атак із класичного репертуару:
- Викликати всі повідомлення про помилки. Кожне повідомлення — це гілка обробки помилок у коді, а такі гілки тестують найрідше. Мішень — необроблені й неправильно оброблені помилкові стани.
- Змусити застосунок застосувати значення за замовчуванням. Пропустити необов'язкове поле, стерти передзаповнене. Мішень — дефолти, яких насправді немає або які невалідні.
- Дослідити допустимі набори символів і типи даних. Юнікод у поле «тільки латиниця», текст у числове поле, від'ємне число в поле кількості. Мішень — валідація, що довіряє клієнту.
- Переповнити буфер вводу. Рядок на десятки тисяч символів, файл на порядок більший за очікуваний. Мішень — відсутні ліміти довжини й розміру.
- Повторити ту саму дію багато разів. Повторний сабміт, повторний запит, повторне скасування. Мішень — стан, що не переживає повторення (неідемпотентні операції — докладніше в главі про HTTP-методи).
Той самий цикл, який перетворює випадкову знахідку на системний інструмент, виглядає так:
Гілка «пункт вигорів» — не дрібниця: це парадокс пестицидів у дії. Якщо атака роками нічого не ловить, або команда вже навчилася цього класу помилок не робити, або атака сформульована так, що б'є повз ціль.
Чеклист-тестування
Чеклист-тестування (checklist-based testing) — проєктування і виконання перевірок за переліком пунктів-нагадувань. Чеклист фіксує «що перевірити», але лишає тестувальнику свободу в «як» — цим він відрізняється і від детального тест-кейсу (там зафіксовано і «що», і «як»), і від вільного дослідження (там не зафіксовано нічого наперед).
| Підхід | Що зафіксовано наперед | Свобода виконавця |
|---|---|---|
| Детальний тест-кейс | Кроки, дані, очікуваний результат | Мінімальна |
| Чеклист | Перелік перевірок-інваріантів | Як саме перевіряти |
| Сесійне дослідницьке | Чартер: напрям і таймбокс | Що і як перевіряти |
| Ad hoc | Нічого | Повна |
Дослідницьке тестування — окрема велика тема з власними механіками (чартери, тури, дебрифи), їй присвячена наступна глава. ISTQB відносить до досвідних технік усі три: error guessing, exploratory і checklist-based.
Головне ремесло чеклиста — правильний рівень абстракції пункту. Занадто детально — і чеклист виродився в тест-кейс, який дорого підтримувати. Занадто загально («перевірити форму») — і пункт не нагадує нічого. Робочий пункт формулюється як інваріант, що має виконуватись: не «перевірити поле email», а «email із пробілом на кінці приймається після trim або чемно відхиляється». Тоді пункт одночасно і нагадує перевірку, і задає критерій проходження. Докладніше про вибір рівня деталізації — у главі «Тест-кейси й чеклисти: рівень деталізації».
Ціна цієї свободи — розкид: два тестувальники за одним чеклистом проведуть різні перевірки, і повторюваність буде нижчою, ніж зі скриптованими кейсами. Для регресії, де важлива відтворюваність «як минулого разу», це мінус; для швидкого покриття нової фічі — прийнятна плата за швидкість.
Власні чеклисти: як накопичувати досвід у файлі
Готові таксономії дають загальне, але найцінніший чеклист — свій, вирощений на багах саме твого продукту. Правила накопичення прості:
- Кожен дефект, що доїхав до проду, стає пунктом. Не «баг №4521», а узагальнений інваріант: пропустили баг з датою 29 лютого — з'являється пункт «дати перевіряються на високосний рік».
- Пункти групуються за об'єктом: поле вводу, форма, таблиця зі списком, завантаження файлу, платіж. Тоді на новій фічі береш лише релевантні групи, а не ввесь файл.
- Чеклист живе під рев'ю. Раз на кілька місяців — ревізія: що вигоріло, що дублюється, що сформульовано як дія замість перевірки.
Для команди такий файл — прискорювач онбордингу: джун отримує «нюх сеньйора» у придатному для використання вигляді. А ще пункти чеклиста природно перетікають в автоматизацію: пункт-інваріант — це готова специфікація параметризованого тесту.
// Пункт чеклиста «поле переживає небезпечні рядки» → data-driven тест
const naughtyInputs = [
' ',
'a'.repeat(10_000),
'<script>alert(1)</script>',
'емодзі 🐛 і юнікод 𝕊',
"O'Brien; DROP TABLE--",
];
for (const value of naughtyInputs) {
test(`назва товару: приймає або відхиляє ${JSON.stringify(value.slice(0, 15))}`, async ({ page }) => {
await page.goto('/products/new');
await page.getByLabel('Назва товару').fill(value);
await page.getByRole('button', { name: 'Зберегти' }).click();
// інваріант: явна відповідь UI, а не 500 чи мовчазна втрата вводу
await expect(page.getByRole('alert').or(page.getByText('Збережено'))).toBeVisible();
});
}
Зверни увагу: тест не каже, що саме правильно — прийняти чи відхилити. Він перевіряє інваріант нижчого рівня: система відповідає передбачувано. Це типово для перевірок, народжених з атак: вони ловлять «застосунок поводиться неадекватно», а не «результат не збігся зі специфікацією». Готовий набір таких рядків не обов'язково вигадувати — є, наприклад, Big List of Naughty Strings.
Межі досвідних технік
Досвідні техніки мають три системні обмеження, і на співбесіді їх знання цінується не менше, ніж знання самих технік.
Немає моделі — немає вимірного покриття. У класів еквівалентності можна порахувати: класів вісім, покрито вісім. У error guessing лічити нема чого: список гіпотез принципово відкритий, тож «ми покрили 80% здогадок» — беззмістовна фраза. Наслідок: досвідними техніками неможливо обґрунтувати достатність тестування, тільки доповнити його.
Якість дорівнює досвіду виконавця. Error guessing джуна об'єктивно слабший за error guessing сеньйора — і це не лікується старанністю, лише часом і таксономіями. Тому в командах досвідні перевірки нової критичної фічі варто або віддавати досвідченішим, або підпирати спільним чеклистом.
Погана відтворюваність і трасованість. Перевірку «мені здалося підозрілим, і я спробував» важко трасувати до вимоги та повторити рік по тому. У доменах, де потрібна формальна звітність про покриття вимог, досвідні техніки можуть існувати лише як доповнення до задокументованих.
Звідси головний принцип застосування: досвідні техніки доповнюють специфікаційні, а не замінюють їх. Правильний порядок — спершу системний каркас від вимог (еквівалентність, межі, таблиці рішень — залежно від типу логіки, див. першу главу розділу), а поверх нього — досвідний прохід по тому, чого у вимогах немає. Обернений порядок небезпечний: «у мене нюх» перетворюється на виправдання дір у базовому покритті.
Типові помилки
- Виглядає як «error guessing — це тикати куди попало», а насправді це перевірка сформульованих гіпотез про конкретні класи дефектів. Немає гіпотези («що я очікую тут зламати?») — це вже не техніка, а ad hoc.
- Виглядає як «чеклист — це просто скорочений тест-кейс», а насправді це інший інструмент: кейс фіксує кроки, чеклист — інваріанти. Скоротивши кейс, отримаєш поганий кейс; чеклист пишеться одразу на іншому рівні.
- Виглядає як «досвідні техніки швидші, тож почнемо з них, а системні — якщо лишиться час», а насправді так утворюються діри в базовому покритті: досвід ловить екзотику, але не гарантує, що перевірені звичайні класи еквівалентності.
- Виглядає як «чеклист написали — і він працює вічно», а насправді пункти вигорають (парадокс пестицидів): команда перестає робити ці помилки, а нові класи багів у чеклист ніхто не додав. Чеклист без ревізії деградує до ритуалу.
- Виглядає як «нюх або є, або нема», а насправді це накопичувана статистика: баг-трекер, розбори продових інцидентів, чужі таксономії. Джун без нюху — норма; джун, який не читає закриті баги свого проєкту, — втрачена можливість.
Підсумок
- Досвідні техніки виводять перевірки не з вимог, а з гіпотез про дефекти; їхня цінність дорівнює якості цих гіпотез.
- «Нюх» — це стиснута статистика минулих багів, і її можна накопичувати свідомо: баг-трекер, розбори інцидентів, готові таксономії.
- Атака — це error guessing із мішенню, методом і очікуваним симптомом; цикл «баг → пункт списку → атака на наступній фічі» перетворює випадкові знахідки на систему.
- Чеклист фіксує «що перевірити» і лишає свободу в «як»; робочий пункт — інваріант із критерієм, а не дія.
- Досвідні техніки не мають вимірного покриття, тому доповнюють специфікаційні, а не замінюють їх: спершу системний каркас, потім досвідний прохід.
Що питають на співбесіді
- «Що таке error guessing і коли ти його застосовуєш?» Інтерв'юер дивиться, чи розумієш ти це як техніку з гіпотезами, а не «тестування навмання», і чи назвеш місце в процесі — після системних технік, не замість.
- «Як тестувати фічу, на яку немає вимог?» Очікують структуру: зібрати неявні джерела вимог, побудувати базові перевірки, а тоді досвідний прохід — таксономія, атаки, чеклист. Кандидат, який одразу каже «клацав би навмання», втрачає бали.
- «Чим чеклист відрізняється від тест-кейсу і коли що вибрати?» Дивляться на розуміння компромісу: відтворюваність проти швидкості й гнучкості, і чи згадаєш, що рівень деталізації — свідомий вибір.
- «Звідки береш ідеї для негативних перевірок?» Сильна відповідь — конкретика: класи типових дефектів (довжина, юнікод, порожньо, повтори, час), баг-трекер проєкту, готові списки на кшталт naughty strings. Слабка — «з досвіду» без деталей.
- «Розкажи про баг, який ти знайшов завдяки досвіду, а не тест-кейсам». Перевіряють, чи є за словами практика: очікують історію з гіпотезою («я запідозрив, що...»), а не випадкову знахідку.
- «Які слабкі місця в досвідних технік?» Питання на зрілість: невимірне покриття, залежність від виконавця, погана відтворюваність. Хто називає межі техніки — той нею справді користувався.
Джерела
- ISTQB CTFL 4.0 Syllabus — розділ 4.4 «Experience-based Test Techniques»: error guessing (4.4.1), exploratory testing (4.4.2), checklist-based testing (4.4.3). Ця глава покриває 4.4.1 і 4.4.3.
- ISTQB Glossary — канонічні означення термінів error guessing, fault attack, checklist-based testing.
- James A. Whittaker. How to Break Software: A Practical Guide to Testing. Addison-Wesley, 2002 — першоджерело підходу «атак» на ПЗ.
- Cem Kaner, Jack Falk, Hung Q. Nguyen. Testing Computer Software, 2nd ed. — додаток «Common Software Errors», класичний каталог типових дефектів.
- Big List of Naughty Strings — готовий набір небезпечних рядків для атак на поля вводу.
Які техніки тест-дизайну називають досвідними і чим вони відрізняються від специфікаційних?
Досвідні техніки (experience-based test techniques) виводять перевірки не з вимог, а з досвіду: знання того, як застосунки типово ламаються. ISTQB відносить сюди три техніки: error guessing, дослідницьке тестування (exploratory testing) і чеклист-тестування (checklist-based testing). Принципова відмінність — напрямок виведення: специфікаційні техніки відповідають на питання «що обіцяє вимога і як це перевірити», досвідні — «де розробник найімовірніше помилився, навіть якщо вимога виконана буквально». Тому досвідні техніки ловлять баги там, де специфікація мовчить: ніде не написано, що поле не повинно падати від емодзі чи що подвійний клік по «Оплатити» не має списати гроші двічі. Практичний наслідок: ці техніки доповнюють специфікаційні, а не замінюють їх.
Що таке error guessing (передбачення помилок)?
Error guessing — техніка, у якій тестувальник вгадує, де в продукті ховаються дефекти, спираючись на досвід: як цей застосунок ламався раніше, які помилки типово роблять розробники, як падали схожі системи. Формально це найпростіша з технік — «подумай, де може бути баг, і перевір», тому вся її цінність — у якості здогадок. Одиниця роботи тут — не вимога, а гіпотеза про дефект: «тут, мабуть, забули обрізати пробіли», «цей список, певно, не тестували на порожньому стані». На співбесіді важливо показати саме це: error guessing — перевірка сформульованих гіпотез про конкретні класи дефектів, а не хаотичне клацання.
Чим error guessing відрізняється від ad hoc «потикати навмання»?
Різниця — у наявності гіпотези. В error guessing перед кожною перевіркою стоїть питання «що я очікую тут зламати?» і відповідь на нього: конкретний клас дефекту, який підозрюється в конкретному місці. Ad hoc — це дії без жодної зафіксованої наперед ідеї, тому знахідки там випадкові й не відтворювані. Гіпотеза дає ще один бонус: її можна записати, обговорити й перетворити на пункт таксономії чи чеклиста — тобто зробити досвід передаваним. Немає гіпотези — це вже не техніка, а везіння.
Звідки тестувальник бере ідеї для негативних перевірок?
Сильна відповідь — конкретні джерела, а не «з досвіду». Перше — власна історія багів: кожен знайдений дефект — це патерн, який перевіряєш першим наступного разу. Друге — баг-трекер команди: пара сотень закритих багів проєкту показує, які модулі й типи помилок повторюються (принцип скупчення дефектів працює й тут). Третє — знання типових помилок розробки, незалежних від проєкту: off-by-one на межах, необроблений null, порожня колекція, конкурентний доступ, округлення float, час і таймзони, кодування рядків. Четверте — знання платформи: для веба, наприклад, «тест бачить стару версію» — це найчастіше кеш, а «залогінило не того» — cookie й сесії. Плюс готові артефакти: таксономії дефектів і списки на кшталт Big List of Naughty Strings.
Що таке таксономія дефектів і навіщо вона, якщо є власний досвід?
Таксономія дефектів (defect taxonomy) — класифікований перелік типових видів помилок: той самий досвід, тільки вже зібраний і розкладений по категоріях кимось до тебе. Класика — таксономія Бейзера і додаток «Common Software Errors» до «Testing Computer Software» Канера, Фолка й Нгуєна: каталог на кілька сотень дефектів за категоріями (обробка вводу, обчислення, стан і дані, обробка помилок, навантаження). Користуються нею просто: проходиш списком по своїй фічі й біля кожного пункту питаєш «а тут таке можливе?». Головна цінність таксономії не в повноті, а в передаваності: особистий нюх лишається в голові, таксономія — артефакт, який можна дати новачкові, обговорити на рев'ю і поповнювати. Кожен рядок такого списку — згорнута гіпотеза error guessing.
Джун без «нюху» — це вирок? Як прискорити накопичення досвіду?
Ні: «нюх» — не талант, а стиснута статистика минулих багів, і її можна накопичувати свідомо. Найшвидший спосіб «купити» чужий досвід — прочитати останні пару сотень закритих багів свого проєкту в баг-трекері: стане видно, що і де повторюється. Далі — розбирати причини чужих багів, а не лише своїх; після кожного пропущеного в прод дефекту питати «яка перевірка його б зловила» і перетворювати відповідь на пункт чеклиста. І користуватися готовими таксономіями замість того, щоб роками набивати власні ґулі. Джун без нюху — норма; джун, який не читає закриті баги свого проєкту, — втрачена можливість.
Що таке атака (fault attack) і чим вона відрізняється від простого error guessing?
Атака — цілеспрямована спроба викликати конкретний клас відмови; ISTQB описує це як методичний підхід до error guessing: скласти перелік можливих помилок, дефектів і відмов, а тоді спроєктувати тести, які ці відмови спровокують. Канонічне джерело — «How to Break Software» Джеймса Віттекера, де тестування описане саме як набір атак. Від «потикати» атаку відрізняють три речі: мішень (конкретний клас дефекту), метод (що саме робимо) і очікуваний симптом (як зрозуміти, що влучили). Приклади з класичного репертуару: викликати всі повідомлення про помилки (гілки обробки помилок тестують найрідше), змусити застосунок застосувати дефолти, згодувати неприпустимі символи й типи, переповнити буфер вводу довжелезним рядком, повторити ту саму дію багато разів (повторний сабміт ловить неідемпотентні операції).
Як тестувати фічу, на яку немає вимог?
Очікують структуру, а не «клацав би навмання». Спершу зібрати неявні джерела вимог: схожі фічі продукту, поведінка конкурентів, здоровий глузд домену, розмова з розробником чи продактом. З цього побудувати базові перевірки — той самий системний каркас, тільки від відновлених вимог. І вже поверх нього — досвідний прохід: пройтися таксономією дефектів по типу об'єкта (поле, форма, список, файл), виконати стандартні атаки, звіритися з командним чеклистом. Саме в цій задачі досвідні техніки розкриваються найповніше, бо специфікаційним технікам нема від чого відштовхнутись. Кандидат, який одразу починає з хаотичного клацання, втрачає бали.
Чим чеклист відрізняється від детального тест-кейсу і від дослідницького тестування?
Різниця — у тому, що зафіксовано наперед. Детальний тест-кейс фіксує і «що», і «як»: кроки, дані, очікуваний результат — свободи виконавця майже немає. Чеклист фіксує лише «що перевірити» — перелік перевірок-інваріантів, а «як саме» лишає тестувальнику. Сесійне дослідницьке тестування фіксує ще менше — чартер із напрямом і таймбоксом, а ad hoc не фіксує нічого. Вибір — це компроміс: скриптовані кейси дають відтворюваність «як минулого разу» (важливо для регресії), чеклист дає швидкість і гнучкість на новій фічі, але два тестувальники за одним чеклистом проведуть різні перевірки. Важливо не плутати: чеклист — не «скорочений тест-кейс», а інший інструмент на іншому рівні абстракції.
Як сформулювати хороший пункт чеклиста?
Головне ремесло — правильний рівень абстракції. Занадто детально — і чеклист виродився в тест-кейс, який дорого підтримувати; занадто загально («перевірити форму») — і пункт не нагадує нічого. Робочий пункт формулюється як інваріант, що має виконуватись: не «перевірити поле email», а «email із пробілом на кінці приймається після trim або чемно відхиляється». Такий пункт одночасно і нагадує перевірку, і задає критерій проходження — по ньому видно, пройдено чи ні. Побічний бонус: пункт-інваріант — це готова специфікація параметризованого автотесту.
Як вести власний чеклист команди, щоб він приносив користь, а не деградував у ритуал?
Три правила. Перше: кожен дефект, що доїхав до проду, стає пунктом — не «баг №4521», а узагальнений інваріант (пропустили баг з 29 лютого — з'являється пункт «дати перевіряються на високосний рік»). Друге: пункти групуються за об'єктом — поле вводу, форма, таблиця, завантаження файлу, платіж — щоб на новій фічі брати лише релевантні групи. Третє: чеклист живе під рев'ю — раз на кілька місяців ревізія: що вигоріло, що дублюється, що сформульовано як дія замість перевірки. Для команди такий файл — прискорювач онбордингу: джун отримує «нюх сеньйора» у придатному для використання вигляді.
Як досвідні перевірки перетікають в автоматизацію?
Пункт-інваріант чеклиста — готова специфікація параметризованого (data-driven) тесту: «поле переживає небезпечні рядки» розгортається в цикл по масиву значень (пробіли, десятки тисяч символів, HTML-теги, емодзі, лапки) з одним асертом. Характерна риса таких тестів: вони часто не кажуть, що саме правильно — прийняти чи відхилити значення, — а перевіряють інваріант нижчого рівня: система відповідає передбачувано (явна помилка чи явний успіх), а не віддає 500 і не втрачає ввід мовчки. Це типово для перевірок, народжених з атак: вони ловлять «застосунок поводиться неадекватно», а не «результат не збігся зі специфікацією». Набори значень не обов'язково вигадувати — є готові, як Big List of Naughty Strings.
Що таке парадокс пестицидів у контексті чеклистів і атак?
Пункти чеклиста й атаки з часом вигорають: команда перестає робити цей клас помилок, і перевірка роками нічого не ловить. Це парадокс пестицидів у дії — ті самі перевірки перестають знаходити нові дефекти. Варіантів два: або клас помилок справді викорінено, або атака сформульована так, що б'є повз ціль. Тому цикл роботи з досвідом замкнений: баг у проді → розбір, до якого класу він належить → пункт у таксономії чи чеклисті → атака на кожній наступній фічі → якщо давно не влучає, ревізія пункту (переформулювати або прибрати). Чеклист без ревізії деградує до ритуалу: його проходять, але він уже нічого не захищає, а нові класи багів у нього ніхто не додав.
Які слабкі місця в досвідних технік?
Три системні обмеження. Перше: немає моделі — немає вимірного покриття. У класів еквівалентності можна порахувати «класів вісім, покрито вісім»; список гіпотез error guessing принципово відкритий, тож «покрили 80% здогадок» — беззмістовна фраза, і досвідними техніками неможливо обґрунтувати достатність тестування. Друге: якість дорівнює досвіду виконавця — error guessing джуна об'єктивно слабший за сеньйорський, і це не лікується старанністю, лише часом і таксономіями. Третє: погана відтворюваність і трасованість — перевірку «мені здалося підозрілим, і я спробував» важко трасувати до вимоги й повторити рік по тому, тому в доменах із формальною звітністю досвідні техніки існують лише як доповнення до задокументованих. Хто називає межі техніки — той нею справді користувався.
Чому небезпечно починати тестування з досвідних технік, а системні лишати «на потім»?
Бо так утворюються діри в базовому покритті: досвід ловить екзотику, але не гарантує, що перевірені звичайні класи еквівалентності й межі. Правильний порядок — спершу системний каркас від вимог (еквівалентність, граничні значення, таблиці рішень — залежно від типу логіки), а поверх нього досвідний прохід по тому, чого у вимогах немає. Обернений порядок небезпечний ще й психологічно: «у мене нюх» перетворюється на виправдання пропусків у базовому покритті. Формула для співбесіди: досвідні техніки доповнюють специфікаційні, а не замінюють їх — і невимірність їхнього покриття якраз пояснює чому.
Три кейси про те, як досвід перестає бути «нюхом у голові» і стає інструментом: десятихвилинний прохід атаками по формі без вимог, рев'ю командного чеклиста з переформулюванням вигорілих пунктів і перетворення продового бага на параметризований автотест.
Кейс 1. Форма без вимог: прохід атаками за десять хвилин
Ситуація: у спринт заїхала форма «Створити промокод» — назва, знижка у відсотках, дата закінчення. Вимог — два рядки в тікеті, обидва про happy path. Системні техніки застосувати нема до чого, тож будуємо досвідний прохід: для кожної атаки фіксуємо мішень, метод і очікуваний симптом — інакше це не атака, а тикання.
| Атака | Метод на цій формі | Симптом влучання |
|---|---|---|
| Викликати всі повідомлення про помилки | Сабміт порожньої форми, знижка 0 і 101, дата в минулому | Замість зрозумілої помилки — 500, порожній тост або форма мовчки «з'їла» сабміт |
| Змусити застосувати дефолти | Стерти передзаповнену дату, пропустити необов'язкову назву | Створився промокод із датою Invalid Date чи порожнім ім'ям |
| Неприпустимі символи й типи | Емодзі та лапка в назві, 12,5 і 1e2 у поле відсотка | Ламається верстка списку промокодів, відсоток зберігся не тим числом |
| Переповнити ввід | Назва на 10 000 символів | Немає ліміту: падає запит, або список промокодів стає нечитабельним |
| Повторити дію | Подвійний клік по «Створити», повторний сабміт після «назад» | Два однакові промокоди — операція неідемпотентна |
Що тут подивитись і чому:
- Кожен рядок — згорнута гіпотеза, а не випадковість. Перед кліком є відповідь на «що я очікую зламати». Саме це відрізняє прохід від ad hoc: знахідку можна повторити, а гіпотезу, що не влучила, — викреслити свідомо.
- Колонка симптомів — половина цінності. Без неї легко пройти повз баг: форма «щось показала», і ок. Симптом заздалегідь каже, що вважається влучанням: 500, мовчазна втрата вводу, дублікат.
- Прохід не скасовує системного каркаса. Межі знижки (
0,1,100,101) — це граничні значення, вони мають бути й без усяких атак. Досвідний шар накриває те, чого у вимогах немає: повтори, довжину, символи. - Знахідки не вмирають у тікетах. «Подвійний клік створює два промокоди» після фіксу стає пунктом командного чеклиста для всіх майбутніх форм — див. кейс 2.
Кейс 2. Рев'ю чеклиста: переписуємо дії на інваріанти
Ситуація: командному чеклисту «Форми» два роки, його проходять за звичкою, але останні півроку він не зловив жодного бага. Ревізія показує типові хвороби — пункти-дії без критерію, пункти-тест-кейси, які дорого підтримувати, і вигорілі рядки.
| Було | Діагноз | Стало |
|---|---|---|
| «Перевірити поле email» | Дія без критерію: не нагадує нічого конкретного | «Email із пробілами на краях приймається після trim або чемно відхиляється» |
| «Ввести a@b.c, натиснути Зберегти, побачити зелений тост» | Виродився в тест-кейс: зафіксовано і «що», і «як» | «Валідний email зберігається, UI явно підтверджує збереження» |
| «Перевірити, що IE11 рендерить форму» | Вигорів: платформу давно не підтримуємо | Прибрати |
| «Клацнути сабміт двічі» | Дія є, інваріанта немає — що вважати проходженням? | «Повторний сабміт не створює дубліката і не списує повторно» |
| «Перевірити дати» | Занадто загально | «Дата 29 лютого, межа доби і року, інша таймзона не ламають збереження» |
Що тут подивитись і чому:
- Робочий пункт читається як твердження, яке можна перевірити на істинність. Якщо пункт не відповідає на «пройдено чи ні» — це не перевірка, а нагадування про напрямок, і тлумачити його кожен буде по-своєму.
- Пункт-тест-кейс — теж поломка, тільки в інший бік. Зафіксовані кроки й дані означають дорогу підтримку і втрату головної переваги чеклиста — свободи виконавця у «як».
- Прибирати вигоріле не менш важливо, ніж додавати нове. Парадокс пестицидів: пункти, які роками нічого не ловлять, перетворюють проходження чеклиста на ритуал і з'їдають час, що мав піти на нові класи багів.
- Групування за об'єктом (поле, форма, список, платіж) дає змогу на новій фічі взяти три релевантні групи замість усього файлу.
Кейс 3. З продового бага — у параметризований тест
Ситуація: у прод доїхав баг — користувач двічі клікнув «Оформити замовлення», списання пройшло двічі. Розбір за циклом «баг → клас → пункт → атака»: клас — неідемпотентна операція, у чеклист їде пункт «повторна дія не дублює ефект», а сам пункт-інваріант — готова специфікація автотесту для всіх критичних кнопок.
// Пункт чеклиста «повторний сабміт не створює дубліката» → атака повтором
const criticalActions = [
{ path: '/checkout', button: 'Оформити замовлення', listPath: '/orders' },
{ path: '/promo/new', button: 'Створити', listPath: '/promo' },
];
for (const action of criticalActions) {
test(`подвійний клік по "${action.button}" не дублює операцію`, async ({ page }) => {
await page.goto(action.path);
// ...заповнення мінімально валідними даними...
await page.getByRole('button', { name: action.button }).dblclick();
await page.goto(action.listPath);
// інваріант: рівно один створений запис, а не два
await expect(page.getByTestId('created-item')).toHaveCount(1);
});
}
Що тут подивитись і чому:
- Тест народився не з вимоги. У жодному тікеті не написано «подвійний клік не має дублювати замовлення» — це вважалося очевидним. Джерело перевірки — продовий інцидент, узагальнений до класу дефектів.
- Асерт перевіряє інваріант, а не конкретний сценарій. Не важливо, як саме застосунок захистився — дизейблом кнопки, дедуплікацією на бекенді чи ідемпотентним ключем. Важливо, що ефект один. Тому тест переживе рефакторинг захисту.
- Параметризація — пряме продовження чеклиста. Один пункт-інваріант, масив об'єктів, до яких він застосовний, — і атака автоматично виконується на кожній критичній дії в кожному прогоні, а не тільки там, де баг уже стрельнув.
- Цикл замкнувся. Випадкова знахідка в проді стала системним інструментом: пункт чеклиста для ручних проходів нових фіч плюс автотест для регресії. Якщо за рік атака нічого не зловить — це привід для ревізії, а не для гордості.
Error guessing і джерела гіпотез
- Розумію, що досвідні техніки виводять перевірки з гіпотез про дефекти, а не з вимог, і ISTQB відносить сюди error guessing, exploratory і checklist-based.
- Можу пояснити різницю напрямків: специфікаційні техніки — «що обіцяє вимога», error guessing — «де розробник найімовірніше помилився».
- Знаю межу між error guessing і ad hoc: техніка починається там, де є сформульована гіпотеза «що я очікую тут зламати».
- Можу назвати чотири джерела гіпотез: власна історія багів, баг-трекер команди, типові помилки розробки (off-by-one, null, порожня колекція, float, таймзони, кодування), знання платформи.
- Знаю, що «нюх» — накопичувана статистика, і найшвидший спосіб для джуна її здобути — прочитати закриті баги свого проєкту.
Таксономії та атаки
- Можу пояснити, що таксономія дефектів — це чужий досвід списком, і її цінність у передаваності, а не в повноті.
- Знаю класичні каталоги: таксономія Бейзера і «Common Software Errors» Канера, Фолка й Нгуєна.
- Можу накидати компактну таксономію веб-форми за чотирма групами: ввід, дії, стан, час і локаль.
- Знаю три складові атаки (fault attack): мішень, метод, очікуваний симптом — і чим це відрізняється від «потикати навмання».
- Можу назвати кілька атак з репертуару Віттекера: викликати всі повідомлення про помилки, змусити застосувати дефолти, неприпустимі символи й типи, переповнення вводу, повторення дії.
- Розумію цикл «баг у проді → клас дефекту → пункт списку → атака на наступній фічі» і гілку ревізії, коли пункт вигорів.
Чеклист-тестування
- Можу розставити чотири підходи за ступенем фіксації: детальний тест-кейс → чеклист → сесійне дослідницьке → ad hoc, і пояснити, чому чеклист (фіксує «що», лишає свободу в «як») — не «скорочений тест-кейс».
- Можу сформулювати робочий пункт як інваріант із критерієм: не «перевірити поле email», а «email із пробілом на кінці приймається після trim або чемно відхиляється».
- Розумію ціну свободи чеклиста: два тестувальники проведуть різні перевірки, повторюваність нижча — мінус для регресії, плюс для швидкого покриття нової фічі.
- Знаю правила ведення власного чеклиста: кожен продовий дефект стає узагальненим пунктом, пункти групуються за об'єктом, чеклист живе під періодичне рев'ю — без нього парадокс пестицидів деградує чеклист до ритуалу.
- Можу пояснити, як пункт-інваріант перетікає в data-driven автотест з асертом «система відповідає передбачувано», а не «результат збігся зі специфікацією».
Межі й місце в процесі
- Можу назвати три системні обмеження: невимірне покриття (список гіпотез відкритий), якість дорівнює досвіду виконавця, погана відтворюваність і трасованість.
- Розумію, чому досвідними техніками не можна обґрунтувати достатність тестування — лічити нема чого.
- Знаю правильний порядок: спершу системний каркас від вимог, потім досвідний прохід — і чому обернений порядок лишає діри в базовому покритті.
- Маю готову структуру відповіді на «як тестувати без вимог»: неявні джерела вимог → базові перевірки → таксономія, атаки, чеклист.
Що є одиницею роботи в error guessing?
Питання
Досвідні техніки (experience-based) — з чого вони виводять перевірки?