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

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

    Попарне тестування й комбінаторика

    Зміст

    Форма оплати має пʼять параметрів по три-чотири значення кожен — і раптом чесне «перевірити всі комбінації» перетворюється на сотні тест-кейсів, які ніхто ніколи не виконає. (pairwise testing) — техніка, яка стискає цей набір до пари десятків рядків, і робить це не «на око», а з чіткою математичною гарантією: кожна пара значень будь-яких двох параметрів зустрінеться хоча б в одному тесті. На співбесідах ця тема спливає у двох формах: пряме «що таке pairwise» і замасковане «як би ви тестували форму з N параметрами» — і друга форма підступніша, бо перевіряє, чи вмієте ви рахувати комбінації взагалі.

    Це глава-поглиблення: при першому проході розділу її можна пропустити й повернутися після «Вибір і комбінування технік». Базовий трек — класи еквівалентності, граничні значення і таблиці рішень — самодостатній без неї. Але якщо у вашому продукті є конфігураційна матриця «браузери × ОС × ролі» або форма з купою незалежних опцій — ця техніка окупиться швидко.

    Комбінаторний вибух

    Кількість повних комбінацій — це добуток кількостей значень кожного параметра. Візьмімо чекаут інтернет-магазину:

    ПараметрЗначенняКількість
    Спосіб оплатикартка, PayPal, Apple Pay3
    ВалютаUSD, EUR, UAH3
    Доставкакурʼєр, самовивіз, поштомат3
    Платформаweb, iOS, Android3

    Повний перебір: 3 × 3 × 3 × 3 = 81 тест. Додаємо промокод (є/немає) — уже 162. Додаємо стан користувача (гість/залогінений) — 324. Кожен новий параметр множить, а не додає — саме тому це називають комбінаторним вибухом (combinatorial explosion). Для конфігураційної матриці на кшталт «4 браузери × 3 ОС × 4 вʼюпорти × 2 локалі» це 96 повних прогонів — і жодна команда стільки не потягне на кожен реліз.

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

    Гіпотеза попарності

    На чому ґрунтується право викинути більшість комбінацій? На емпіричному спостереженні: переважна більшість дефектів спричинена або одним параметром окремо, або взаємодією двох. Дослідники NIST (Kuhn зі співавторами) розбирали звіти про реальних систем — медичного ПЗ, браузера, сервера, розподіленої бази даних — і виявили: значну частку відмов тригерить одне-єдине значення, разом із парними взаємодіями це закриває переважну більшість, а відмов, що вимагали збігу понад шести параметрів, у вивчених системах не зафіксували взагалі.

    Звідси гіпотеза попарності: якщо набір тестів покриває кожну пару значень кожних двох параметрів, він зловить більшість дефектів взаємодії за малу частку вартості повного перебору. Формально pairwise — це окремий випадок t-wise при t = 2: можна вимагати покриття всіх трійок (3-wise), четвірок і далі — кількість тестів зростає, але лишається незрівнянно меншою за повний перебір. Математичне коріння техніки — ортогональні масиви (orthogonal arrays), які статистики використовували в планах експериментів задовго до тестування ПЗ.

    Важливо чесно розуміти, що гарантія дає і чого не дає:

    • Дає: будь-яка комбінація значень двох параметрів точно зустрінеться щонайменше в одному тесті.
    • Не дає: конкретна трійка значень може не зустрітися ніколи. Баг, який відтворюється лише за збігу «Apple Pay + UAH + поштомат», pairwise-набір має право пропустити.

    Тобто це усвідомлений розмін на вартість, а не безкоштовний обід.

    Побудова pairwise вручну

    Для двох-трьох параметрів набір реально скласти руками — і на співбесіді це іноді просять зробити. Візьмемо мінімальний приклад: браузер (Chrome, Firefox, Safari), ОС (Windows, macOS), роль (admin, user). Повний перебір: 3 × 2 × 2 = 12 тестів.

    Нижня межа pairwise-набору — добуток двох найбільших кількостей значень: тут 3 × 2 = 6, бо всі шість пар «браузер × ОС» мусять десь зʼявитися, а в одному тесті живе лише одна така пара. Алгоритм ручної побудови: виписати декартів добуток двох найбільших параметрів як каркас, а колонки решти параметрів заповнювати так, щоб кожне нове значення закривало ще не покриті пари.

    #БраузерОСРоль
    1ChromeWindowsadmin
    2ChromemacOSuser
    3FirefoxWindowsuser
    4FirefoxmacOSadmin
    5SafariWindowsadmin
    6SafarimacOSuser

    Перевірте самі: усі 6 пар «браузер × ОС» на місці (каркас), усі 6 пар «браузер × роль» — рядки 1–6, усі 4 пари «ОС × роль» — рядки 1, 2 (або 6), 3, 4. Шість тестів замість дванадцяти, і жодна пара не втрачена.

    На чотирьох-пʼяти параметрах ручне заповнення перетворюється на судоку: додав значення в один рядок — зламав покриття в іншому. Тому на практиці набір генерують інструментом.

    PICT: генерація набору

    PICT (Pairwise Independent Combinatorial Tool) — opensource-інструмент від Microsoft, один із найпоширеніших для цієї задачі. Модель — звичайний текстовий файл: параметр, двокрапка, значення через кому.

    PaymentMethod: Card, PayPal, ApplePay
    Currency:      USD, EUR, UAH
    Shipping:      Courier, Pickup, Locker
    Platform:      Web, iOS, Android

    Запуск — одна команда:

    pict model.txt

    На виході — таблиця тест-кейсів (tab-separated), яка покриває всі пари: для моделі вище це близько десяти рядків замість 81 повної комбінації. За замовчуванням PICT генерує саме пари; /o піднімає порядок взаємодії — pict model.txt /o:3 покриє всі трійки, якщо аналіз ризиків каже, що пар замало.

    Constraints: неможливі комбінації

    У реальних системах параметри рідко повністю незалежні: Apple Pay не існує на Android, Safari не живе на Windows. Перша інтуїція — згенерувати набір і викреслити безглузді рядки руками — неправильна: разом із рядком ви викидаєте всі валідні пари, які він покривав, і в наборі зʼявляються діри, яких ніхто не бачить.

    Правильний шлях — описати обмеження (constraints) у самій моделі, тоді генератор перекладе валідні пари в інші рядки:

    IF [PaymentMethod] = "ApplePay" THEN [Platform] <> "Android";
    IF [Platform] = "iOS" THEN [Shipping] <> "Locker";

    Ще дві можливості PICT, які варто знати:

    • Невалідні значення позначаються тильдою (~ExpiredCard): PICT гарантує не більше одного невалідного значення на рядок — це та сама дисципліна «кожен невалідний клас окремим тестом» із глави про , тільки автоматизована.
    • (seeding) — файл із обовʼязковими комбінаціями (прапорець /e): бізнес-критичні сценарії, які мусять бути в наборі, фіксуються явно, а генератор добудовує решту покриття навколо них.

    Коли pairwise недостатньо

    Pairwise — інструмент для одного конкретного класу задач: багато незалежних параметрів, кожна валідна комбінація має сенс, результат не залежить від хитрої логіки між умовами. Поза цим класом техніка або мовчки пропускає баги, або просто не застосовна:

    • Логіка між умовами. Якщо «знижка 10% дається тільки залогіненому з промокодом при сумі понад 1000» — це не незалежні параметри, а бізнес-правила. Тут потрібна таблиця рішень: вона перелічує правила явно й дає очікуваний результат для кожного.
    • Послідовність має значення. Pairwise комбінує значення, але нічого не знає про порядок дій. Сценарії «скасувати після оплати, але до відправлення» — територія переходів станів.
    • Відомі ризиковані трійки. Якщо аналітика багів чи досвід підказує, що конкретні три параметри взаємодіють (оплата × валюта × платіжний ), — підніміть порядок до 3-wise для цієї підмножини або зафіксуйте комбінації сідінгом. Ризик-орієнтований підхід до вибору глибини — канонічно в розділі «Основи тестування».
    • Бракує . Генератор видає входи, але не каже, який результат очікувати в кожному рядку. Якщо очікуваний результат для довільної комбінації визначити важко — виграш від згенерованих 200 рядків ілюзорний: ви не зможете їх перевірити.

    Так

    Ні

    Так

    Ні

    Так

    Ні

    Багато параметрів зі значеннями

    Комбінацій мало —
    до кількох десятків?

    Повний перебір:
    дешевше ніж думати

    Результат визначають
    бізнес-правила між умовами?

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

    Критична послідовність
    дій чи станів?

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

    Pairwise / n-wise
    + constraints + сідінг

    Так

    Ні

    Так

    Ні

    Так

    Ні

    Багато параметрів зі значеннями

    Комбінацій мало —
    до кількох десятків?

    Повний перебір:
    дешевше ніж думати

    Результат визначають
    бізнес-правила між умовами?

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

    Критична послідовність
    дій чи станів?

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

    Pairwise / n-wise
    + constraints + сідінг

    Комбінаторика в конфігураційному тестуванні

    Найчастіше pairwise у вебі застосовують не до полів форми, а до конфігураційної матриці: браузери × ОС × × локалі. Логіка та сама, але з двома особливостями.

    Перша: значення параметрів беруться не зі специфікації, а з аналітики користувачів. Немає сенсу тримати в матриці комбінацію, якою користується 0.1% аудиторії, і пропустити ту, де сидить 40%. Спершу ріжеться список значень (реальні браузери й пристрої вашої аудиторії), потім pairwise ріже комбінації.

    Друга: конфігурації нерівноцінні за вартістю. Прогнати сюїту в headless Chromium — хвилини; на реальному Safari під macOS у фермі — набагато дорожче. Тому типова стратегія — асиметрична: повна сюїта на основній конфігурації, pairwise-редукована матриця на решті, і — на екзотиці.

    В автоматизації конфігураційна матриця живе прямо в конфігурації . У Playwright це projects — кожен рядок вашого pairwise-набору стає окремим проєктом:

    // playwright.config.ts — pairwise-редукована матриця замість повної
    export default defineConfig({
      projects: [
        { name: 'chromium-desktop-uk', use: { ...devices['Desktop Chrome'], locale: 'uk-UA' } },
        { name: 'webkit-desktop-en',   use: { ...devices['Desktop Safari'], locale: 'en-US' } },
        { name: 'firefox-desktop-en',  use: { ...devices['Desktop Firefox'], locale: 'en-US' } },
        { name: 'chromium-mobile-en',  use: { ...devices['Pixel 7'], locale: 'en-US' } },
      ],
    });

    Повна матриця «3 рушії × 2 форм-фактори × 2 локалі» — це 12 проєктів; строгий pairwise дав би 6 (нижня межа — 3 × 2, як у ручному прикладі вище). Чотири рядки вище — наступний крок редукції, уже ризик-орієнтований: кожен рушій проганяється хоча б раз, а «дорогі» пари з локаллю uk-UA і мобільною областю перегляду лишаються тільки на основному рушії аудиторії. Це і є типова еволюція матриці: повний перебір → pairwise → підрізання за аналітикою. Той самий принцип працює для матриць у CI (стратегія прогонів — розділ «Git і CI/CD») і для кросбраузерного тестування верстки (окрема глава в розділі «Веб і мережі»).

    Типові помилки

    • Виглядає як «pairwise покрив усі комбінації», а насправді він гарантує лише пари: трійка «Apple Pay + UAH + поштомат» може не зустрітися в жодному рядку, і баг на її перетині набір пропустить. Скорочення — це прийнятий ризик, і його треба вміти назвати вголос.
    • Виглядає як «згенерував набір, викреслив неможливі рядки — готово», а насправді разом із рядком випали валідні пари, які він покривав. Неможливі комбінації описуються constraints у моделі — тоді генератор перекриє пари іншими рядками.
    • Виглядає як «параметр = поле, значення = все, що є в дропдауні», а насправді значення мають бути представниками й межами. Пхати в модель 25 країн замість 3–4 класів — отримати вибух ще до генерації.
    • Виглядає як «інструмент згенерував 15 тестів — тест-дизайн готовий», а насправді генератор видав лише входи. Очікуваний результат кожного рядка все одно визначає людина; без оракула це не тести, а перелік натискань.
    • Виглядає як «критичні сценарії якось потраплять у набір», а насправді генератор нічого не знає про бізнес-ризик. Комбінацію, на якій компанія заробляє гроші, фіксують сідінгом явно — а не сподіваються на випадковість.

    Підсумок

    • Повний перебір росте як добуток кількостей значень параметрів — кожен новий параметр множить, а не додає. Тому вичерпне комбінування неможливе майже одразу.
    • Pairwise гарантує рівно одне: кожна пара значень будь-яких двох параметрів зустрінеться хоча б в одному тесті. Трійки й глибші взаємодії — поза гарантією; за потреби порядок піднімають до t-wise.
    • Значення для комбінаторики — представники класів еквівалентності й межі, а не сирий перелік із UI. Спершу ріжуться значення, потім — комбінації.
    • Неможливі комбінації описуються constraints у моделі, критичні — фіксуються сідінгом. Ручне викреслювання рядків руйнує покриття непомітно.
    • Pairwise — для незалежних параметрів. Логіка між умовами — ; послідовності — переходи станів; вибір за контекстом — глава про комбінування технік.

    Можливі питання

    • «Форма має 5 параметрів по 4 значення. Скільки тестів для повного перебору і як скоротити?» — Чекають миттєвого 4^5 = 1024 і слова «pairwise» з поясненням гарантії. Інтервʼюер дивиться, чи вмієте ви взагалі порахувати добуток і чи розумієте, що саме втрачається при скороченні.
    • «Що гарантує попарне тестування і чого не гарантує?» — Сильна відповідь: гарантує покриття всіх пар, не гарантує трійок; згадка гіпотези попарності (більшість багів — взаємодія одного-двох параметрів, дані NIST) і що це усвідомлений розмін ризику на вартість.
    • «Якими інструментами будували pairwise-набір?» — Достатньо PICT: модель, constraints, прапорець порядку взаємодії. Червоний прапорець для інтервʼюера — кандидат чув слово, але не знає, що робити з неможливими комбінаціями.
    • «Як ви обрали б браузерну матрицю для регресії?» — Дивляться на порядок міркування: аналітика аудиторії → значення параметрів → pairwise-редукція → асиметрія (повна сюїта на основній конфігурації, смоук на решті). Відповідь «тестуємо на всьому» — програшна, бо ігнорує вартість.
    • «Коли pairwise застосовувати не варто?» — Перевірка зрілості: залежні параметри й бізнес-правила (таблиця рішень), важливий порядок дій (переходи станів), нема оракула для довільної комбінації. Кандидат, який знає межі техніки, цінніший за того, хто застосовує її всюди.

    Формат розгорнутої відповіді на задачі типу «протестуйте форму» — у главі «Класичні задачі співбесід».

    Джерела

    Комбінаторний вибух

    Гіпотеза попарності

    Побудова pairwise вручну

    • ISTQB® Certified Tester Advanced Level Syllabus – Test Analyst (CTAL-TA) v4.0 — чому ручне заповнення впирається в стелю: пошук мінімального набору для попарного покриття канон називає загалом складним і відсилає до інструментів генерації. Самої ручної процедури джерело не дає.

    PICT: генерація набору

    • Microsoft PICT — README (Pairwise Independent Combinatorial Testing) — інструмент і формат моделі: файл із параметрами інтерфейсу, з якого PICT будує компактний набір кейсів; значення параметрів беруться з їхньої природи або з розбиття на класи еквівалентності.
    • Microsoft PICT — документація doc/pict.md — порядок секцій моделі, прапорець /o як шкала глибини комбінацій, пряма заборона просто викреслювати рядки з результату (разом із ними гинуть валідні пари) і тильда для позначення невалідних значень.

    Коли pairwise недостатньо

    • Microsoft PICT — документація doc/pict.md — відповідь на «коли пар мало» тут технічна: /o:3 покриває всі трійки, /o за кількістю параметрів дає вичерпний набір, /o:1 — лише всі значення.
    • ISTQB® Certified Tester Advanced Level Syllabus – Test Analyst (CTAL-TA) v4.0 — глибина комбінацій як функція ризику: вищий може вимагати всіх комбінацій замість попарних, але з обовʼязковим розміном на трудовитрати.

    Комбінаторика в конфігураційному тестуванні

    Пояснення

    «Поясни» працює з власним API-ключем Anthropic: запит іде з вашого браузера прямо до Anthropic.

    Свій API-ключ (BYOK)

    Вставте власний ключ Anthropic — пояснення працюватиме на реальній моделі. Ключ зберігається лише у вашому браузері (localStorage), нікуди не надсилається, крім api.anthropic.com, і не логується.