Плавающие баги и как их искать

Плавающие баги и как их искать

Заметки о QA
Время чтения ~5 минут
Очень много из текста основано на докладе Анны Васильевой (ныне Куреновой) "Поиск плавающих багов"
Ссылка на ее tg-канал

Что такое плавающие баги

Вот так я представляю плавающие баги

Бывает, что поведение системы иногда не соответствует ожидаемому результату: то программа падает, то нет. И вроде бы ты повторяешь те же действия, которые делал только что, но проблема повторяется не постоянно. Это и есть плавающие баги.

Проблема плавающих багов заключается в сложности обнаружения их причины. Баг ты словил, а написать шаги воспроизведения не можешь. И что в таком случае делать? Попробовать опереться на типичные причины, чтобы понять природу падения.

Типичные причины возникновения плавающих багов

Типичные причины плавающих багов
  • Состояние гонки (Race Condition): ситуация, когда два или более потока (или процесса) пытаются одновременно получить доступ к общему ресурсу.
    * эта причина меня особенно заинтересовала, потому что ее тяжело повторить без осознанного действия
  • Редкие тестовые данные: данные, которые тяжело подобрать.
  • Недостаток наблюдения: неочевидные ошибки, которые быстро появляются и быстро пропадают.
  • Инфраструктурные проблемы: закончилась память, заблокировалась база данных, не обновился сертификат и прочие типичные проблемы инфраструктуры, которые можно либо словить из-за случайности, либо воспроизводить с помощью мок-северов.

Состояние гонки (Race condition)

Race condition - состояние гонки в системе: ошибка проектирования многопоточной системы или приложения, при которой работа системы или приложения зависит от того, в каком порядке выполняются части кода.

В этом случае дефект зависит от времени и последовательности действий:

  • насколько быстро/медленно мы произвели действие
  • как конкретно мы это сделали (в какой очередности производились действия)

Часто дефекты появляются на границе работы нескольких потоков: например, один поток положил сущность в базу данных, а второй при попытке сделать то же самое упал с ошибкой из-за отсутствия уникальности. Тут важно одновременное действие потоков: оба практически в один и тот же момент пытались сделать одно и то же. И обработки такого одновременно действия двумя потоками в системе не было, что и привело к ошибке.

Последствия race condition

  • неправильная работа функционала
  • утечка памяти, что может привести сервер к зависанию или перезагрузки
  • временные блокировки ресурса, а значит замедление работы сервера
  • порча данных
  • образование уязвимостей
  • ошибки сегментирования

Как искать плавающие баги

  • фаззинг: генерация разных тестовых данных с помощью специальных программ, что позволит решить проблему редких тестовых данных
  • поиск ошибок в логах: отслеживание инфраструктурных проблем и их причин в системах логирования, что позволит найти неожиданные ошибки или странную перезагрузку сервера
  • отправка большого количества запросов: оценка того, насколько сервер выдерживает разную нагрузку и не выкидывает странные ошибки
  • отправка запросов параллельно: отображение корректности работы нескольких потоков с одними и теми же объектами

Почему стоит искать плавающие баги и всегда ли стоит искать их до конца?

Плавающие баги точно стоит искать: они могут выявить критические проблемы, которые могут привести к потери данных или невозможности работы какого-то пользователя.

Иногда причину плавающих багов очень сложно и долго локализовывать и тогда возникает вопрос: как понять, что это критический баг, а не наша попытка зацепиться за нерешаемую проблему и погрязнуть в ней?

Тут точного ответа нет, все очень индивидуально и зависит от бага, который вы ловите: иногда ситуация не может повториться на продакшн среде из-за увеличенного количества памяти, иногда баг можно получить "нереальной" последовательностью действий. Поэтому нужно оценивать риски для бизнеса появившейся проблемы и действовать согласно ситуации, привлекая других участников команды для ускорения поиска.

Личная история пропуска плавающего бага

Иногда одни и те же плавающие баги появляются настолько часто, что мы перестаем их искать: глаз замыливается и начинает воспринимать проблему как норму.

У меня в работе был случай, когда при параллельном запуске автотестов начиналось падение тех тестов, которые отдельно позитивно отрабатывают. Обсудив с разработчиком, который убедил меня в проблеме автотестов, я продолжила перезапускать тесты и убеждаться, что при последовательность запуске все отлично. А значит бага нет (ха-ха).

Все было хорошо до момента, когда не обнаружился баг на продакшене: события терялись при большом количестве документов. И мои тесты отлавливали именно это! Вот так я и пропустила баг, который проявлялся при большом количестве запросов к нескольким потокам...

Так что не повторяйте моих ошибок 🥸


Пост telegram-канала "Заметки о QA"

Report Page