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

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

    Покриття вимог і трасування

    Зміст

    «Ми протестували достатньо?» — питання, на яке доводиться відповідати перед кожним релізом. Відповідь «ну, ми багато тестували» не приймає ні менеджер, ні інтервʼюер. Аргументована відповідь завжди зводиться до покриття: скільки елементів із тих, що треба було перевірити, реально закрито тестами. І тут же перша пастка: «покриття 87%» без уточнення, чого саме 87%, — порожній звук. 87% вимог, рядків коду чи правил таблиці рішень — це три різні числа про три різні речі.

    Ця глава — про те, як звʼязати вимоги з тестами так, щоб на «чи все покрито?» відповідала таблиця, а не інтуїція: види покриття, матриця трасування (RTM), пошук прогалин і тестів-сиріт, і як усе це живе в TMS та автотестах. Ланцюжком test basis → тестова умова → тест-кейс із глави про шлях від вимоги до перевірки ми досі рухалися лише вперед — від вимоги до кейсів. Тепер навчимося ходити ним в обидва боки.

    Покриття — це завжди покриття «чогось»

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

    Вид покриттяБаза (звідки елементи)Елемент покриттяНа яке питання відповідає
    ВимогСпецифікація, user story, критерії прийманняВимога або окремий критерійЧи перевірено все, що обіцяли користувачу
    КодуВихідний кодОператор, гілка, умоваЧи виконувався тестами весь написаний код
    РизиківМатриця ризиківІдентифікований продуктовий ризикЧи прикриті найнебезпечніші сценарії

    Ключове: це три незалежні осі, і одна не замінює іншу. Код може виконуватися тестом, який нічого по суті не перевіряє, — покриття коду зросте, покриття вимог ні. Вимога може бути взагалі не реалізована — покриття коду цього не покаже, бо неіснуючі рядки не входять у знаменник; а от у матриці вимог така діра світиться одразу. Тому «покриття вимог 100%, покриття коду 60%» — не суперечність, а нормальна картина: тести ходять по всіх вимогах, але частина коду (обробка помилок, службові гілки) ними не зачеплена.

    Механіку покриття коду — statement, branch і чому 100% операторів не означає 100% гілок — розбираємо окремо в главі про білоскринькові техніки. Покриття ризиків спирається на матрицю «ймовірність × вплив» — це канонічна тема ризик-орієнтованого тестування в розділі про основи тестування; тут важливо лише, що ризик — така сама одиниця покриття, як вимога чи гілка коду.

    Елементи покриття технік

    Кожна техніка тест-дизайну з попередніх глав — це, по суті, машинка з виробництва елементів покриття (coverage items): вона бере вимогу і видає скінченний список того, що треба закрити тестами.

    ТехнікаЕлемент покриття100% означає
    Класи еквівалентностіКлас (партиція)Кожен клас зачеплено хоча б одним значенням
    Граничні значенняМежаПеревірено всі межі (2- або 3-точково)
    Таблиці рішеньПравило (стовпець таблиці)Кожне здійсненне правило має свій кейс
    Переходи станівСтан або перехідПройдено всі стани / всі переходи
    Покриття кодуОператор, гілкаВиконано весь код / усі гілки

    Саме тому «покрито на 100%» — незавершене речення, поки не названо техніку. 100% класів еквівалентності і 100% переходів станів для тієї самої фічі — різні набори тестів і різний рівень впевненості. Звідси й сильна відповідь на класичне «як зрозуміти, що тестів достатньо?»: обираю техніку під тип логіки, рахую її елементи покриття, показую, що всі закриті, — а решту добираю за ризиками. Як саме обирати техніку — тема глави про вибір і комбінування технік.

    RTM: матриця, яка звʼязує вимоги з тестами

    Матриця трасування вимог (requirements traceability matrix, RTM) — таблиця відповідності між вимогами і тестами, найпростіший робочий вигляд якої такий:

    ВимогаТест-кейсиОстанній прогін
    REQ-101 Пароль 8–64 символиTC-310, TC-311, TC-312passed
    REQ-102 Блокування після 5 невдалих спробTC-315, TC-316TC-316 failed
    REQ-103 Відновлення пароля через emailтестів немає

    Одна таблиця відповідає одразу на три питання: що покрито, що зламано (failed у TC-316 миттєво перекладається мовою бізнесу — «під загрозою блокування акаунтів») і де діра (REQ-103 узагалі без тестів). Без матриці кожне з цих питань — окреме розслідування.

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

    назад: яку вимогу зачеплено

    Вимога / AC
    REQ-102

    Тестові умови

    Тест-кейси
    TC-315, TC-316

    Результат прогону

    Дефект BUG-77

    назад: яку вимогу зачеплено

    Вимога / AC
    REQ-102

    Тестові умови

    Тест-кейси
    TC-315, TC-316

    Результат прогону

    Дефект BUG-77

    Два практичні рішення при побудові:

    • Гранулярність. Трасувати варто до окремого критерію приймання або тестової умови, а не до user story цілком. Story з вісьмома AC, до якої прилінковано один happy-path тест, у матриці виглядає «покритою» — і це найпоширеніший спосіб самообману. Формати AC та їхню роль розбирали у главі про сценарії використання.
    • Дефекти теж у ланцюжку. Регресійний тест, написаний на баг, часто трасується не на вимогу, а на дефект. Якщо матриця бачить лише вимоги, такі тести виглядають сиротами — хоча прикривають реальні болючі місця.

    Тепер про підтримку — і це важливіше за побудову. RTM, складена один раз, протухає в день першої зміни вимог. Живою матриця лишається за єдиної умови: звʼязки оновлюються в тому самому процесі, де змінюються вимоги і тести. Новий кейс без лінка на вимогу не проходить рев'ю; вимога змінилась — тікет не закривається, поки не переглянуті привʼязані тести. Excel-матриця, яку хтось «актуалізує щоквартально», цієї умови не витримує — тому на практиці трасування живе в TMS, де лінк ставиться за секунду в момент створення кейсу.

    Пошук прогалин: неперевірені вимоги і тести-сироти

    Двобічність трасування дає два протилежні типи знахідок.

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

    Тест-сирота (orphan test) — тест, не привʼязаний до жодної вимоги. Тут головне — не хапатися за кнопку «видалити». У сироти три типові причини, і лише одна з них — сміття:

    • вимогу змінили або видалили, а тест лишився — кандидат на оновлення чи видалення;
    • тест перевіряє недокументовану, але реальну поведінку — хтось колись знайшов баг чи мовчазне очікування користувачів і закрив його тестом; правильна дія — задокументувати вимогу і привʼязати, а не зносити перевірку;
    • тест дублює наявний — ось це справді баласт.

    Тому робота з сиротами починається з питання «що ти перевіряєш?», а не з чистки. Механічне видалення всіх сиріт — класичний спосіб знести регресійні перевірки багфіксів і отримати повторне відкриття старих дефектів.

    Третя, найбільш недооцінена користь трасування — аналіз впливу (impact analysis). Вимога змінилася: backward-трасування за секунду відповідає, які тести застаріли і що треба прогнати, — замість «переглянемо всі 800 кейсів, раптом щось зачепило». Це щоденна робоча функція матриці; звіт про покриття — лише її побічний продукт.

    Метрики покриття: користь і межі

    Користь метрики покриття вимог — у трьох ролях:

    • Критерій виходу. «Усі вимоги релізу покриті, критичні — пройдені» — вимірюваний рядок у тест-плані замість «тестування завершено, коли скінчився час».
    • Прозорість. Менеджменту не цікаво «ми стараємось»; «94 зі 100 критеріїв закриті, ось список шести відкритих з ризиками» — мова, якою ухвалюють рішення про реліз.
    • Аргумент при скороченні. Коли часу на повну регресію немає, матриця показує, що саме випадає з прогону і які вимоги лишаються без сітки, — скорочення стає керованим ризиком, а не лотереєю.

    Тепер межі — і на співбесіді middle-рівня питають саме про них:

    • Метрика бінарна. Вона бачить наявність звʼязку, а не силу перевірки. Вимога з одним поверховим happy-path тестом і вимога з двадцятьма тестами за класами і межами у звіті виглядають однаково: «покрито». Сто відсотків покриття вимог — це «на кожну вимогу є хоч щось», не більше.
    • Метрика сліпа до невимовленого. Покриття вимог рахується від написаних вимог. Усе, чого в специфікації немає — неявні очікування, нефункціональні аспекти, поведінка на стиках фіч, — у знаменник не потрапляє. Система може пройти 100% вимог і бути непридатною: це помилкове уявлення про відсутність дефектів (absence-of-defects fallacy) із семи принципів тестування (розділ про основи тестування).
    • Метрика-ціль псується. Щойно відсоток покриття стає KPI, він росте найдешевшим способом: вимоги дробляться на тривіальні, до них лінкуються аби-які тести. Число зелене, впевненості нуль. Покриття — діагностичний прилад для команди, а не показник продуктивності для звіту.

    Трасування в TMS і звʼязка з автотестами

    У TMS (TestRail, Zephyr, Xray тощо) трасування — це не окремий документ, а побічний продукт гігієни: кейс має поле звʼязку з вимогою (типово — тікет у Jira), дефект лінкується до кейсу й вимоги, а RTM і звіт покриття будуються автоматично як зріз цих лінків. Ручна Excel-матриця вмирає на першій сотні кейсів; у TMS вона оновлюється тим самим рухом, яким створюється кейс.

    З автотестами є розрив: код живе в git, вимоги — у трекері. Стандартне рішення — ID вимоги в тегах або анотаціях тесту:

    import { test, expect } from '@playwright/test';
    
    test('акаунт блокується після пʼяти невдалих спроб входу',
      { tag: ['@REQ-102'] },
      async ({ page }) => {
        // кроки перевірки
      });

    Такий тег працює одразу на два боки:

    • Трасування. Репортери TMS-інтеграцій читають теги і привʼязують результати прогону до кейсів та вимог — колонка «останній прогін» у матриці заповнюється без ручної праці.
    • Фільтр запуску. npx playwright test --grep "@REQ-102" — прогін усіх перевірок конкретної вимоги перед її релізом чи після зміни. Трасування перестає бути звітністю і стає інструментом запуску.

    Правило гігієни те саме, що й для кейсів у TMS: тег вимоги додається в тому ж pull request, що й сам тест. Трасування, яке «допишемо потім», не доживає до потім.

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

    • Виглядає як «покриття вимог 100% — можна релізити», а насправді метрика каже лише, що на кожну вимогу є хоча б один тест. Вона мовчить і про якість цих тестів, і про все, чого у вимогах не написали.
    • Виглядає як «RTM — документ, який складають наприкінці для звіту», а насправді головна функція матриці — щоденний impact analysis і пошук прогалин. Складена постфактум, вона протухла ще до того, як її відкрили.
    • Виглядає як «тест без вимоги — сміття, видаляємо», а насправді сирота часто прикриває недокументовану вимогу або старий багфікс. Спершу зʼясуй, що він перевіряє, — потім вирішуй.
    • Виглядає як «прилінкували тест до user story — покрито», а насправді story з вісьмома критеріями приймання формально «закрита» одним happy-path тестом. Трасувати треба до окремого критерію чи тестової умови.
    • Виглядає як «покриття коду 85%, отже вимоги майже покриті», а насправді це різні осі: код може виконуватися без змістовних перевірок, а нереалізовану вимогу покриття коду не побачить узагалі.

    Підсумок

    • Покриття — це дріб «перевірені елементи / всі ідентифіковані елементи». Без назви бази (вимоги, код, ризики, елементи конкретної техніки) відсоток беззмістовний.
    • Кожна техніка тест-дизайну постачає власні елементи покриття; вимоги, код і ризики — три незалежні осі, одна не замінює іншу.
    • Цінність RTM — у двобічності: вперед вона знаходить неперевірені вимоги, назад — тести-сироти і відповідь на «що прогнати після зміни вимоги».
    • Матриця жива, лише якщо звʼязки оновлюються в тому самому процесі, де змінюються вимоги й тести; актуалізація «раз на квартал» — це мертвий документ.
    • Метрика покриття показує наявність звʼязку, а не силу перевірки; 100% — привід спитати «100% чого і наскільки глибоко», а не розслаблятися.

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

    • «Що таке RTM і навіщо вона?» Слабка відповідь зупиняється на «табличка вимоги-тести для звіту». Сильна називає двобічне трасування і щоденні функції: пошук прогалин, тести-сироти, impact analysis при зміні вимог.
    • «Як зрозуміти, що тестів достатньо?» Інтервʼюер чекає структуру, а не «коли час скінчився»: елементи покриття обраних технік закриті, вимоги трасовані, залишкові прогалини названі і прийняті за ризиком.
    • «Покриття вимог 100%, покриття коду 60% — як це можливо?» Перевірка, чи розумієш різні бази вимірювання. Бонус — зворотний приклад: високе покриття коду при дірявих вимогах.
    • «Вимога змінилася — ваші дії?» Дивляться, чи згадаєш трасування як інструмент: backward-звʼязки дають список тестів на оновлення і прогін, без перегляду всього набору.
    • «Як ви звʼязуєте автотести з вимогами?» Очікують практику: ID вимоги в тегах/анотаціях, TMS-інтеграція з результатами прогонів, тег як фільтр запуску. Плюс — правило «лінк у тому ж PR, що й тест».

    Джерела