Go: Автоматическое тестирование
Теория: Тестирование ошибок и паник
Ошибки и паники — это два разных уровня поломок в программе. Ошибка — это ожидаемая ситуация, которую можно обработать. Пользователь ввёл кривые данные, файл не открылся, база недоступна — всё это нормально, функция вернула ошибку, а вызывающий код решает, что с ней делать.
Паника — это авария. Программа оказалась в состоянии, где продолжать работу уже нельзя. Например, деление на ноль в функции, которая по контракту должна «всегда делить», или сломанное внутреннее состояние. В Go паника выбивается с помощью panic.
В тестах важно проверять и то, и другое: иногда функция должна вернуть ошибку, а иногда она обязана упасть.
Ошибки: встроенный тип error
В Go ошибки — это обычные значения. Есть встроенный интерфейс:
То есть всё, что умеет возвращать строку через метод Error(), считается ошибкой. Чаще всего используют errors.New("...") или fmt.Errorf("..."), чтобы создать ошибку.
Функции обычно возвращают результат и ошибку:
Если всё хорошо — ошибка равна nil. Если что-то пошло не так — вторая переменная хранит ошибку с описанием.
Проверка ошибок в тестах
Когда мы пишем тест, важно проверить не только «счастливый путь», но и то, как функция реагирует на неправильный ввод.
Почему t.Fatal и t.Errorf разные?
t.Fatal(иt.Fatalf) — это экстренный стоп. Тест немедленно прерывается. Мы используем его там, где без этого дальше нет смысла. В примере выше — если ошибки вообще нет, то сравнивать её текст бессмысленно.t.Error(иt.Errorf) — это мягкий сигнал: «что-то не так, но давай посмотрим дальше». Тест помечается как упавший, но выполнение продолжается. Это удобно, если ошибка есть, но сообщение отличается — тогда мы хотя бы увидим, что ещё делал тест.
Нужно запомнить правило: Fatal — для критичных проверок, Error — для уточняющих.
Паники: аварийные ситуации
Иногда функция должна не вернуть ошибку, а «завалиться» с паникой. Это используется редко, но бывают такие места, где программа не имеет смысла без аварийной остановки.
Проверка паник в тестах
Если такую функцию вызвать напрямую, весь тест упадёт. Чтобы проверить панику, нужно её поймать. Для этого есть связка defer + recover.
Схема работы простая:
- Ставим
deferс анонимной функцией. - Внутри неё вызываем
recover(). - Если
recover()вернулnil→ паники не было → тест провален. - Если вернул строку → проверяем, что она совпадает с ожидаемой.
Когда ошибка, а когда паника?
Ошибки — это часть нормального хода программы. Мы можем их обработать и продолжить работу:
- Пользователь не ввёл пароль → показали сообщение.
- Файл не найден → создали новый.
- Подключение к БД не вышло → повторили через секунду.
Паники — это аварии. Тут уже нельзя «показать подсказку и продолжить». Надо валить выполнение или хотя бы остановить конкретный кусок.
- Нарушены внутренние инварианты.
- В функцию передали данные, с которыми она категорически не умеет работать.
- Ошибка в инициализации, без которой приложение бессмысленно.
В тестах важно фиксировать и такие сценарии: что код не просто «как-то себя ведёт», а строго выдаёт ошибку или строго падает.
Ошибки в Go — это встроенный механизм, с которым мы сталкиваемся постоянно. Паники — более редкий инструмент, но их тоже нужно уметь проверять.
Ошибки проверяются через if err != nil и err.Error(). Паники — через defer и recover. В тестах t.Fatal используют для критичных проверок, когда без этого тест теряет смысл, а t.Errorf — для уточняющих сравнений.
Так мы получаем тесты, которые покрывают весь спектр: и удачные сценарии, и ошибки, и аварийные ситуации.



