Перейти к основному содержимому

Как искать баг

Разработчику

Цикл поиска бага

ШагСуть
ReproduceСтабильно воспроизвести
IsolateСузить место и условия
HypothesisОдна проверяемая догадка
VerifyОтладчик, лог, эксперимент
FixМинимальное исправление
TestРегрессионный тест + ручная проверка

Подробно про отладчик — Отладка. После фикса — Тестирование для разработчика.


Шаблон баг-репорта

Заполните до копания в код:

## Шаги
1. Открыть /tasks
2. Нажать "Добавить"
3. Ввести пустой заголовок
4. Нажать "Сохранить"

## Ожидание
Сообщение "заголовок обязателен"

## Факт
Белый экран, в Console TypeError

## Окружение
- OS: Windows 11
- Browser: Chrome 122
- Версия: commit abc123, dev

## Логи / скрин
[вставить stack trace]

Хороший отчёт экономит часам команде — 7.05 QA.


1. Воспроизведение — разбор по типам багов

UI не обновился

  • Hard refresh (Ctrl+Shift+R);
  • DevTools → Network — ушёл запрос? статус? — 1116;
  • ответ JSON — те ли поля?

500 на сервере

  • stack trace в логах сервера;
  • воспроизвести через curl с тем же body — 1133;
  • последний деплой / merge в main.

"Иногда работает"

  • время суток, timezone;
  • конкурентные запросы (race);
  • кэш CDN или браузера;
  • git bisect1141.

Регресс после релиза

  • diff релиза;
  • feature flag включился?
  • миграция БД применилась?

2. Изоляция — бинарный поиск подробно

Пример: закомментируйте вызов sendEmail() — баг ушёл? Проблема в почте или mock. Отключите валидацию — баг ушёл? Смотрите validator.

Минимальный repro — smallest input, smallest code:

# вместо 1000 строк — 10
def test_empty_title():
assert validate_title("") == False # падает

3. Гипотеза — журнал экспериментов

Ведите блокнот (или комментарий в issue):

#ГипотезаЭкспериментРезультат
1null userIdbreakpoint на line 42userId = null ✓
2CORScurl без браузера200 OK — отпадает
3неверный Content-Typeпроверить headerapplication/text ✗

Одна строка — один эксперимент. Не смешивайте три правки в одном commit.


4. Проверка — уровни логирования

УровеньКогда
DEBUGзначения переменных, dev
INFO"запрос обработан", prod
WARNподозрительно, но работает
ERRORисключение, stack trace
import logging
log = logging.getLogger(__name__)
log.debug("user_id=%s", user_id)

Prod — без print; структурированные логи — 1111 логирование.

Breakpoint — что смотреть

  • значения аргументов функции;
  • условие if — true или false;
  • стек вызовов (кто вызвал);

Отладка ./111.md.


5. Fix — антипаттерны

ПлохоЛучше
try/except: passобработать причину
if user_id == 5 хардкодисправить источник id
копипаста fix в 5 файловодна функция + тест
@ts-ignore / # noqaпонять тип или валидацию

1115 типичные ошибки.


6. Test — регрессионный тест

def test_empty_title_rejected(): # GitHub issue #42
response = client.post("/tasks", json={"title": ""})
assert response.status_code == 400
assert "title" in response.json()["error"]

Имя теста ссылается на issue — через год понятно, какой баг не должен вернуться — 1117.


Heisenbug и race condition

Heisenbug — пропадает, когда смотрите (breakpoint, лог). Race condition — два потока/запроса меняют данные одновременно.

Признаки:

  • баг только под нагрузкой;
  • "не воспроизводится локально";
  • разный порядок логов.

Инструменты: stress-тест, -race в Go, лог с correlation id — 112 производительность.


Prod и local — чем отличаются

ФакторLocalProd
Данныемало, тестовыемиллионы записей
Конфиг.env devсекреты в vault
HTTPSчасто HTTPTLS, другие cookie
КэшвыключенRedis, CDN

Баг "только на prod" — проверьте данные (null, дубликаты), конфиг, права — 1112 .env.


Минимальный repro для issue в библиотеке

  1. Новый пустой проект.
  2. Одна зависимость — проблемная версия.
  3. 10–20 строк кода, воспроизводящие баг.
  4. Версии OS, runtime, библиотеки в описании.

Без repro upstream часто закрывает issue.


1. Воспроизведение (Reproduce)

Без воспроизведения вы не знаете, исправили ли проблему.

Зафиксируйте:

  • шаги (1, 2, 3…);
  • окружение (ОС, браузер, версия, dev/prod);
  • входные данные (файл, JSON, пользователь);
  • ожидание — что должно произойти;
  • факт — что произошло на самом деле;
  • stack trace (трассировка стека — цепочка вызовов до ошибки), скрин, лог (время, correlation id).

Если баг "плавает" — ищите общее (нагрузка, час, конкретный аккаунт). git bisect находит коммит-виновник — типовые ситуации Git.


2. Изоляция (Isolate)

Сужайте область:

ВопросДействие
Фронт или бэк?DevTools Network — ушёл запрос? какой статус? — 1116
Один модуль?Отключите половину кода / закомментируйте ветку (временно)
Данные?Минимальный пример: один пользователь, одна запись
Недавнее изменение?git log, diff последнего деплоя

Бинарный поиск: отключите половину системы — баг остался? повторите на половине половины. Чтение кода по цепочке — Как читать чужой код.


3. Гипотеза (Hypothesis)

Одна формулировка за раз:

  • "Падает, потому что userId null после десериализации JSON".
  • "404, потому что роут не зарегистрирован в dev-сервере".
  • "CORS, потому что API не отдаёт заголовок для origin фронта" — CORS.

Не меняйте пять вещей сразу — не поймёте, что помогло.


4. Проверка (Verify)

ИнструментКогда
Breakpoint (точка останова)Значения переменных в момент сбоя — Отладка
ЛогProd, где breakpoint нельзя — Логирование
Console / NetworkВеб — DevTools
curlAPI без UI — 1133
printБыстрый черновик; для сложного случая замените на лог или отладчик

Подтвердили гипотезу — фикс. Опровергли — новая гипотеза, не копайте дальше в ложном направлении.


5. Исправление (Fix)

  • Минимальный diff: fix отдельно, рефакторинг — другим commit/PR.
  • Устраните причину, а не только симптом (если данные неверны, одного try/catch мало).
  • Проверьте соседние места с той же ошибкой (копипаста).

Типовые ловушки — 1115 (N+1, SQLi, CORS, секреты в коде).


6. Тест и регрессия (Test)

  1. Тест, который падал до фикса и зелёный после — 1117.
  2. Ручной сценарий из шага Reproduce — снова OK.
  3. Если баг из prod — мониторинг/алерт не должен повториться.

Частые ловушки мышления

ЛовушкаЧто делать вместо
"Сразу перепишу"Сначала понять причину
Print вездеТочечный лог или breakpoint
"Виню кэш браузера"Hard refresh, потом Network
Копировать fix из Stack OverflowПроверить версию стека и контекст
ИИ "исправил"Запустить тесты и repro руками

Когда эскалировать

  • Нет доступа к prod-логам — DevOps / on-call.
  • Баг в сторонней библиотеке — минимальный repro, issue upstream.
  • Данные повреждены — DBA + бэкап, не "починить SQL на глаз".

Связанные материалы