Вибір і комбінування технік
Зміст
Попередні глави розділу розібрали техніки поодинці: класи еквівалентності, граничні значення, таблиці рішень, переходи станів, сценарії, досвідні техніки. Але робоча задача ніколи не приходить з етикеткою «застосуй BVA». Приходить фіча, дедлайн і специфікація сумнівної повноти — і рішення, якими техніками покривати, наскільки глибоко і коли зупинитися, доводиться ухвалювати самому. Саме це рішення відрізняє рівні: junior знає техніки, senior знає, коли яку і скільки.
На співбесіді ця різниця видна за пʼять хвилин. «Протестуй форму» junior починає з перерахування перевірок, senior — з уточнень і вибору інструментів: де тут дані, де комбінації умов, де стани, що з цього ризиковане. Питання «як обираєш підхід до тестування фічі», «скільки тестів достатньо», «як тестувати без документації» — усе це питання цієї глави.
Чотири критерії вибору
Силабус ISTQB (CTFL 3.1; у v4.0 явний перелік прибрали) наводив довгий список факторів вибору технік — серед них складність компонента, регуляторні стандарти, вимоги контракту, рівень ризику, доступна документація, знання й навички тестувальників, час і бюджет, модель розробки. На практиці цей список стискається до чотирьох робочих критеріїв.
Тип логіки — де живе складність. Головний і перший фільтр. Кожна специфікаційна техніка — це модель певного типу складності, і техніка працює лише там, де її модель збігається з задачею. Складність у значеннях окремих полів (діапазони, формати, ліміти) — це еквівалентність і межі. Складність у поєднаннях умов («знижка, якщо преміум І сума понад 1000») — таблиця рішень. Складність в історії (та сама дія дає різний результат залежно від минулого) — переходи станів. Складність у кількості конфігурацій (браузери × ОС × локалі) — попарне тестування. Складність у потоці користувача — сценарії. Застосувати техніку до чужого типу складності можна, але це як забивати шуруп молотком: щось вийде, тримати не буде.
Ризик. Чим болючіший можливий збій і чим він імовірніший, тим формальніша техніка й глибше покриття. Канонічний розбір ризик-орієнтованого підходу — у розділі «Основи тестування», глава про ризик-орієнтоване тестування; тут важлива його проєкція на вибір технік, про неї — окремий підрозділ нижче.
Час і бюджет. Повна таблиця рішень на 6 бінарних умов — це 64 правила; на переоцінений компонент цього ніхто не дасть. Брак часу зсуває вибір у бік дешевших технік — чеклистів і досвідного проходу — але чесним рішення стає лише тоді, коли зрізане покриття назване вголос: «встигаємо перевірити правила знижок попарно, повний перебір — ні, ризик такий-то».
Якість специфікації. Специфікаційним технікам потрібна специфікація: без описаних правил нема з чого будувати таблицю рішень. Що гірша тестова основа (test basis), то більша частка досвідних технік у міксі — аж до випадку «вимог немає взагалі», якому нижче присвячений окремий підрозділ.
Абзац глибини для регульованих доменів: у safety-critical розробці вибір техніки — не завжди твій. Стандарти на кшталт DO-178C в авіоніці прямо вимагають певних видів покриття коду (для найкритичнішого рівня — MC/DC, розібраний у главі про білоскринькові техніки). Тоді критерій «регуляторка» бʼє всі інші.
Мапа «тип задачі → техніка»
Робоча шпаргалка. У лівій колонці — те, що ти бачиш у задачі, у правій — провідна техніка, з якої варто почати.
| Що бачиш у задачі | Провідна техніка |
|---|---|
| Поле чи параметр із діапазонами, форматами, лімітами | Класи еквівалентності + граничні значення |
| Бізнес-правило з кількох умов («якщо… і… то…») | Таблиця рішень |
| Результат дії залежить від того, що було раніше | Переходи станів |
| Багато незалежних параметрів конфігурації | Попарне тестування |
| Наскрізний користувацький потік з винятками | Сценарії використання |
| Специфікації немає або їй не віриш | Досвідні техніки + дослідницьке тестування |
| Критичний алгоритм, є доступ до коду й coverage-звітів | Білоскринькові техніки |
Та сама мапа як послідовність питань, які можна проговорити на співбесіді:
Два застереження. Перше: це евристика для старту, а не алгоритм — у реальній фічі складність майже завжди живе в кількох місцях одразу, тому «провідна техніка» перетворюється на «комбінація технік» (наступний підрозділ). Друге: останній крок — досвідний прохід поверх — не опція, а константа: специфікаційні техніки покривають те, що написано у вимогах, а чимала частка дефектів живе саме в тому, чого там немає.
Ризик задає не лише техніку, а й глибину
Менш очевидна половина ризик-орієнтованого вибору: майже кожна техніка має внутрішні «ручки глибини», і крутити їх треба теж за ризиком, а не за звичкою.
| Важіль | Економний варіант | Глибокий варіант |
|---|---|---|
| Межі діапазону | 2-точковий аналіз | 3-точковий аналіз |
| Комбінації полів | Each choice (кожне значення хоч раз) | Pairwise → повна таблиця рішень |
| Переходи станів | Покрити всі стани | Усі переходи, потім ланцюжки переходів |
| Покриття коду | Statement coverage | Branch, далі MC/DC |
Логіка однакова на всіх рядках: глибший варіант ловить тонший клас дефектів і коштує помітно дорожче. Для поля «нікнейм» досить 2-точкового аналізу меж; для поля «сума переказу» — 3-точковий, бо ціна off-by-one тут вимірюється грошима. Для матриці браузерів інтранет-звіту досить each choice; для правил нарахування комісії — повна таблиця, бо саме в непереглянутій комбінації умов живе найдорожчий баг.
Ризик визначає й формальність артефактів: критичний флоу документується детальними кейсами, які переживуть плинність команди, а низькоризикова адмінка — чеклистом. Це та сама шкала деталізації, що розібрана в главі про рівень деталізації кейсів, тільки тепер у неї зʼявився критерій вибору.
Комбінування технік на одній фічі
Розберімо на фічі «оформлення замовлення зі знижками» — досить типовій, щоб бути впізнаваною, і досить складній, щоб жодна техніка поодинці її не закрила.
- Поля — кількість товару, сума, формат промокоду: класи еквівалентності + межі. Це дає скелет перевірок значень: валідні класи, невалідні класи, краї діапазонів.
- Правила знижки — тип клієнта × сума кошика × наявність промокоду: таблиця рішень. Окремі поля вже перевірені, тепер перевіряємо поєднання: чи не дає система подвійну знижку, чи правильно розвʼязується конфлікт правил.
- Життєвий цикл замовлення — створене → оплачене → скасоване → повернене: переходи станів. Особливо невалідні: оплата скасованого замовлення через API, повторна оплата з другої вкладки.
- Наскрізні сценарії — happy path «обрав → застосував промокод → оплатив → отримав лист» плюс головні винятки: сценарії використання. Їх мало — два-чотири, — бо атомарні перевірки вже зроблені кроками 1–3.
- Поверх — досвідний прохід: unicode і пробіли в промокоді, подвійний клік «Оплатити», прострочений промокод, застосований за секунду до опівночі.
Ключовий принцип комбінування — кожна техніка закриває свій шар, і перевірки не дублюються. Наскрізний сценарій із кроку 4 не повинен перебирати всі промокоди — формати промокоду вже покриті кроком 1, і ганяти їх через повний UI-флоу означає платити хвилини за те, що перевіряється секундами. Атомарні перевірки значень і правил природно опускаються на рівень API, сценарії лишаються тонким шаром зверху — це та сама логіка розподілу, яку в розділі про автоматизацію описує піраміда тестування.
Технічно дедуплікацію тримають на елементах покриття (coverage items): кожна техніка породжує свій список (класи, межі, правила, переходи), і кожен елемент має бути покритий якимось тестом — одного разу достатньо. Один тест може закривати кілька елементів — сценарій оплати заразом проходить і валідний клас суми, і правило знижки, — і це нормально, якщо звʼязок зафіксований. Як саме фіксувати — у главі про покриття вимог і трасування.
Тест-дизайн без вимог
«Вимог немає» — найчастіше виправдання відсутності тест-дизайну і найчастіша пастка на співбесіді. Насправді без вимог зникає не метод, а лише звична тестова основа — і її треба замінити, а не оплакувати.
Замінники бази, за спаданням надійності: сам продукт (його поведінка — теж специфікація, хай і неявна), попередня версія фічі, баг-трекер (де падало раніше — впаде знову), логи й аналітика реального використання, продукти-аналоги, стандарти платформи, і нарешті голови аналітика та розробника — пʼятнадцять хвилин розмови часто дають більше, ніж день реверс-інжинірингу.
Порядок роботи виглядає так. Спершу дослідницькі сесії будують модель фічі: що вона робить, які в неї входи, стани, правила. Далі спостережена поведінка фіксується письмово — фактично ти відновлюєш вимоги у формі гіпотез: «схоже, промокод застосовується лише до товарів без акції». А до зафіксованих гіпотез уже застосовні звичайні техніки: у гіпотези є діапазони — будуй межі, є умови — таблицю.
Окрема проблема без вимог — оракул: звідки взяти очікуваний результат, якщо його ніде не написано? Робоча відповідь — евристики консистентності: поведінка має узгоджуватися з попередньою версією, з аналогами, з обіцянками маркетингу, зі стандартами платформи, з рештою самого продукту. Розбіжність із будь-чим із цього списку — не автоматично баг, але завжди привід для питання власнику продукту.
І головна пастка, яку перевіряють на співбесідах: спостережена поведінка — не еталон. Задокументувавши, що система робить, ти зафіксував факт, а не норму: можливо, промокод не застосовується до акційних товарів через баг, а не задум. Тому гіпотези з реверс-інжинірингу мають статус «підтвердити в продакт-овнера», а не «очікуваний результат».
Критерії достатності
«Скільки тестів достатньо?» — питання-фільтр на senior-позиції, і число у відповіді — завжди неправильна відповідь. Правильна відповідь — про модель і залишковий ризик, і в неї три рівні.
Рівень технік: покриті елементи покриття. Кожна застосована техніка дає вимірюваний критерій виходу: кожен клас еквівалентності представлений, кожна межа перевірена з обох боків, кожне правило таблиці має тест, кожен перехід пройдений. Це і є перша чесна відповідь: «достатньо» = «елементи покриття обраних технік закриті». Зауваж: критерій залежить від обраних технік — тому вибір технік і вибір моменту зупинки це одне рішення, а не два.
Рівень вимог: покрита кожна вимога. Трасування «вимога → тести» ловить діри іншого сорту: вимогу, для якої тестів не спроєктували взагалі. Методика — у главі про покриття вимог.
Рівень ризику: залишок прийнятий свідомо. Стовідсоткове покриття обраної моделі — не «перевірено все»: вичерпне тестування неможливе, це другий принцип тестування. Отже, щось завжди лишається неперевіреним, і питання лише в тому, чи цей залишок названий і прийнятий: «повний перебір конфігурацій не робили, покрили попарно; ризик — рідкісні потрійні взаємодії». Приймає залишковий ризик не тестувальник, а стейкхолдери — робота тестувальника зробити ризик видимим.
Практичний тест чесності власного дизайну: для кожної непокритої комбінації ти можеш сказати, чому її немає. «Відрізали свідомо, бо низький ризик» — вибірка обґрунтована. «Не подумали» — діра. І ще одне правило, без якого критерії достатності не працюють: їх фіксують до початку тестування. Критерій, дописаний наприкінці, магічним чином завжди виявляється виконаним.
Від дизайну до data-driven тестів
Специфікаційні техніки мають приємну властивість: їхній результат — це природно таблиця. Класи, межі, правила рішень — усе зводиться до рядків «вхід → очікуваний результат». А таблиця — готовий вхід для параметризованого автотесту: логіка виконання пишеться один раз, дизайн живе в даних.
// Playwright: межі пароля 8–64 символи, кожен рядок — coverage item
const passwordCases = [
{ len: 7, valid: false, why: 'нижня межа мінус 1' },
{ len: 8, valid: true, why: 'нижня межа' },
{ len: 64, valid: true, why: 'верхня межа' },
{ len: 65, valid: false, why: 'верхня межа плюс 1' },
];
for (const { len, valid, why } of passwordCases) {
test(`пароль довжиною ${len} (${why}): ${valid ? 'приймається' : 'відхиляється'}`, async ({ page }) => {
await page.goto('/signup');
await page.getByLabel('Пароль').fill('a'.repeat(len));
await page.getByRole('button', { name: 'Зареєструватися' }).click();
const error = page.getByTestId('password-error');
if (valid) {
await expect(error).toBeHidden();
} else {
await expect(error).toBeVisible();
}
});
}
Що тут важливо з погляду тест-дизайну, а не коду:
- Таблиця — це і є артефакт дизайну. Ревʼю тест-дизайну перетворюється на ревʼю таблиці: колега дивиться на чотири рядки й одразу бачить, що 3-точковий аналіз не робили і клас «пароль із пробілами» відсутній. Спробуй побачити те саме в чотирьох копіпаст-тестах.
- Новий клас — новий рядок, а не новий тест. Зʼясувалося, що пароль не може складатися з самих пробілів, — додаєш рядок, код не чіпаєш. Дизайн еволюціонує дешево.
- Поле
why— не коментар, а трасування. Воно потрапляє в назву тесту, і звіт прогону читається як карта покриття меж: одразу видно, який саме бік межі зламався. Це та сама вимога «назва описує перевірку» з глави про деталізацію кейсів.
І дзеркальне застереження: data-driven без технік — це не тест-дизайн, а дорога рулетка. Прогнати тисячу випадкових рядків через форму — та сама вибірка навмання, тільки повільніша: усі тисяча можуть лежати в одному валідному класі. Спершу класи й межі визначають, які рядки мають бути в таблиці, потім уже генерація наповнює їх значеннями — про генерацію, property-based підхід та ізоляцію даних між прогонами — глава про тестові дані.
Типові помилки
- «Для фічі треба обрати правильну техніку». Виглядає як пошук єдиної відповіді, а насправді реальна фіча майже завжди потребує комбінації: одна техніка на значення, інша на комбінації, третя на стани. Хто шукає one-size-fits-all — лишає діри там, куди обрана техніка не дістає за побудовою.
- «Більше кейсів — глибше покриття». Виглядає як старанність, а насправді 50 значень з одного класу еквівалентності покривають менше, ніж 8 значень за класами й межами. Міряти треба покриті елементи, не рядки в TMS.
- «Немає вимог — застосувати техніки неможливо». Виглядає як обʼєктивне обмеження, а насправді змінюється лише тестова основа: дослідження будує модель, модель фіксується гіпотезами, до гіпотез застосовуються звичайні техніки.
- «Елементи покриття закриті — тестування завершене». Виглядає як виконаний exit-критерій, а насправді покриття міряється відносно моделі, а модель — це те, що потрапило у вимоги. Дефекти в неописаному ловить лише досвідний шар поверх — тому він обовʼязковий, а не факультативний.
- «Зробимо data-driven — покриємо більше». Виглядає як підсилення тест-дизайну, а насправді без попереднього розбиття на класи це та сама випадкова вибірка, тільки з інфраструктурними витратами. Параметризація масштабує дизайн, який уже є, — і не створює той, якого немає.
Підсумок
- Техніку обирають за чотирма критеріями — тип логіки, ризик, час, якість специфікації; перший фільтр завжди «де живе складність»: у значеннях, комбінаціях, станах чи потоці.
- Ризик задає не лише вибір техніки, а й глибину всередині неї: 2- чи 3-точкові межі, each choice чи повна таблиця, стани чи ланцюжки переходів.
- Одна фіча — комбінація технік: специфікаційні будують скелет по шарах без дублювання перевірок, досвідний прохід зверху обовʼязковий.
- Без вимог зникає основа, а не метод: дослідження → зафіксовані гіпотези → звичайні техніки; спостережена поведінка — факт, що потребує підтвердження, а не еталон.
- «Достатньо» — це закриті елементи покриття обраних технік плюс залишковий ризик, який стейкхолдери прийняли свідомо; число кейсів критерієм не є.
Що питають на співбесіді
- «Як обираєш техніку тест-дизайну для нової фічі?» Інтервʼюер дивиться, чи є в тебе критерії, а не лише назви технік. Сильна відповідь структурована: тип логіки → ризик → час → якість специфікації, з прикладом «для полів — класи й межі, для правил — таблиця».
- «Ось фіча Х — як тестуватимеш?» Перевіряють комбінування: чи розкладеш фічу на шари і чи назвеш техніку для кожного, чи почнеш сипати перевірками впереміш. Розбір класичних варіантів цієї задачі — у главі про задачі співбесід.
- «Як тестувати, якщо вимог немає?» Слабка відповідь — «спитаю в аналітика» і крапка. Сильна — план: замінники тестової основи, дослідницькі сесії, фіксація гіпотез, оракул через консистентність, підтвердження гіпотез у продакт-овнера.
- «Скільки тестів достатньо? Коли зупинишся?» Пастка на число. Очікують відповідь через елементи покриття, покриття вимог і свідомо прийнятий залишковий ризик — і згадку, що критерії виходу фіксуються до старту.
- «Навіщо комбінувати техніки, чому не досить однієї?» Перевіряють розуміння, що кожна техніка — модель одного типу складності: еквівалентність не бачить залежності від історії, переходи станів не бачать меж діапазону.
- «Як твій тест-дизайн перетворюється на автотести?» Очікують ланцюжок «техніка → таблиця значень → параметризований тест» і розуміння, що дизайн живе в даних, а не в коді.
Джерела
- ISTQB CTFL Syllabus v4.0 — розділ 4 «Test Analysis and Design»: підрозділ 4.1 «Test Techniques Overview» і техніки підрозділів 4.2–4.4; розгорнутий перелік факторів вибору технік — у попередній версії силабуса (CTFL 3.1, підрозділ 4.1.1).
- Глосарій ISTQB — канонічні означення test basis, coverage item, exit criteria, experience-based test technique.
- ISO/IEC/IEEE 29119-4:2021 «Software and systems engineering — Software testing — Part 4: Test techniques» — формальний каталог технік з означеними елементами покриття для кожної.
- Playwright: Parameterize tests — офіційна документація параметризованих тестів, механіка data-driven із прикладу глави.
За якими критеріями обирають техніку тест-дизайну для нової фічі?
Робочих критеріїв чотири: тип логіки, ризик, час і бюджет, якість специфікації. Перший і головний фільтр — тип логіки, тобто де живе складність задачі: кожна специфікаційна техніка — це модель певного типу складності, і працює вона лише там, де модель збігається з задачею. Ризик визначає, наскільки формальною буде техніка і наскільки глибоким покриття; брак часу зсуває вибір у бік дешевших технік; якість тестової основи (test basis) визначає, яку частку міксу займуть досвідні техніки. Силабус ISTQB (CTFL 3.1) наводив довший перелік факторів — від регуляторних стандартів до навичок команди, — але на практиці він стискається до цих чотирьох. Сильна відповідь на співбесіді — не перелік назв технік, а критерії з прикладом: «для полів — класи й межі, для бізнес-правил — таблиця рішень».
Як за виглядом задачі зрозуміти, з якої техніки почати?
Спитати «де живе складність» і зіставити відповідь з моделлю техніки. Складність у значеннях окремих полів (діапазони, формати, ліміти) — класи еквівалентності плюс граничні значення. Складність у поєднаннях умов («знижка, якщо преміум І сума понад 1000») — таблиця рішень. Та сама дія дає різний результат залежно від минулого — переходи станів. Багато незалежних параметрів конфігурації (браузери × ОС × локалі) — попарне тестування. Наскрізний користувацький потік з винятками — сценарії використання; немає специфікації або їй не віриш — досвідні техніки з дослідницьким тестуванням. Це евристика для старту, а не алгоритм: у реальній фічі складність майже завжди живе в кількох місцях одразу, тож «провідна техніка» перетворюється на комбінацію.
Чому не існує однієї «правильної» техніки для фічі?
Бо кожна техніка — модель рівно одного типу складності і за побудовою не бачить інших. Еквівалентність не помічає залежності результату від історії, переходи станів не бачать меж діапазону, таблиця рішень нічого не каже про наскрізний потік користувача. Застосувати техніку до чужого типу складності можна, але це як забивати шуруп молотком: щось вийде, тримати не буде. Тому реальна фіча розкладається на шари, і для кожного шару обирається своя техніка. Хто шукає one-size-fits-all — лишає діри там, куди обрана техніка не дістає за побудовою.
Специфікаційні техніки застосовані, всі перевірки спроєктовані. Навіщо ще досвідний прохід поверх?
Бо специфікаційні техніки покривають те, що написано у вимогах, а чимала частка дефектів живе саме в тому, чого там немає. Покриття завжди міряється відносно моделі, а модель будується з тестової основи: якщо у вимогах не описано поведінку промокода з пробілами чи подвійний клік «Оплатити», жодна таблиця рішень цього не породить. Дефекти в неописаному ловить лише досвідний шар — передбачення помилок і чеклисти поверх формального дизайну. Тому в комбінуванні технік досвідний прохід — константа, а не опція: він іде останнім кроком незалежно від того, які техніки обрані під шари фічі.
Як ризик впливає на вибір техніки?
Двічі: на вибір самої техніки і на глибину всередині неї. Перше очевидне: чим болючіший і ймовірніший збій, тим формальніша техніка й детальніші артефакти — критичний флоу документується кейсами, які переживуть плинність команди, низькоризикова адмінка обходиться чеклистом. Друге менш очевидне: майже кожна техніка має внутрішні «ручки глибини», і крутити їх треба теж за ризиком, а не за звичкою. Межі — 2-точковий чи 3-точковий аналіз; комбінації — each choice, pairwise чи повна таблиця рішень; стани — всі стани, всі переходи чи ланцюжки переходів; покриття коду — statement, branch чи MC/DC. Логіка скрізь однакова: глибший варіант ловить тонший клас дефектів і коштує помітно дорожче. Полю «нікнейм» досить 2-точкових меж, полю «сума переказу» потрібні 3-точкові, бо ціна off-by-one тут вимірюється грошима.
«Ось фіча оформлення замовлення зі знижками — як тестуватимеш?»
Розкладу на шари і назву техніку для кожного. Поля (кількість, сума, формат промокоду) — класи еквівалентності й межі: скелет перевірок значень. Правила знижки (тип клієнта × сума кошика × промокод) — таблиця рішень: окремі поля вже перевірені, тепер перевіряємо поєднання, зокрема подвійну знижку й конфлікт правил. Життєвий цикл замовлення (створене → оплачене → скасоване → повернене) — переходи станів, особливо невалідні: оплата скасованого через API, повторна оплата з другої вкладки. Наскрізних сценаріїв мало — два-чотири, happy path плюс головні винятки, бо атомарні перевірки вже зроблені попередніми шарами. Поверх — досвідний прохід: unicode у промокоді, подвійний клік «Оплатити», промокод, застосований за секунду до опівночі. Інтервʼюер тут дивиться саме на структуру відповіді: розкладання на шари замість сипання перевірками впереміш.
Як комбінувати техніки так, щоб перевірки не дублювалися?
Тримати дедуплікацію на елементах покриття (coverage items). Кожна техніка породжує свій список елементів — класи, межі, правила, переходи, — і кожен елемент має бути покритий якимось тестом — одного разу достатньо. Один тест може закривати кілька елементів: сценарій оплати заразом проходить і валідний клас суми, і правило знижки — це нормально, якщо звʼязок зафіксований. Практичний наслідок: наскрізний сценарій не повинен перебирати всі формати промокоду, бо вони вже покриті шаром полів, і ганяти їх через повний UI-флоу означає платити хвилини за те, що перевіряється секундами. Атомарні перевірки значень і правил природно опускаються на рівень API, сценарії лишаються тонким шаром зверху — та сама логіка розподілу, що й у піраміді тестування.
Як тестувати фічу, якщо вимог немає взагалі?
Без вимог зникає не метод, а лише звична тестова основа — і її треба замінити. Замінники за спаданням надійності: сам продукт (його поведінка — теж специфікація, хай і неявна), попередня версія фічі, баг-трекер, логи й аналітика реального використання, продукти-аналоги, стандарти платформи і розмова з аналітиком та розробником — пʼятнадцять хвилин часто дають більше, ніж день реверс-інжинірингу. Порядок роботи: спершу дослідницькі сесії будують модель фічі (входи, стани, правила), далі спостережена поведінка фіксується письмово у формі гіпотез, а до зафіксованих гіпотез уже застосовні звичайні техніки — є діапазони, будуй межі; є умови — таблицю. Слабка відповідь на співбесіді — «спитаю в аналітика» і крапка; сильна — саме цей план цілком.
Звідки взяти очікуваний результат, якщо він ніде не описаний?
Це проблема оракула, і робоча відповідь — евристики консистентності. Поведінка має узгоджуватися з попередньою версією продукту, з аналогами, з обіцянками маркетингу, зі стандартами платформи і з рештою самого продукту. Розбіжність із будь-чим із цього списку — не автоматично баг, але завжди привід для питання власнику продукту. Тобто оракул без специфікації — не «мені здається», а перевірка узгодженості з явно названими джерелами, кожне з яких можна предʼявити в дискусії про дефект.
Чому спостережену поведінку системи не можна брати за еталон?
Бо задокументувавши, що система робить, ти зафіксував факт, а не норму. Можливо, промокод не застосовується до акційних товарів через баг, а не задум — і, прийнявши це за еталон, ти вшиваєш дефект у свої ж очікувані результати. Тому гіпотези з реверс-інжинірингу мають статус «підтвердити в продакт-овнера», а не «очікуваний результат». Це одна з улюблених пасток на співбесідах у темі «тестування без вимог»: перевіряють, чи розрізняє кандидат «система так робить» і «система так має робити».
Скільки тестів достатньо? Коли зупинишся?
Число у відповіді — завжди неправильна відповідь; правильна — про модель і залишковий ризик, і в неї три рівні. Рівень технік: кожна застосована техніка дає вимірюваний критерій виходу — кожен клас представлений, кожна межа перевірена, кожне правило має тест, кожен перехід пройдений; «достатньо» означає «елементи покриття обраних технік закриті». Рівень вимог: трасування «вимога → тести» ловить вимоги, для яких тестів не спроєктували взагалі. Рівень ризику: вичерпне тестування неможливе — це другий принцип тестування, — тож щось завжди лишається неперевіреним, і питання лише в тому, чи цей залишок названий і прийнятий: «повний перебір конфігурацій не робили, покрили попарно; ризик — рідкісні потрійні взаємодії». Приймає залишковий ризик не тестувальник, а стейкхолдери — робота тестувальника зробити ризик видимим. І оскільки критерій виходу залежить від обраних технік, вибір технік і вибір моменту зупинки — одне рішення, а не два.
Чому критерії достатності фіксують до початку тестування?
Бо критерій, дописаний наприкінці, магічним чином завжди виявляється виконаним. Якщо межу «коли зупиняємось» можна рухати під фактичний стан прогону, вона перестає бути межею і перетворюється на виправдання. Зафіксований до старту критерій працює і як тест чесності власного дизайну: для кожної непокритої комбінації ти можеш сказати, чому її немає — «відрізали свідомо, бо низький ризик» означає обґрунтовану вибірку, «не подумали» означає діру. Практичний наслідок: критерії виходу — частина плану тестування, а не розділ підсумкового звіту.
Як твій тест-дизайн перетворюється на автотести?
Ланцюжком «техніка → таблиця значень → параметризований тест». Специфікаційні техніки природно видають таблицю: класи, межі, правила рішень зводяться до рядків «вхід → очікуваний результат», а таблиця — готовий вхід для data-driven тесту, де логіка виконання пишеться один раз, а дизайн живе в даних. Таблиця при цьому і є артефакт дизайну: ревʼю перетворюється на ревʼю таблиці, і колега одразу бачить, що 3-точковий аналіз не робили або клас «пароль із пробілами» відсутній — спробуй побачити те саме в копіпаст-тестах. Новий клас — це новий рядок, а не новий тест: дизайн еволюціонує дешево. А поле з поясненням, чому рядок існує (нижня межа, межа плюс один), потрапляє в назву тесту і працює як трасування: звіт прогону читається як карта покриття меж.
Чому data-driven тестування без технік тест-дизайну не працює?
Бо параметризація масштабує дизайн, який уже є, і не створює той, якого немає. Прогнати тисячу випадкових рядків через форму — та сама вибірка навмання, тільки повільніша: усі тисяча можуть лежати в одному валідному класі еквівалентності, і покриття від цього не зросте. Мірило покриття — покриті елементи, а не кількість рядків у прогоні: 8 значень за класами й межами покривають більше, ніж 50 значень з одного класу. Тому порядок жорсткий: спершу класи й межі визначають, які рядки мають бути в таблиці, потім уже генерація наповнює їх значеннями. Data-driven без цього — не тест-дизайн, а дорога рулетка з інфраструктурними витратами.
Чи завжди вибір техніки належить тестувальнику?
Ні — у регульованих доменах вибір може диктувати стандарт, і тоді критерій «регуляторка» бʼє всі інші. У safety-critical розробці стандарти на кшталт DO-178C в авіоніці прямо вимагають певних видів покриття коду: для найкритичнішого рівня — MC/DC (modified condition/decision coverage). Тестувальник тут не обирає між чеклистом і таблицею за ризиком — глибина покриття записана у вимогах сертифікації, і її виконання доводиться регулятору. Для співбесіди це маркер сеньйорності: розуміння, що чотири робочі критерії — це картина для звичайної продуктової розробки, а в авіоніці, медицині чи фінтеху рамка може бути зовнішньою.
Три кейси про головне рішення тест-дизайнера: розкладання фічі «оформлення замовлення зі знижками» на шари з технікою під кожен, план роботи з фічею без жодного рядка вимог і перетворення таблиці рішень на data-driven автотест у Playwright. Скрізь — не «що перевірити», а «чому саме так».
Кейс 1. Фіча «оформлення замовлення зі знижками»: шари замість купи перевірок
Задача зі співбесіди й з життя одночасно: «як тестуватимеш чекаут зі знижками?». Сипати перевірками впереміш — програшний хід; виграшний — таблиця шарів, де в кожного своя техніка і свій рівень виконання.
| Шар | Техніка | Що перевіряємо | Де ганяти |
|---|---|---|---|
| Поля: кількість товару, сума, формат промокоду | Класи еквівалентності + межі | Валідні й невалідні класи, краї діапазонів | API |
| Правила знижки: тип клієнта × сума кошика × промокод | Таблиця рішень | Поєднання умов: подвійна знижка, конфлікт правил | API |
| Життєвий цикл замовлення: створене → оплачене → скасоване → повернене | Переходи станів | Особливо невалідні: оплата скасованого через API, повторна оплата з другої вкладки | API + UI |
| Наскрізний потік: обрав → промокод → оплатив → лист | Сценарії використання | Happy path + 2–3 головні винятки | UI |
| Поверх усього | Error guessing + чеклисти | Unicode і пробіли в промокоді, подвійний клік «Оплатити», промокод за секунду до опівночі | UI/API |
Що дивитися і чому:
- Кожен шар закриває свій тип складності й не лізе в чужий. Сценарій із четвертого рядка не перебирає формати промокоду — вони вже покриті першим шаром, і ганяти їх через повний UI-флоу означає платити хвилини за те, що API перевіряє секундами.
- Наскрізних сценаріїв мало — два-чотири. Це не лінь, а наслідок дизайну: атомарні перевірки значень і правил уже зроблені нижніми шарами, сценаріям лишається тонкий шар потоку. Та сама логіка, що в піраміді тестування.
- Дедуплікацію тримають елементи покриття (coverage items). Кожна техніка породжує свій список — класи, межі, правила, переходи — і кожен елемент має бути покритий якимось тестом — одного разу достатньо. Сценарій оплати заразом закриває і валідний клас суми, і правило знижки — нормально, якщо звʼязок зафіксований.
- Останній рядок — не опція. Специфікаційні шари покривають те, що написано у вимогах; промокод з пробілами й подвійний клік у вимогах не описані ніколи.
Кейс 2. Вимог немає: від дослідження до гіпотез, до яких застосовні техніки
Фіча промокодів дісталася «у спадок»: документації немає, аналітик звільнився. «Тестувати неможливо» — неправильна відповідь; без вимог зникла тестова основа, а не метод.
Перший крок — дослідницькі сесії будують модель: що фіча робить, які входи, стани, правила. Другий — спостережене фіксується письмово у формі гіпотез, кожна з джерелом:
Гіпотези після дослідницької сесії (статус усіх: підтвердити в продакт-овнера)
H1. Промокод застосовується лише до товарів без акції.
Джерело: поведінка продукту — на акційному товарі знижка не зʼявилась.
H2. Мінімальна сума замовлення для промокоду — 200 грн.
Джерело: текст помилки «Промокод діє від 200 грн».
H3. Прострочений промокод дає ту саму помилку, що й неіснуючий.
Джерело: баг-трекер — схожий кейс уже репортили.
Третій крок — до зафіксованих гіпотез застосовуються звичайні техніки: у H2 є діапазон — будуємо межі (199 / 200), у H1 є умови (акційність × промокод) — міні-таблицю рішень.
Що дивитися і чому:
- Джерело в кожній гіпотезі — не бюрократія. Замінники тестової основи мають різну надійність: сам продукт, попередня версія, баг-трекер, логи, аналоги, стандарти платформи. Коли гіпотеза спірна, джерело вирішує, скільки їй віри.
- Статус «підтвердити в продакт-овнера» — головний рядок кейса. Спостережена поведінка — факт, а не норма: можливо, промокод не застосовується до акційних товарів через баг, а не задум. Прийняти це за еталон — вшити дефект у власні очікувані результати.
- Оракул — евристики консистентності. Очікуваний результат звіряють з попередньою версією, аналогами, обіцянками маркетингу, стандартами платформи, рештою продукту. Розбіжність — не автоматично баг, але завжди питання власнику продукту.
- Пʼятнадцять хвилин з розробником часто дешевші за день реверс-інжинірингу. Розмова — теж замінник тестової основи, і не найгірший.
Кейс 3. Таблиця рішень → data-driven тест: дизайн живе в даних
Другий шар з кейса 1 — правила знижки — природно зводиться до таблиці «умови → очікуваний результат». А таблиця — готовий вхід для параметризованого тесту: логіка виконання пишеться один раз, кожен рядок — окреме правило, тобто окремий елемент покриття.
// Playwright: правила знижки як таблиця рішень, кожен рядок — правило
const discountRules = [
{ premium: false, total: 500, promo: false, discount: 0, why: 'жодна умова не виконана' },
{ premium: true, total: 500, promo: false, discount: 0, why: 'преміум без порога суми' },
{ premium: true, total: 1500, promo: false, discount: 10, why: 'преміум І сума понад 1000' },
{ premium: false, total: 1500, promo: true, discount: 5, why: 'лише промокод' },
{ premium: true, total: 1500, promo: true, discount: 10, why: 'конфлікт правил: більша знижка, не подвійна' },
];
for (const { premium, total, promo, discount, why } of discountRules) {
test(`знижка ${discount}% (${why})`, async ({ request }) => {
const res = await request.post('/api/cart/preview', {
data: { premium, total, promoCode: promo ? 'SAVE5' : null },
});
expect(res.ok()).toBeTruthy();
const body = await res.json();
expect(body.discountPercent).toBe(discount);
});
}
Що дивитися і чому:
- Таблиця — це і є артефакт дизайну. Ревʼю тест-дизайну перетворюється на ревʼю пʼяти рядків: колезі одразу видно, що комбінацію «не преміум, сума понад 1000, без промокоду» не перевірили. У пʼяти копіпаст-тестах цю діру шукати довше.
- Останній рядок — найцінніший. Подвійна знижка й конфлікт правил живуть саме в непереглянутих поєднаннях умов — це те, що таблиця рішень ловить за побудовою, а перевірка полів поодинці не побачить ніколи.
- Поле
why— трасування, а не коментар. Воно потрапляє в назву тесту, і звіт прогону читається як карта покриття правил: одразу видно, яке саме правило зламалось. - Новий факт — новий рядок, а не новий тест. Зʼясувалося, що промокод не діє на акційні товари, — додаєш колонку й рядки, код не чіпаєш.
- Дзеркальне застереження: нагенерувати тисячу випадкових рядків замість цих пʼяти — не глибше покриття, а дорога рулетка: всі тисяча можуть лежати в одному правилі. Спершу техніка визначає, які рядки мають бути, потім дані наповнюють їх значеннями.
Критерії вибору техніки
- Знаю чотири робочі критерії вибору: тип логіки, ризик, час і бюджет, якість специфікації — і що перший фільтр завжди «де живе складність».
- Можу пояснити, чому техніка працює лише там, де її модель збігається з типом складності задачі, а поза ним — «шуруп молотком».
- Розумію, що брак часу зсуває вибір у бік дешевших технік, але чесним рішення стає лише коли зрізане покриття назване вголос.
- Знаю, що в регульованих доменах (DO-178C в авіоніці) вибір диктує стандарт — аж до обовʼязкового MC/DC — і тоді «регуляторка» бʼє всі інші критерії.
Мапа «тип задачі → техніка»
- Можу з ходу назвати провідну техніку за виглядом задачі: діапазони й формати полів → еквівалентність + межі; «якщо… і… то…» → таблиця рішень; результат залежить від минулого → переходи станів; багато параметрів конфігурації → pairwise; наскрізний потік → сценарії.
- Знаю, що при відсутній чи недовіреній специфікації стартують досвідні техніки з дослідницьким тестуванням, паралельно відновлюючи вимоги.
- Розумію, що мапа — евристика для старту, а не алгоритм: у реальній фічі складність майже завжди живе в кількох місцях одразу.
Ризик і глибина
- Знаю «ручки глибини» технік — 2- проти 3-точкового аналізу меж; each choice → pairwise → повна таблиця рішень; всі стани → всі переходи → ланцюжки переходів; statement → branch → MC/DC — і що крутять їх за ризиком, а не за звичкою: полю «нікнейм» досить 2-точкових меж, полю «сума переказу» потрібні 3-точкові.
- Розумію, що ризик визначає й формальність артефактів: критичний флоу — детальні кейси, низькоризикова адмінка — чеклист.
Комбінування технік на одній фічі
- Можу розкласти фічу на шари й назвати техніку для кожного: поля → правила → стани → наскрізні сценарії → досвідний прохід поверх.
- Знаю, чому досвідний прохід поверх — константа, а не опція: специфікаційні техніки не бачать дефектів у тому, чого у вимогах немає.
- Розумію дедуплікацію через елементи покриття (coverage items): кожен елемент закритий хоч одним тестом — одного разу достатньо, один тест може закривати кілька елементів (якщо звʼязок зафіксований), а атомарні перевірки опускаються на рівень API, щоб сценарії лишалися тонким шаром зверху.
Тест-дизайн без вимог
- Знаю замінники тестової основи за спаданням надійності: сам продукт, попередня версія фічі, баг-трекер, логи й аналітика, продукти-аналоги, стандарти платформи, розмова з аналітиком і розробником.
- Можу описати порядок роботи: дослідницькі сесії будують модель → поведінка фіксується гіпотезами → до гіпотез застосовуються звичайні техніки.
- Знаю оракул без специфікації — евристики консистентності: узгодженість із попередньою версією, аналогами, маркетингом, стандартами платформи, рештою продукту.
- Памʼятаю, що спостережена поведінка — факт, а не норма: гіпотези з реверс-інжинірингу мають статус «підтвердити в продакт-овнера».
Достатність і data-driven
- Можу відповісти на «скільки тестів достатньо» без числа: закриті елементи покриття обраних технік + покрита кожна вимога + свідомо прийнятий залишковий ризик.
- Знаю, що критерії виходу фіксують до старту тестування, а залишковий ризик приймають стейкхолдери — робота тестувальника зробити його видимим.
- Можу пояснити ланцюжок «техніка → таблиця значень → параметризований тест» і чому таблиця — це і є артефакт дизайну для ревʼю.
- Розумію, чому data-driven без попереднього розбиття на класи — випадкова вибірка з інфраструктурними витратами: параметризація масштабує дизайн, а не створює його.
Який критерій — перший фільтр при виборі техніки тест-дизайну?
Питання
Чотири критерії вибору техніки тест-дизайну