vyvchy
    Теми розділу

    02 · Тест-дизайн

    Вибір і комбінування технік

    Зміст

    Попередні глави розділу розібрали техніки поодинці: класи еквівалентності, граничні значення, таблиці рішень, переходи станів, сценарії, досвідні техніки. Але робоча задача ніколи не приходить з етикеткою «застосуй BVA». Приходить фіча, дедлайн і специфікація сумнівної повноти — і рішення, якими техніками покривати, наскільки глибоко і коли зупинитися, доводиться ухвалювати самому. Саме це рішення відрізняє рівні: junior знає техніки, senior знає, коли яку і скільки.

    На співбесіді ця різниця видна за пʼять хвилин. «Протестуй форму» junior починає з перерахування перевірок, senior — з уточнень і вибору інструментів: де тут дані, де комбінації умов, де стани, що з цього ризиковане. Питання «як обираєш підхід до тестування фічі», «скільки тестів достатньо», «як тестувати без документації» — усе це питання цієї глави.

    Чотири критерії вибору

    Силабус ISTQB (CTFL 3.1; у v4.0 явний перелік прибрали) наводив довгий список факторів вибору технік — серед них складність компонента, регуляторні стандарти, вимоги контракту, рівень ризику, доступна документація, знання й навички тестувальників, час і бюджет, модель розробки. На практиці цей список стискається до чотирьох робочих критеріїв.

    Тип логіки — де живе складність. Головний і перший фільтр. Кожна специфікаційна техніка — це модель певного типу складності, і техніка працює лише там, де її модель збігається з задачею. Складність у значеннях окремих полів (діапазони, формати, ліміти) — це еквівалентність і межі. Складність у поєднаннях умов («знижка, якщо преміум І сума понад 1000») — таблиця рішень. Складність в історії (та сама дія дає різний результат залежно від минулого) — переходи станів. Складність у кількості конфігурацій (браузери × ОС × локалі) — попарне тестування. Складність у потоці користувача — сценарії. Застосувати техніку до чужого типу складності можна, але це як забивати шуруп молотком: щось вийде, тримати не буде.

    Ризик. Чим болючіший можливий збій і чим він імовірніший, тим формальніша техніка й глибше покриття. Канонічний розбір ризик-орієнтованого підходу — у розділі «Основи тестування», глава про ризик-орієнтоване тестування; тут важлива його проєкція на вибір технік, про неї — окремий підрозділ нижче.

    Час і бюджет. Повна таблиця рішень на 6 бінарних умов — це 64 правила; на переоцінений компонент цього ніхто не дасть. Брак часу зсуває вибір у бік дешевших технік — чеклистів і досвідного проходу — але чесним рішення стає лише тоді, коли зрізане покриття назване вголос: «встигаємо перевірити правила знижок попарно, повний перебір — ні, ризик такий-то».

    Якість специфікації. Специфікаційним технікам потрібна специфікація: без описаних правил нема з чого будувати таблицю рішень. Що гірша тестова основа (test basis), то більша частка досвідних технік у міксі — аж до випадку «вимог немає взагалі», якому нижче присвячений окремий підрозділ.

    Абзац глибини для регульованих доменів: у safety-critical розробці вибір техніки — не завжди твій. Стандарти на кшталт DO-178C в авіоніці прямо вимагають певних видів покриття коду (для найкритичнішого рівня — MC/DC, розібраний у главі про білоскринькові техніки). Тоді критерій «регуляторка» бʼє всі інші.

    Мапа «тип задачі → техніка»

    Робоча шпаргалка. У лівій колонці — те, що ти бачиш у задачі, у правій — провідна техніка, з якої варто почати.

    Що бачиш у задачіПровідна техніка
    Поле чи параметр із діапазонами, форматами, лімітамиКласи еквівалентності + граничні значення
    Бізнес-правило з кількох умов («якщо… і… то…»)Таблиця рішень
    Результат дії залежить від того, що було ранішеПереходи станів
    Багато незалежних параметрів конфігураціїПопарне тестування
    Наскрізний користувацький потік з виняткамиСценарії використання
    Специфікації немає або їй не віришДосвідні техніки + дослідницьке тестування
    Критичний алгоритм, є доступ до коду й coverage-звітівБілоскринькові техніки

    Та сама мапа як послідовність питань, які можна проговорити на співбесіді:

    Ні

    Так

    У значеннях полів

    У комбінаціях умов

    В історії станів

    У конфігураціях

    У потоці користувача

    Нова задача

    Є специфікація, якій віриш?

    Досвідні техніки + дослідницьке
    паралельно відновлюй вимоги

    Де живе складність?

    Еквівалентність + межі

    Таблиця рішень

    Переходи станів

    Pairwise

    Сценарії використання

    Поверх усього: error guessing і чеклисти

    Ні

    Так

    У значеннях полів

    У комбінаціях умов

    В історії станів

    У конфігураціях

    У потоці користувача

    Нова задача

    Є специфікація, якій віриш?

    Досвідні техніки + дослідницьке
    паралельно відновлюй вимоги

    Де живе складність?

    Еквівалентність + межі

    Таблиця рішень

    Переходи станів

    Pairwise

    Сценарії використання

    Поверх усього: error guessing і чеклисти

    Два застереження. Перше: це евристика для старту, а не алгоритм — у реальній фічі складність майже завжди живе в кількох місцях одразу, тому «провідна техніка» перетворюється на «комбінація технік» (наступний підрозділ). Друге: останній крок — досвідний прохід поверх — не опція, а константа: специфікаційні техніки покривають те, що написано у вимогах, а чимала частка дефектів живе саме в тому, чого там немає.

    Ризик задає не лише техніку, а й глибину

    Менш очевидна половина ризик-орієнтованого вибору: майже кожна техніка має внутрішні «ручки глибини», і крутити їх треба теж за ризиком, а не за звичкою.

    ВажільЕкономний варіантГлибокий варіант
    Межі діапазону2-точковий аналіз3-точковий аналіз
    Комбінації полівEach choice (кожне значення хоч раз)Pairwise → повна таблиця рішень
    Переходи станівПокрити всі станиУсі переходи, потім ланцюжки переходів
    Покриття кодуStatement coverageBranch, далі MC/DC

    Логіка однакова на всіх рядках: глибший варіант ловить тонший клас дефектів і коштує помітно дорожче. Для поля «нікнейм» досить 2-точкового аналізу меж; для поля «сума переказу» — 3-точковий, бо ціна off-by-one тут вимірюється грошима. Для матриці браузерів інтранет-звіту досить each choice; для правил нарахування комісії — повна таблиця, бо саме в непереглянутій комбінації умов живе найдорожчий баг.

    Ризик визначає й формальність артефактів: критичний флоу документується детальними кейсами, які переживуть плинність команди, а низькоризикова адмінка — чеклистом. Це та сама шкала деталізації, що розібрана в главі про рівень деталізації кейсів, тільки тепер у неї зʼявився критерій вибору.

    Комбінування технік на одній фічі

    Розберімо на фічі «оформлення замовлення зі знижками» — досить типовій, щоб бути впізнаваною, і досить складній, щоб жодна техніка поодинці її не закрила.

    1. Поля — кількість товару, сума, формат промокоду: класи еквівалентності + межі. Це дає скелет перевірок значень: валідні класи, невалідні класи, краї діапазонів.
    2. Правила знижки — тип клієнта × сума кошика × наявність промокоду: таблиця рішень. Окремі поля вже перевірені, тепер перевіряємо поєднання: чи не дає система подвійну знижку, чи правильно розвʼязується конфлікт правил.
    3. Життєвий цикл замовлення — створене → оплачене → скасоване → повернене: переходи станів. Особливо невалідні: оплата скасованого замовлення через API, повторна оплата з другої вкладки.
    4. Наскрізні сценарії — happy path «обрав → застосував промокод → оплатив → отримав лист» плюс головні винятки: сценарії використання. Їх мало — два-чотири, — бо атомарні перевірки вже зроблені кроками 1–3.
    5. Поверх — досвідний прохід: 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 чи повна таблиця, стани чи ланцюжки переходів.
    • Одна фіча — комбінація технік: специфікаційні будують скелет по шарах без дублювання перевірок, досвідний прохід зверху обовʼязковий.
    • Без вимог зникає основа, а не метод: дослідження → зафіксовані гіпотези → звичайні техніки; спостережена поведінка — факт, що потребує підтвердження, а не еталон.
    • «Достатньо» — це закриті елементи покриття обраних технік плюс залишковий ризик, який стейкхолдери прийняли свідомо; число кейсів критерієм не є.

    Що питають на співбесіді

    • «Як обираєш техніку тест-дизайну для нової фічі?» Інтервʼюер дивиться, чи є в тебе критерії, а не лише назви технік. Сильна відповідь структурована: тип логіки → ризик → час → якість специфікації, з прикладом «для полів — класи й межі, для правил — таблиця».
    • «Ось фіча Х — як тестуватимеш?» Перевіряють комбінування: чи розкладеш фічу на шари і чи назвеш техніку для кожного, чи почнеш сипати перевірками впереміш. Розбір класичних варіантів цієї задачі — у главі про задачі співбесід.
    • «Як тестувати, якщо вимог немає?» Слабка відповідь — «спитаю в аналітика» і крапка. Сильна — план: замінники тестової основи, дослідницькі сесії, фіксація гіпотез, оракул через консистентність, підтвердження гіпотез у продакт-овнера.
    • «Скільки тестів достатньо? Коли зупинишся?» Пастка на число. Очікують відповідь через елементи покриття, покриття вимог і свідомо прийнятий залишковий ризик — і згадку, що критерії виходу фіксуються до старту.
    • «Навіщо комбінувати техніки, чому не досить однієї?» Перевіряють розуміння, що кожна техніка — модель одного типу складності: еквівалентність не бачить залежності від історії, переходи станів не бачать меж діапазону.
    • «Як твій тест-дизайн перетворюється на автотести?» Очікують ланцюжок «техніка → таблиця значень → параметризований тест» і розуміння, що дизайн живе в даних, а не в коді.

    Джерела