Баг-репорт і життєвий цикл дефекту
Зміст
Розробник виправляє не той баг, який ти знайшов, а той, який ти описав. Тому баг-репорт (bug report, defect report) — найважливіший письмовий продукт тестувальника: знайти дефект — половина роботи, друга половина — донести його так, щоб хтось інший відтворив, зрозумів наслідки й виправив саме його. Погано описаний дефект живе довше і ходить по колу «не відтворюється — глянь ще раз», зʼїдаючи час двох людей.
Баг-репорт — це асинхронна комунікація: його читатимуть без тебе, через тиждень, в іншому контексті, можливо — людина, яка ніколи не бачила цієї фічі. Тому кожне поле репорту існує не «для порядку в трекері», а відповідає на конкретне питання читача. Що таке дефект і чим він відрізняється від помилки та відмови — розібрано в базових поняттях; тут — що робити, коли дефект уже знайдено.
Структура баг-репорту
Назви полів різняться між трекерами (Jira, Azure DevOps, YouTrack), але набір стабільний, бо кожне поле закриває питання, без відповіді на яке фікс гальмує:
| Поле | На яке питання відповідає |
|---|---|
| Заголовок | Що зламалося, де і за яких умов — одним рядком |
| Кроки відтворення | Як мені побачити це в себе? |
| Фактичний результат | Що саме сталося, з точним текстом помилки |
| Очікуваний результат | Що мало статися і звідки це відомо (вимога, AC) |
| Середовище | Оточення, білд/версія, браузер, ОС — де саме це відбулося |
| Серйозність (severity) | Наскільки тяжкі технічні наслідки |
| Пріоритет (priority) | Наскільки терміново це виправляти |
| Атачі | Докази: скриншот, відео, логи, HAR |
Два поля заслуговують окремих слів.
Заголовок — це те, за чим баг шукатимуть у трекері через пів року. Робоча формула: «що + де + за яких умов». Порівняй: «Не працює оплата» проти «Checkout: 500 при оплаті замовлення із застосованим промокодом». Перший заголовок змушує відкривати репорт, щоб зрозуміти, про що він; другий уже сам по собі — діагноз.
Очікуваний результат — найчастіше недооцінене поле. «Має працювати коректно» — це порожнє місце: розробник не знає, що для тебе «коректно». Сильний очікуваний результат посилається на джерело істини — вимогу, acceptance criteria, макет чи усталену поведінку сусідніх фіч. Саме це поле перетворює «мені здається, тут не так» на «продукт порушує ось цю домовленість».
Мінімальний робочий приклад цілком:
Заголовок: Checkout: 500 при оплаті замовлення із застосованим промокодом
Середовище: stage, білд 2.14.3, Chrome 138, macOS
Severity: Critical Priority: High Частота: 5/5
Передумови: у кошику один товар, промокод SUMMER10 застосовано
Кроки:
1. Відкрити /checkout
2. Заповнити дані доставки валідними значеннями
3. Натиснути «Сплатити»
Фактичний результат: сторінка помилки; POST /api/orders повертає 500,
тіло відповіді: {"error": "discount_id is null"}
Очікуваний результат: замовлення створено, редірект на /order/confirmation
(AC-3 у сторі ORD-214)
Атачі: скриншот помилки, HAR, відео
Зверни увагу на рядок «Частота: 5/5» — скільки разів дефект відтворився зі скількох спроб. Для стабільних багів це формальність, для плаваючих — критична інформація, яка чесно попереджає розробника, що з першої спроби може не вийти.
І правило, яке економить найбільше: один дефект — один репорт. Три проблеми в одному тикеті означають, що після фікса першої тикет закриють, а дві решти загубляться.
Кроки відтворення
Кроки відтворення (steps to reproduce) — серце репорту. Хороші кроки мають три властивості:
- Відтворюваність з нуля. Кроки починаються зі стану, який читач може створити сам: передумови явні (який користувач, які дані, який стан системи), а не «на моєму акаунті». Про стенди й білди, які фіксуються в передумовах, — глава про тестові середовища.
- Конкретні дані. Не «ввести довге імʼя», а «ввести імʼя з 256 символів». Не «застосувати промокод», а «застосувати SUMMER10». Дефект часто живе саме в даних, і «будь-які» значення його не покажуть.
- Мінімальність. Перед заведенням бага сценарій варто звузити: прибрати кроки й умови, без яких дефект однаково відтворюється. Якщо 500 на оплаті ловиться і без заповнення доставки — крок про доставку зайвий. Мінімальний сценарій не лише швидше перевіряти — він сам по собі підказує, де причина: усе, що лишилося в кроках, і є умовами прояву.
Чим кроки в баг-репорті відрізняються від кроків у тест-кейсі: кейс описує заплановану перевірку, репорт — фактичний шлях до дефекту. Тому кроки репорту завжди конкретніші й вужчі — це не сценарій «перевірити оплату», а точний маршрут до однієї ями (структура тест-кейсу — у попередній главі).
Severity vs priority
Класика співбесід, яку питають майже завжди. Різниця проста, поки не змішувати дві осі:
- Severity (серйозність) — наскільки тяжкі технічні наслідки дефекту для системи й користувача: краш, втрата даних, непрацююча функція, косметика. Зазвичай виставляє тестувальник, бо саме він бачив наслідки. Типова шкала: critical / major / minor / trivial (плюс blocker — коли дефект блокує саме тестування).
- Priority (пріоритет) — наскільки терміново дефект треба виправити з погляду бізнесу. Виставляє той, хто відповідає за продукт і чергу робіт: продакт-менеджер або лід, часто на тріажі (triage) — регулярному розборі нових багів.
Осі незалежні, тому реальні всі чотири комбінації:
| Severity | Priority | Приклад |
|---|---|---|
| Висока | Високий | 500 при оплаті: checkout лежить у всіх користувачів, компанія втрачає гроші щохвилини |
| Висока | Низький | Краш при експорті річного звіту, який бухгалтерія формує раз на рік, — а до звітного періоду пів року |
| Низька | Високий | Одрук у назві компанії на головній сторінці за день до запуску рекламної кампанії: технічно дрібниця, репутаційно — ні |
| Низька | Низький | Іконка зʼїхала на два пікселі у футері сторінки «Умови використання» |
Комбінації «висока severity + низький priority» і навпаки — улюблені на співбесідах, бо перевіряють, чи розумієш ти саме незалежність осей, а не завчив означення. Ключ до прикладів: severity дивиться на тяжкість наслідку, priority — на те, скільки людей і грошей це зачіпає зараз.
Життєвий цикл дефекту
Від заведення до закриття дефект проходить ланцюжок статусів. Конкретні назви залежать від трекера й процесу команди, але скелет однаковий усюди:
Ключові точки маршруту:
- New → тріаж. Свіжий баг спершу проходить розбір: чи дефект це взагалі, чи не дублікат, який пріоритет. Саме тут репорт «продає» себе — і саме тому якість опису вирішує.
- Fixed → ретест. Розробник перевів баг у «виправлено» — це означає лише, що фікс потрапив у білд. Закриває баг тестувальник після ретесту на тому середовищі, куди фікс доїхав. Різниця між ретестом і регресією — у главі про смоук і регресію.
- Reopened — лише якщо не виправлено те саме: ті самі кроки знову дають той самий фактичний результат. Якщо фікс зламав щось поруч — це новий дефект з новим репортом, а не reopen: у нового бага інші кроки, інша причина й, можливо, інший виконавець.
Баг не відтворюється
«Cannot reproduce» — не вирок і не привід мовчки закрити тикет. Дефект, який відтворюється нестабільно, нікуди не подівся — просто не всі умови його прояву потрапили в репорт. Систематичний перелік гіпотез, звідки береться різниця «у мене відтворюється — у розробника ні»:
- Середовище. Інше оточення (test проти stage), інший білд, інша конфігурація. Перше, що звіряють, — рядок «Середовище» з репорту.
- Дані та стан. У тебе користувач із промокодом і історією замовлень, у розробника — чистий акаунт. Стан бази часто і є «секретною» умовою відтворення.
- Кеш. Браузер або CDN віддає стару версію фронтенду — у вас із розробником буквально різні застосунки. Як це працює і як діагностується — у главі про кешування.
- Таймінги й гонки. Дефект проявляється лише на повільній мережі, при швидких кліках, при паралельних діях. Саме такі баги відтворюються «3 з 10» — і саме вони найболючіше стріляють у проді, бо там користувачів і паралельності більше, ніж на стенді.
- Платформа. Браузер, його версія, ОС, розширення.
Що робити практично: зафіксувати частоту спроб («відтворилося 2 з 10»), зібрати артефакти в момент прояву (скриншот, HAR, логи з часовою міткою — щоб бекенд-лог можна було зіставити з моментом помилки) і додати все це в репорт. Якщо дефект впіймано один раз і більше ніяк — чесний варіант: репорт з усіма доказами й позначкою про частоту. Один раз побачений 500 з тілом відповіді в атачі — це вже зачіпка для розробника в серверних логах, навіть без стабільного відтворення.
Duplicate, rejected, won't fix
Не кожен баг завершується фіксом — і це нормальні, а не «поразкові» фінали:
- Duplicate (дублікат) — такий дефект уже заведено. Ліки профілактичні: перед заведенням пошукати в трекері за ключовими словами й текстом помилки. Якщо дублікат усе ж стався — тикети лінкують: два незалежні прояви — корисна інформація про частоту.
- Rejected / not a bug — поведінка відповідає вимогам (works as designed), або «дефект» виявився нерозумінням фічі. Перший крок при незгоді — перечитати вимогу: можливо, права саме вона. Якщо вимога мовчить — це вже інша знахідка: дірка у вимогах, і її теж варто зафіксувати.
- Wonʼt fix — дефект визнано, але виправляти не будуть: вартість фікса вища за шкоду, фіча доживає останні місяці, кейс екзотичний. Це бізнес-рішення про пріоритети, а не оцінка твоєї роботи. Задача тестувальника — щоб рішення ухвалювалося з повною картиною наслідків, і щоб воно лишилося зафіксованим письмово: коли дефект вистрелить у проді, історія «ми знали і свідомо відклали» звучить зовсім інакше, ніж «ніхто не знав».
- Deferred (відкладено) — проміжний варіант: виправлять, але не в цьому релізі.
Аргументація без емоцій
Баг-репорт і коментарі під ним читають люди — і найкращий опис дефекту можна знецінити одним пасивно-агресивним рядком. Кілька правил, які відрізняють професійну комунікацію від сварки в трекері:
- Факти замість оцінок. «POST /api/orders повертає 500 при застосованому промокоді» — факт. «Знову все зламали після деплою» — оцінка, яка гарантовано переведе розмову з дефекту на тон. Репорт описує поведінку продукту, а не якість чиєїсь роботи.
- Вплив замість гучності. Severity не «підвищують», щоб баг помітили. Якщо вважаєш дефект важливішим, ніж його оцінила команда, — принеси дані: скільки користувачів проходить цей сценарій, що саме вони втрачають, як часто відтворюється. Аргумент «це блокує головний сценарій покупки для всіх користувачів з промокодом» працює; аргумент «та це ж очевидно критично!» — ні.
- Питання замість звинувачень. «Не баг» від розробника — початок діалогу, а не стіна: «Дивись, в AC-3 написано ось так, а поводиться ось так — я щось пропускаю?» Часто зʼясовується, що обидва праві: код відповідає вимозі, а вимога — застаріла.
- Ескалація — через процес, не через голос. Якщо після обговорення згоди немає, рішення ухвалює той, хто володіє пріоритетами (продакт, лід) — і будь-яке його рішення, включно з wonʼt fix, фіксується в тикеті. Тестувальник відповідає за те, щоб ризик був видимий, а не за те, щоб кожен його баг був виправлений.
Атачі: логи, скриншоти, відео, HAR
Правильний атач скорочує шлях від «бачу симптом» до «бачу причину». У кожного типу своя робота:
- Скриншот — найшвидший доказ «що сталося». Стрілка чи рамка на місці проблеми обовʼязкова: без анотації читач шукатиме дефект по всьому екрану. Скриншот показує наслідок, але не шлях — тому він доповнює кроки, а не замінює їх.
- Відео — для дефектів, де важлива послідовність або таймінг: щось блимнуло, зникло, стрибнуло. Коротке, від передумови до фактичного результату.
- Логи — консоль браузера для фронтенд-помилок, серверні логи для 5xx. Головне в логах — часова мітка: вона дозволяє зіставити твій прояв бага з записами на бекенді. Якщо у відповідях API є ідентифікатор запиту (request id) — він у репорті безцінний.
- HAR (HTTP Archive) — JSON-файл з повним записом мережевої активності вкладки: усі запити з заголовками, тілами, статусами й таймінгами. Експортується з вкладки Network у DevTools (як саме — у главі про DevTools). Для багів рівня «фронт-бек» HAR — найсильніший атач: розробник бачить точний запит і точну відповідь, а не переказ. Важливе застереження: HAR містить cookie, токени й тіла запитів — перед прикріпленням у трекер (тим паче публічний) чутливі дані треба вичистити.
В автотестах ті самі артефакти збираються автоматично. Playwright уміє писати HAR і відео на рівні контексту, а його трейс (trace) — це скриншоти, дії, мережа й консоль в одному файлі, готовий атач до баг-репорту з CI:
const context = await browser.newContext({
recordHar: { path: 'artifacts/checkout.har' },
recordVideo: { dir: 'artifacts/videos/' },
});
Принцип відбору атачів простий: скриншот відповідає на «що видно», відео — на «як до цього дійшло», логи й HAR — на «що при цьому відбувалося під капотом». Для UI-косметики досить скриншота; для 500 на оплаті — HAR і лог з міткою часу.
Типові помилки
- Виглядає як економія часу — три проблеми в одному репорті, а насправді після фікса першої тикет закриють, а дві решти загубляться без сліду. Один дефект — один репорт.
- Виглядає як «баг важливий, тому ставлю високу severity», а насправді severity — про технічні наслідки, а «наскільки терміново» — це priority, і виставляє його той, хто керує чергою робіт. Змішування осей — найчастіший провал на співбесіді.
- Виглядає як очікуваний результат — «має працювати коректно», а насправді це порожнє поле: без посилання на вимогу, AC чи усталену поведінку читач не знає, що таке «коректно» для тебе.
- Виглядає як «не відтворилося двічі — закриваю», а насправді нестабільне відтворення — типовий почерк гонок і залежності від даних. Такий дефект не зник — він просто чекає на прод.
- Виглядає як «скриншот усе пояснює», а насправді скриншот без кроків і середовища — це загадка: видно наслідок, невідомо ні шляху, ні місця, ні версії.
- Виглядає як привід для reopen — «фікс зламав сусідню фічу», а насправді це новий дефект з новими кроками. Reopen — лише коли ті самі кроки знову дають той самий результат.
- Виглядає як чесність — «знову нічого не працює» у заголовку, а насправді емоційна оцінка замість фактів переводить обговорення з дефекту на стосунки. Продукт зламаний — репорт спокійний.
Підсумок
- Баг-репорт пишеться для людини, яка відтворюватиме дефект без тебе: конкретні кроки з даними, фактичний результат з текстом помилки, очікуваний результат із джерелом (вимога/AC), точне середовище й білд.
- Severity — технічний вплив, ставить тестувальник; priority — терміновість для бізнесу, ставить власник пріоритетів. Осі незалежні: реальні всі чотири комбінації, і на співбесіді чекають прикладів, а не означень.
- Життєвий цикл: New → тріаж → In Progress → Fixed → ретест → Closed, з бічними гілками rejected/duplicate/deferred/wonʼt fix. Закриває дефект тестувальник після ретесту, а не розробник після коміту.
- «Не відтворюється» — це брак умов у репорті, а не відсутність дефекту: звіряй середовище, дані, кеш і таймінги, фіксуй частоту спроб і збирай артефакти в момент прояву.
- Атачі відповідають на різні питання: скриншот — «що видно», відео — «як дійшло», логи й HAR — «що під капотом». HAR містить cookie й токени — чисти перед прикріпленням.
Що питають на співбесіді
- «Чим severity відрізняється від priority? Наведи приклад бага з високою severity і низьким priority — і навпаки.» Класика номер один. Інтервʼюер чекає не означень, а живих прикладів на обидві «перехресні» комбінації: саме вони показують, що ти розумієш незалежність осей.
- «Опиши життєвий цикл дефекту.» Дивляться, чи знаєш ти більше за happy path: гілки rejected/duplicate/deferred, хто переводить між статусами і чому закриває баг тестувальник після ретесту, а не розробник після фікса.
- «З чого складається хороший баг-репорт?» Сильна відповідь пояснює «навіщо» кожного поля (для кого воно і яке питання закриває), а не перелічує назви полів. Бонус — правило «один дефект — один репорт» і згадка про частоту відтворення.
- «Баг не відтворюється в розробника. Твої дії?» Перевіряють системність: перелік гіпотез (середовище, білд, дані, кеш, таймінги), збір артефактів з часовими мітками, чесна фіксація частоти — а не «попрошу подивитися ще раз» чи «закрию».
- «Розробник каже, що це не баг. Що робитимеш?» Питання про зрілість, а не про впертість: спершу вимоги, потім уточнення в автора рішення, далі — дані про вплив, і ескалація через власника пріоритетів. Червоний прапорець для інтервʼюера — «доводитиму, поки не визнають».
- «Що прикладеш до бага про помилку оплати?» Чекають розуміння, який артефакт яке питання закриває, і згадки про HAR для клієнт-серверних багів — з застереженням про чутливі дані в ньому.
Джерела
- ISTQB CTFL Syllabus v4.0 — глава покриває розділ 5.5 «Defect Management»: цілі управління дефектами і зміст defect report.
- Глосарій ISTQB — канонічні означення термінів: defect, defect report, defect management, severity, priority.
- Chrome DevTools: Network panel reference — робота з вкладкою Network, зокрема запис і експорт HAR.
- Playwright: Trace Viewer — трейс як готовий пакет артефактів (дії, скриншоти, мережа, консоль) для розбору фейлу й баг-репорту.
Що таке баг-репорт і навіщо він потрібен?
Баг-репорт (bug report, defect report) — письмовий опис знайденого дефекту, за яким інша людина зможе його відтворити, зрозуміти наслідки й виправити. Ключова властивість — асинхронність: репорт читатимуть без тебе, через тиждень, можливо людина, яка ніколи не бачила цієї фічі, тому кожне поле відповідає на конкретне питання читача, а не існує «для порядку в трекері». Розробник виправляє не той баг, який ти знайшов, а той, який ти описав. Погано описаний дефект живе довше і ходить по колу «не відтворюється — глянь ще раз», зʼїдаючи час двох людей.
З чого складається хороший баг-репорт?
Стабільний набір полів: заголовок, кроки відтворення, фактичний результат, очікуваний результат, середовище (оточення, білд, браузер, ОС), severity, priority і атачі. Сильна відповідь на співбесіді пояснює «навіщо» кожного поля, а не перелічує назви: заголовок — щоб знайти баг у трекері й зрозуміти суть одним рядком; кроки — «як мені побачити це в себе»; фактичний результат — що саме сталося з точним текстом помилки; очікуваний — що мало статися і звідки це відомо; середовище — де саме це відбулося. Бонусні бали дає правило «один дефект — один репорт» і згадка про частоту відтворення (наприклад, 5/5 чи 2/10).
Яким має бути заголовок баг-репорту?
Робоча формула: «що + де + за яких умов» — одним рядком. Порівняй «Не працює оплата» і «Checkout: 500 при оплаті замовлення із застосованим промокодом»: перший змушує відкривати репорт, щоб зрозуміти, про що він, другий сам по собі — діагноз. Заголовок — це те, за чим баг шукатимуть у трекері через пів року, тому в ньому мають бути ключові слова: місце, симптом, умова прояву.
Чому «має працювати коректно» — поганий очікуваний результат?
Бо це порожнє місце: розробник не знає, що для тебе «коректно». Сильний очікуваний результат посилається на джерело істини — вимогу, acceptance criteria, макет або усталену поведінку сусідніх фіч. Саме це посилання перетворює «мені здається, тут не так» на «продукт порушує ось цю домовленість» — і знімає суперечку ще до її початку. Без джерела репорт легко відлітає в rejected зі словами «works as designed».
Назви властивості хороших кроків відтворення.
Їх три. Відтворюваність з нуля: кроки починаються зі стану, який читач може створити сам, — передумови явні (який користувач, які дані, який стан системи), а не «на моєму акаунті». Конкретні дані: не «ввести довге імʼя», а «ввести імʼя з 256 символів», не «застосувати промокод», а «застосувати SUMMER10» — дефект часто живе саме в даних. Мінімальність: перед заведенням сценарій звужують, прибираючи кроки, без яких дефект однаково відтворюється; мінімальний сценарій не лише швидше перевіряти — він сам підказує причину, бо все, що лишилося, і є умовами прояву.
Чим кроки відтворення в баг-репорті відрізняються від кроків у тест-кейсі?
Тест-кейс описує заплановану перевірку, репорт — фактичний шлях до вже знайденого дефекту. Тому кроки репорту завжди конкретніші й вужчі: це не сценарій «перевірити оплату», а точний маршрут до однієї ями, з конкретними даними й умовами, за яких дефект проявляється. Кейс пишеться до виконання і розрахований на повторне використання, репорт фіксує одну конкретну знахідку.
Чим severity відрізняється від priority?
Severity (серйозність) — наскільки тяжкі технічні наслідки дефекту для системи й користувача: краш, втрата даних, непрацююча функція, косметика. Її зазвичай виставляє тестувальник, бо саме він бачив наслідки. Priority (пріоритет) — наскільки терміново дефект треба виправити з погляду бізнесу; його виставляє той, хто відповідає за продукт і чергу робіт: продакт-менеджер або лід, часто на тріажі. Осі незалежні, тому реальні всі чотири комбінації — і на співбесіді чекають живих прикладів «перехресних» варіантів, а не завчених означень.
Наведи приклад бага з високою severity і низьким priority — і навпаки.
Висока severity + низький priority: краш при експорті річного звіту, який бухгалтерія формує раз на рік, а до звітного періоду ще пів року — технічно тяжко (краш), але терміновості немає. Низька severity + високий priority: одрук у назві компанії на головній сторінці за день до запуску рекламної кампанії — технічно дрібниця, репутаційно ні. Ключ до побудови таких прикладів: severity дивиться на тяжкість наслідку, priority — на те, скільки людей і грошей це зачіпає саме зараз.
Опиши життєвий цикл дефекту.
Скелет однаковий у всіх трекерах: New → тріаж → In Progress → Fixed → ретест → Closed. З New є бічні гілки: Rejected (не дефект), Duplicate (уже заведено), Deferred (фікс відкладено). Якщо ретест не пройшов — Fixed переходить у Reopened і далі знову In Progress. Сильна відповідь показує знання більше за happy path: хто переводить між статусами (тріаж вирішує долю нового бага, розробник переводить у Fixed, тестувальник закриває після ретесту) і що конкретні назви статусів залежать від трекера й процесу команди.
Розробник перевів баг у Fixed. Це кінець роботи з дефектом?
Ні — Fixed означає лише, що виправлення потрапило в білд. Закриває баг тестувальник після ретесту на тому середовищі, куди фікс доїхав: треба пройти ті самі кроки й переконатися, що фактичний результат став очікуваним. Якщо ретест не пройшов — баг перевідкривається. Це принциповий розподіл відповідальності: розробник заявляє «виправив», підтверджує це той, хто вміє відтворити дефект.
Фікс виправив баг, але зламав сусідню фічу. Reopen чи новий репорт?
Новий репорт. Reopened — лише коли не виправлено те саме: ті самі кроки знову дають той самий фактичний результат. У поламаної сусідньої фічі інші кроки, інша причина й, можливо, інший виконавець — це новий дефект з власною історією. Змішування в одному тикеті двох різних проблем ламає трасування: незрозуміло, що саме виправлялося і що ретестити.
Що таке тріаж?
Тріаж (triage) — регулярний розбір свіжих багів, де вирішується їхня доля: чи це взагалі дефект, чи не дублікат, який пріоритет, кому призначити. Саме на тріажі репорт «продає» себе — рішення ухвалюють за описом, часто без автора поруч. Тому якість опису безпосередньо впливає на швидкість фікса: незрозумілий репорт у кращому разі повернеться з питаннями, у гіршому — отримає занижений пріоритет або rejected.
Баг не відтворюється в розробника. Твої дії?
Систематично шукати умову, якої бракує в репорті, — «cannot reproduce» означає, що не всі умови прояву зафіксовані, а не що дефекту немає. Перелік гіпотез: середовище (інше оточення, інший білд, інша конфігурація — перше, що звіряють), дані та стан (у тебе користувач з історією замовлень, у розробника чистий акаунт), кеш (браузер чи CDN віддає стару версію фронтенду — у вас буквально різні застосунки), таймінги й гонки (повільна мережа, швидкі кліки, паралельні дії), платформа (браузер, версія, ОС, розширення). Практично: зафіксувати частоту спроб («відтворилося 2 з 10»), зібрати артефакти в момент прояву — скриншот, HAR, логи з часовою міткою, щоб бекенд-лог можна було зіставити з моментом помилки, — і додати все в репорт. Червоний прапорець на співбесіді — «попрошу подивитися ще раз» або «закрию».
Дефект впіймано один раз і більше не відтворюється. Заводити репорт?
Так — з усіма доказами й чесною позначкою про частоту. Один раз побачений 500 з тілом відповіді в атачі — це вже зачіпка для розробника в серверних логах, навіть без стабільного відтворення. Нестабільне відтворення — типовий почерк гонок і залежності від даних: такий дефект не зник, він чекає на прод, де користувачів і паралельності більше, ніж на стенді. Мовчки закрити «бо не відтворилося двічі» — означає викинути сигнал, який потім вистрелить у користувачів.
Що означають фінали Rejected, Duplicate, Wonʼt fix і Deferred?
Rejected (not a bug) — поведінка відповідає вимогам або «дефект» виявився нерозумінням фічі; перший крок при незгоді — перечитати вимогу. Duplicate — такий дефект уже заведено; профілактика — пошук у трекері за ключовими словами й текстом помилки перед заведенням, а якщо дублікат стався — тикети лінкують, бо два незалежні прояви — корисна інформація про частоту. Wonʼt fix — дефект визнано, але виправляти не будуть: вартість фікса вища за шкоду, фіча доживає останні місяці, кейс екзотичний. Deferred — виправлять, але не в цьому релізі. Усе це нормальні, а не «поразкові» фінали: не кожен баг завершується фіксом, і задача тестувальника — щоб рішення ухвалювалося з повною картиною наслідків і лишилося зафіксованим письмово.
Розробник каже, що це не баг. Що робитимеш?
Спершу перечитати вимогу — можливо, права саме вона, і це нерозуміння фічі з мого боку. Далі — уточнення без звинувачень: «в AC-3 написано ось так, а поводиться ось так — я щось пропускаю?»; часто зʼясовується, що обидва праві — код відповідає вимозі, а вимога застаріла, і це вже знахідка про дірку у вимогах. Якщо вважаю дефект важливішим, ніж його оцінили, — приношу дані про вплив: скільки користувачів проходить сценарій, що вони втрачають, як часто відтворюється. Якщо згоди немає — ескалація через процес: рішення ухвалює власник пріоритетів, і будь-яке його рішення, включно з wonʼt fix, фіксується в тикеті. Тестувальник відповідає за видимість ризику, а не за те, щоб кожен його баг був виправлений; червоний прапорець для інтервʼюера — «доводитиму, поки не визнають».
Які атачі прикладеш до бага про помилку оплати і чому?
Принцип відбору: кожен атач відповідає на своє питання. Скриншот — «що видно»: найшвидший доказ наслідку, обовʼязково з анотацією (стрілка чи рамка), але він не показує шлях, тому доповнює кроки, а не замінює їх. Відео — «як до цього дійшло»: для дефектів, де важлива послідовність або таймінг. Логи — «що під капотом»: консоль браузера для фронтенд-помилок, серверні логи для 5xx, і головне в них — часова мітка, щоб зіставити прояв з записами бекенда; request id з відповіді API — безцінний. Для помилки оплати (клієнт-серверний баг) найсильніший атач — HAR з точним запитом і відповіддю плюс лог з міткою часу; для UI-косметики вистачило б скриншота.
Що таке HAR і про яке застереження треба памʼятати?
HAR (HTTP Archive) — JSON-файл з повним записом мережевої активності вкладки: усі запити з заголовками, тілами, статусами й таймінгами; експортується з вкладки Network у DevTools. Для багів рівня «фронт-бек» це найсильніший атач: розробник бачить точний запит і точну відповідь, а не переказ. Застереження: HAR містить cookie, токени й тіла запитів, тому перед прикріпленням у трекер — тим паче публічний — чутливі дані треба вичистити. В автотестах ті самі артефакти збираються автоматично: Playwright уміє писати HAR і відео на рівні контексту, а його трейс — скриншоти, дії, мережа й консоль в одному файлі — готовий атач до баг-репорту з CI.
Три кейси з робочого життя навколо одного вміння — донести дефект так, щоб його виправили: переписування слабкого репорту в сильний (було → стало), розкладання чотирьох багів по осях severity/priority на тріажі та розслідування «у мене працює» зі збором артефактів з автотесту. Скрізь — що саме змінюється і чому.
Кейс 1. Було → стало: переписуємо слабкий репорт
Репорт, який у такому вигляді приходить на тріаж, гарантує пінг-понг «не відтворюється — глянь ще раз»:
Заголовок: Не працює пошук
Кроки:
1. Зайти на сайт
2. Щось пошукати
Фактичний результат: помилка
Очікуваний результат: має працювати коректно
Той самий дефект після звуження сценарію і збору фактів:
Заголовок: Пошук: 500 при запиті з апострофом (O'Brien)
Середовище: stage, білд 2.14.3, Chrome 138, macOS
Severity: Major Priority: High Частота: 5/5
Кроки:
1. Відкрити /search
2. Ввести O'Brien у поле пошуку
3. Натиснути Enter
Фактичний результат: сторінка помилки; GET /api/search?q=O'Brien
повертає 500, тіло відповіді: {"error": "unterminated string literal"}
Очікуваний результат: список результатів або порожній стан
«Нічого не знайдено» (AC-2 у сторі SRCH-88)
Атачі: скриншот з анотацією, HAR, лог консолі з часовою міткою
Що змінилося і чому:
- Заголовок став діагнозом за формулою «що + де + за яких умов»: через пів року цей баг знайдеться в трекері за словами «пошук», «500» чи «апостроф» — і зрозуміється без відкривання.
- Дані конкретні, бо дефект живе саме в даних. «Щось пошукати» ніколи не покаже проблему: 500 дає лише запит з апострофом. Саме тому в кроках
O'Brien, а не «ввести імʼя». - Сценарій мінімальний. Логін, навігація по каталогу й інші кроки прибрані — 500 ловиться прямо на
/search. Усе, що лишилося в кроках, і є умовами прояву: це вже пів-діагнозу для розробника. - Фактичний результат цитує помилку дослівно — статус, ендпоінт, тіло відповіді. За цим текстом розробник знайде місце в коді швидше, ніж за переказом «помилка».
- Очікуваний результат отримав джерело істини — посилання на acceptance criteria. Без нього репорт легко відлітає в rejected зі словами «works as designed».
Кейс 2. Тріаж: розкладаємо чотири баги по осях
Чотири свіжі баги інтернет-магазину прийшли на тріаж. Severity вже виставив тестувальник — за тяжкістю технічних наслідків; priority команда визначає за тим, скільки людей і грошей це зачіпає зараз:
| Дефект | Severity | Priority | Логіка рішення |
|---|---|---|---|
| 500 при оплаті замовлення з промокодом | Critical | High | Checkout лежить, компанія втрачає гроші щохвилини — тяжко і терміново |
| Краш при експорті річного звіту | Critical | Low | Наслідок тяжкий (краш), але звіт формують раз на рік, а до звітного періоду пів року |
| Одрук у назві компанії на головній | Minor | High | Технічно косметика, але завтра стартує рекламна кампанія — репутаційна ціна висока |
| Іконка зʼїхала на два пікселі у футері «Умов використання» | Trivial | Low | Ні технічної тяжкості, ні терміновості |
Що дивитися і чому:
- Осі незалежні — на столі всі чотири комбінації. Перехресні варіанти (рядки 2 і 3) — улюблені на співбесідах, бо показують, що ти розумієш різницю, а не завчив означення.
- Ролі не змішуються. Severity виставив тестувальник до тріажу, priority ухвалює той, хто керує чергою робіт. Тестувальник може аргументувати, але не «продавлювати» терміновість через завищену severity.
- Аргумент — вплив, не гучність. «Це блокує головний сценарій покупки для всіх користувачів з промокодом» — працює; «та це ж очевидно критично!» — ні. Якщо не згоден з оцінкою — принось дані: скільки користувачів проходить сценарій, як часто відтворюється.
- Рішення фіксується в тикеті. Навіть якщо краш звіту свідомо відклали — письмовий слід перетворює майбутнє «чому ніхто не знав» на «ми знали і свідомо відклали».
Кейс 3. «У мене працює»: розслідування + артефакти з автотесту
Баг з оплатою відтворюється в тебе 2 рази з 10, у розробника — жодного. «Cannot reproduce» — не вирок: дефект нікуди не подівся, просто не всі умови прояву потрапили в репорт. Проходимо гіпотези по черзі:
- Середовище. Звіряємо рядок «Середовище» з репорту: ти на stage з білдом 2.14.3, розробник — локально на гілці з незлитим фіксом? Уже не той самий застосунок.
- Дані та стан. У тебе користувач із застосованим промокодом та історією замовлень, у розробника — чистий акаунт. Стан бази часто і є «секретною» умовою відтворення.
- Кеш. Браузер або CDN віддає розробнику стару версію фронтенду — ви буквально дивитеся на різні застосунки.
- Таймінги й гонки. «2 з 10» — типовий почерк гонки: дефект проявляється на повільній мережі, при швидких кліках чи паралельних діях. Саме такі баги найболючіше стріляють у проді, де паралельності більше, ніж на стенді.
Якщо сценарій покритий автотестом, докази збираються самі — досить налаштувати збір артефактів для впалих прогонів:
// playwright.config.ts: артефакти лишаються тільки для впалих тестів
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
trace: 'retain-on-failure', // дії, скриншоти, мережа й консоль в одному файлі
video: 'retain-on-failure',
screenshot: 'only-on-failure',
},
});
А для конкретного розслідування HAR і відео пишуться на рівні контексту:
const context = await browser.newContext({
recordHar: { path: 'artifacts/checkout.har' },
recordVideo: { dir: 'artifacts/videos/' },
});
Що дивитися і чому:
- Частота — чесно в репорт: «відтворилося 2 з 10». Це не слабкість репорту, а критична інформація: вона попереджає розробника, що з першої спроби може не вийти, і сама по собі натякає на гонку чи залежність від даних.
- Часова мітка й request id — місток до бекенда. Лог з міткою часу дозволяє зіставити твій прояв бага з серверними записами; ідентифікатор запиту з відповіді API робить це зіставлення точним.
- Трейс Playwright — готовий атач з CI. Один файл містить дії, скриншоти, мережу й консоль — усе, що інакше довелося б збирати руками в момент прояву.
- HAR чистити перед прикріпленням. У ньому cookie, токени й тіла запитів — у трекер (тим паче публічний) такий файл у сирому вигляді не кладуть.
- Один прояв — теж репорт. Якщо 500 впіймано лише раз, але тіло відповіді є в атачі — це вже зачіпка для пошуку в серверних логах. Заводь репорт з усіма доказами й позначкою про частоту, а не чекай стабільного відтворення.
Структура баг-репорту
- Можу пояснити «навіщо» кожного поля репорту — на яке питання читача воно відповідає, — а не просто перелічити назви полів.
- Знаю формулу заголовка «що + де + за яких умов» і чому «Не працює оплата» змушує відкривати тикет, а «Checkout: 500 при оплаті з промокодом» — уже діагноз.
- Розумію, чому очікуваний результат мусить посилатися на джерело істини (вимога, acceptance criteria, макет, усталена поведінка), а «має працювати коректно» — порожнє поле.
- Знаю правило «один дефект — один репорт»: після фікса першої з трьох проблем тикет закриють, а дві решти загубляться.
Кроки відтворення
- Знаю три властивості хороших кроків: відтворюваність з нуля (явні передумови, а не «на моєму акаунті»), конкретні дані, мінімальність.
- Можу пояснити, чому мінімальний сценарій сам підказує причину: все, що в ньому лишилося, і є умовами прояву дефекту.
- Розумію різницю кроків у баг-репорті та тест-кейсі: кейс — запланована перевірка, репорт — фактичний маршрут до однієї конкретної ями.
Severity vs priority
- Знаю різницю severity vs priority: тяжкість технічних наслідків проти терміновості для бізнесу — і що це дві незалежні осі; шкала severity: critical / major / minor / trivial плюс blocker, який блокує саме тестування.
- Памʼятаю, хто що виставляє: severity — тестувальник (він бачив наслідки), priority — власник черги робіт (продакт-менеджер або лід), часто на тріажі.
- Можу навести живий приклад на обидві «перехресні» комбінації: краш експорту річного звіту за пів року до звітного періоду; одрук у назві компанії на головній за день до рекламної кампанії.
Життєвий цикл дефекту
- Можу описати скелет циклу: New → тріаж → In Progress → Fixed → ретест → Closed, з бічними гілками Rejected / Duplicate / Deferred.
- Розумію, що Fixed означає лише «виправлення потрапило в білд»: закриває баг тестувальник після ретесту на середовищі, куди фікс доїхав.
- Знаю, коли Reopened, а коли новий репорт: reopen — лише якщо ті самі кроки знову дають той самий результат; «фікс зламав сусідню фічу» — новий дефект.
- Розумію фінали без фікса — rejected (works as designed), duplicate, wonʼt fix, deferred — і чому це нормальні бізнес-рішення, які мають лишитися зафіксованими письмово.
Баг не відтворюється
- Памʼятаю пʼять гіпотез різниці «у мене відтворюється — у нього ні»: середовище/білд, дані та стан, кеш, таймінги й гонки, платформа.
- Знаю, що робити з дефектом, впійманим один раз: репорт з усіма доказами й чесною частотою («відтворилося 2 з 10»), а не мовчазне закриття.
Комунікація навколо бага
- Тримаю в репорті факти замість оцінок: «POST /api/orders повертає 500 при застосованому промокоді», а не «знову все зламали після деплою».
- Знаю, як аргументувати важливість бага: дані про вплив (скільки користувачів, що втрачають, як часто), а не завищена severity «щоб помітили»; якщо згоди немає — ескалація через власника пріоритетів, рішення фіксується в тикеті.
Атачі
- Можу пояснити, яке питання закриває кожен атач: скриншот — «що видно», відео — «як до цього дійшло», логи й HAR — «що під капотом»; часова мітка й request id зіставляють прояв бага з бекенд-логами.
- Знаю, що HAR — це повний запис мережевої активності вкладки з cookie, токенами й тілами запитів, тому перед прикріпленням у трекер його треба чистити від чутливих даних.
Що описує severity дефекту?
Питання
Формула хорошого заголовка баг-репорту?