Почему важно тестировать обработку ошибок
Когда API работает идеально, тестирование просто. Настоящий вызов — и где прячется большинство багов — в том, как API обрабатывает ситуации, когда что-то идёт не так. Тестирование обработки ошибок проверяет, что API падает корректно, предоставляет полезную информацию и не раскрывает уязвимости.
В продакшне в компаниях вроде Google качество обработки ошибок напрямую влияет на скорость отладки. Чёткое сообщение «Поле ’email’ должно содержать валидный email» экономит часы по сравнению с общим «Bad Request».
Структура ответа об ошибке
Хорошо спроектированный ответ об ошибке следует единообразному формату:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Ошибка валидации запроса",
"details": [
{
"field": "email",
"message": "Должен быть валидным email-адресом",
"value": "не-email"
},
{
"field": "age",
"message": "Должен быть положительным целым числом",
"value": -5
}
]
},
"requestId": "req_abc123",
"timestamp": "2025-12-15T10:30:00Z"
}
Что проверять в ответах об ошибках
| Аспект | Что верифицировать |
|---|---|
| Код статуса | Соответствует типу ошибки (400, 401, 403, 404, 422, 500) |
| Код ошибки | Машиночитаемый, единообразный по всему API |
| Сообщение | Человекочитаемое, действенное, без внутренних деталей |
| Детали | Конкретные ошибки на уровне полей |
| ID запроса | Присутствует для отладки |
| Content-Type | По-прежнему application/json даже для ошибок |
Категории тестирования ошибок
Ошибки валидации ввода (400/422)
Тестируйте каждое поле ввода с невалидными данными:
Отсутствие обязательных полей → "Поле 'name' обязательно"
Неверный тип данных → "Поле 'age' должно быть целым числом"
Вне диапазона → "Поле 'age' должно быть от 0 до 150"
Невалидный формат → "Поле 'email' должно быть валидным"
Слишком длинное → "Поле 'name' максимум 100 символов"
Невалидный enum → "Поле 'role': admin, user, viewer"
Ошибки аутентификации (401)
| Сценарий | Ожидаемое сообщение |
|---|---|
| Токен не предоставлен | «Требуется аутентификация» |
| Просроченный токен | «Токен истёк» |
| Некорректный токен | «Невалидный токен аутентификации» |
| Отозванный токен | «Токен был отозван» |
Ошибки авторизации (403)
| Сценарий | Ожидаемое сообщение |
|---|---|
| Пользователь на admin-endpoint | «Недостаточно прав» |
| Доступ к чужим данным | «Доступ запрещён» |
| Отключённая функция | «Недоступно для вашего плана» |
Ошибки Not Found (404)
| Сценарий | Ожидаемое сообщение |
|---|---|
| Невалидный ID ресурса | «Пользователь не найден» |
| Удалённый ресурс | «Ресурс больше не существует» |
| Неверный endpoint | Стандартный ответ 404 |
Продвинутое тестирование ошибок
Единообразие ошибок
Проверьте, что ошибки следуют одному формату по всему API:
- Одинаковая JSON-структура для всех ответов
- Единообразные коды ошибок
- Единообразное использование кодов статуса
Безопасность в сообщениях об ошибках
Проверьте, что сообщения НЕ раскрывают:
- Имена таблиц или колонок БД
- Stack trace или пути файлов
- SQL-запросы
- Имена внутренних сервисов или IP-адреса
- Факт существования пользователя (для endpoint-ов логина)
Плохо: "Error: SELECT * FROM users WHERE id=42 failed: connection to postgres:5432 refused"
Хорошо: "Не удалось обработать запрос. Попробуйте позже. Ссылка: req_abc123"
Обработка ошибок под нагрузкой
- БД недоступна? (должен быть 503, не 500 со stack trace)
- Некорректный JSON? (должен быть 400, не 500)
- Огромный payload? (должен быть 413 Payload Too Large)
- Неподдерживаемый Content-Type? (должен быть 415)
Интернационализация сообщений об ошибках
Если API поддерживает несколько языков:
- Сообщения на каждом языке через Accept-Language
- Fallback на язык по умолчанию
- Коды ошибок неизменны вне зависимости от языка
Построение набора тестов ошибок
Для каждого endpoint-а создайте матрицу:
POST /api/users
├── Отсутствует 'name' → 400, VALIDATION_ERROR
├── Пустой 'name' → 400, VALIDATION_ERROR
├── Имя слишком длинное → 400, VALIDATION_ERROR
├── Невалидный email → 422, VALIDATION_ERROR
├── Дублирующийся email → 409, CONFLICT
├── Без auth-токена → 401, AUTH_REQUIRED
├── Невалидный токен → 401, INVALID_TOKEN
├── Роль user на admin → 403, FORBIDDEN
├── Некорректный JSON → 400, PARSE_ERROR
└── Неверный Content-Type → 415, UNSUPPORTED_MEDIA_TYPE
Практическое упражнение
- Отобразите ответы об ошибках: Отправьте 10 невалидных запросов к JSONPlaceholder и задокументируйте каждый формат ответа
- Проверьте единообразие: Сравните форматы ошибок между endpoint-ами
- Аудит безопасности: Поищите ответы, раскрывающие внутренние детали
- Создайте матрицу ошибок: Для endpoint-а регистрации перечислите все сценарии ошибок
Ключевые выводы
- Тестирование обработки ошибок так же важно, как тестирование позитивных сценариев
- Ответы об ошибках должны следовать единой структуре: код статуса, код ошибки, сообщение и детали
- Никогда не раскрывайте внутренние детали в сообщениях об ошибках
- Тестируйте каждое поле с каждым типом невалидных данных
- Стройте систематические матрицы тестов ошибок для каждого endpoint-а