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

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

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

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

ШагСуть
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 bisect — 1141.

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

  • 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 на глаз".

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