Баг — это дефект в коде или в поведении программы, из-за которого она работает не так, как ожидалось: выдает неверный результат, зависает, падает или делает не то, что задумано. Слово произошло от английского bug («жук») и давно стало рабочим термином, а не только сленгом. Ниже разберу, какие бывают виды ошибок в программировании, чем баг отличается от дефекта и сбоя, как ошибки классифицируют по серьезности и приоритету и как их ловят на практике. Примеры кода даны тройкой: неверный вариант, его результат и исправление.
Содержание
Баг, дефект, ошибка, сбой — в чем разница
В обычной речи эти слова смешивают, но в тестировании у них разный смысл. Проще всего представить их как цепочку причин и следствий.
- Ошибка (error, mistake) — действие человека, приведшее к неверному результату. Например, разработчик перепутал знак в условии или неправильно понял требование.
- Дефект (defect) — изъян в коде или в продукте, который появился из-за ошибки. Баг — это разговорный синоним дефекта.
- Сбой (отказ, failure) — проявление дефекта во время работы: программа повела себя не так, как ожидал пользователь.
Цепочка выглядит так: ошибка человека -> дефект (баг) в коде -> сбой при выполнении. Важный нюанс: не каждый дефект приводит к сбою. Баг может годами лежать в редко используемой ветке кода и не проявляться, пока не сложатся нужные условия. Поэтому «нашли баг» и «случился сбой» — не одно и то же.
Как классифицируют ошибки: основные виды
Единой обязательной классификации нет, но по моменту и причине проявления удобно выделить пять основных видов ошибок в программировании. Первые два видны еще до запуска, остальные — только когда программа уже работает.
Синтаксические
Нарушение правил языка: пропущенный символ, лишняя скобка, опечатка в ключевом слове. Такие ошибки самые безобидные, потому что их находит сам компилятор или интерпретатор еще до выполнения кода и обычно точно указывает строку. Часто их подсвечивает редактор кода и линтер прямо во время набора.
Ошибки компиляции
Возникают на этапе сборки программы в машинный код или байт-код. Причина не всегда в синтаксисе: сюда же попадают несоответствие типов, обращение к необъявленной переменной, несовместимые версии зависимостей. Пока такие ошибки не устранены, готового исполняемого файла не будет. В интерпретируемых языках (например, Python) отдельного этапа компиляции в привычном смысле нет, и часть таких проблем всплывает уже во время выполнения.
Логические
Синтаксис верный, программа запускается и не падает, но результат неправильный. Это самый коварный вид: компилятор молчит, а ошибка спрятана в самой логике — перепутано условие, неверная формула, сдвиг на единицу в границах цикла. Ловятся такие ошибки тестами, ревью кода и отладчиком — то есть сравнением фактического результата с ожидаемым.
Ошибки времени выполнения (runtime)
Проявляются во время работы программы при определенных данных или условиях, даже если синтаксис и логика в целом верны. Классические примеры: деление на ноль, обращение к несуществующему файлу, выход за границы массива, нехватка памяти. Код может месяцами работать нормально и упасть только на редком сочетании входных данных.
Интеграционные
Возникают на стыке модулей, сервисов или систем, когда каждая часть по отдельности работает, а вместе — нет. Причины: несовпадение форматов данных, изменившийся ответ внешнего API, разные предположения о поведении соседнего компонента. Такие ошибки не видны при проверке одного модуля и требуют интеграционных тестов.
Ресурсные ошибки (переполнение буфера, утечки памяти) и арифметические (переполнение типа, потеря точности) на практике чаще относят к частным случаям runtime-ошибок.
Серьезность (severity) и приоритет (priority)
Когда баг найден, его оценивают по двум независимым шкалам. Их часто путают, хотя это разные вещи.
- Severity (серьезность) — насколько сильно дефект влияет на работу продукта. Это техническая, объективная характеристика. Типичные уровни: blocker (работать дальше нельзя), critical, major, minor, trivial.
- Priority (приоритет) — насколько срочно баг нужно чинить. Это уже решение команды с учетом бизнеса и планов релиза: high, medium, low.
Ключевой момент — шкалы не связаны жестко. Падение приложения в функции, которой пользуется один клиент раз в год, может иметь высокую severity, но низкий priority. И наоборот: опечатка в названии компании на главной странице технически тривиальна, но приоритет ее исправления высокий, потому что ее видят все. Именно поэтому в баг-трекере обычно два поля, а не одно.
Жизненный цикл бага
Найденный баг не исправляется мгновенно, а проходит через несколько состояний в баг-трекере. Типичный путь такой:
- New — баг заведен тестировщиком, но еще не разобран.
- Assigned / In progress — назначен на разработчика, идет работа.
- Fixed — разработчик считает, что исправил, и передал на проверку.
- Retest / Verified — тестировщик перепроверяет исправление.
- Closed — баг подтвержденно исправлен, либо Reopened, если проблема осталась.
Есть и «тупиковые» статусы: Rejected (не признан багом), Duplicate (дубликат уже заведенного), Deferred (отложен на будущее). Понимание этого цикла помогает разработчику и тестировщику говорить на одном языке.
Примеры кода: неверно, результат, исправление
Разберу три частых случая на Python. Для каждого — неверный код, его фактический результат и исправленный вариант.
1. Синтаксическая ошибка
Неверно (пропущено двоеточие после условия):
x = 10
if x > 5
print("больше пяти")
Результат — код даже не запустится:
File "example.py", line 2
if x > 5
^
SyntaxError: expected ':'
Исправление:
x = 10
if x > 5:
print("больше пяти") # больше пяти
2. Логическая ошибка
Неверно — хотели среднее, но взяли целочисленное деление, и дробная часть потерялась:
total = 7
people = 2
share = total // people
print(share) # 3 (а ожидали 3.5)
Программа не падает и синтаксически верна — именно поэтому логические ошибки так трудно заметить. Признак выбора здесь простой: // берут, когда нужно целое число (например, количество полных коробок), а / — когда важна дробная часть.
Исправление:
total = 7
people = 2
share = total / people
print(share) # 3.5
3. Ошибка времени выполнения (runtime)
Неверно — функция падает на пустом списке из-за деления на ноль:
def average(nums):
return sum(nums) / len(nums)
print(average([])) # ZeroDivisionError: division by zero
Синтаксис и логика для непустого списка верны, но на граничном значении (пустой ввод) программа аварийно завершается. Исправление — проверить условие заранее:
def average(nums):
if not nums:
return 0
return sum(nums) / len(nums)
print(average([])) # 0
Таблица: где искать каждый вид ошибки
| Тип ошибки | Когда проявляется | Как ловят |
|---|---|---|
| Синтаксическая | до запуска, при разборе кода | компилятор или интерпретатор, линтер, подсветка в редакторе |
| Компиляции | на этапе сборки в машинный или байт-код | компилятор, сообщения сборки |
| Логическая | во время работы, результат неверный | тесты, ревью кода, отладчик, сверка с ожиданием |
| Времени выполнения (runtime) | во время выполнения при определенных данных | обработка исключений, логи, мониторинг, тесты граничных значений |
| Интеграционная | при взаимодействии модулей, сервисов, API | интеграционные и контрактные тесты, тестовые стенды |
Выводы
- Баг — это дефект в коде или поведении программы; он не всегда виден, пока не сложатся условия для сбоя.
- Ошибка, дефект (баг) и сбой — разные звенья одной цепочки: ошибка человека порождает дефект, а дефект проявляется как сбой.
- По моменту проявления ошибки делятся на синтаксические, компиляции, логические, времени выполнения и интеграционные. Компилятор ловит первые два вида, но логику и runtime не проверяет.
- Severity и priority — независимые шкалы: серьезный технически баг может иметь низкий приоритет, а мелкий — высокий.
- Самые дорогие в отладке — логические и runtime-ошибки, потому что код при них выглядит рабочим; ловят их тестами и отладчиком, а не компилятором.
- Чем раньше найден баг (на разработке или тестировании, а не после релиза), тем дешевле и быстрее его исправить.
Где применяется / связь с практикой
Умение отличать виды ошибок и понимать их жизненный цикл — базовый навык тестировщика. На собеседованиях в QA почти всегда спрашивают разницу между багом, дефектом и сбоем, а также между severity и priority, и от этого зависит, как быстро команда договорится, что чинить в первую очередь.
Если хочется разобраться в тестировании системно — от классификации багов до работы с трекерами и автотестами, посмотрите курс QA-инженер по автоматизации на JavaScript. Чтобы сначала присмотреться к профессии без обязательств, удобно сходить на бесплатные вебинары — там разбирают реальные задачи и отвечают на вопросы вживую.
Смежные темы: Тестирование ПО или как стать тестировщиком, Чем занимается QA-инженер?, Топ 7 мифов в работе QA-тестировщика.
FAQ
Баг или фича — как понять разницу?
Багом считают поведение, которое расходится с требованиями или ожиданиями. Если неожиданное поведение заложено в спецификацию намеренно, это фича, а не баг. Спорные случаи решают не программисты в одиночку, а по требованиям и договоренности с заказчиком.
Можно ли выпускать продукт с известными багами?
Да, так делают часто: баги с низкой severity и низким приоритетом заносят в список известных проблем (known issues) и чинят в следующих версиях. Блокеры и критические дефекты релиз обычно останавливают.
Все ли ошибки находит компилятор?
Нет. Компилятор и интерпретатор ловят синтаксические ошибки и ошибки типов, но логические и runtime-ошибки для него невидимы — код формально корректен. Их выявляют тестами, ревью и отладкой.



