Зачем это спрашивают
Ответ «смотрю, что пришёл 200» — один из самых частых и самых слабых на собеседовании. Интервьюер задаёт этот вопрос, чтобы понять глубину: видите ли вы за запросом контракт, данные, права доступа и состояние системы. Сильный кандидат перечисляет проверки по группам, приводит негативные сценарии и обязательно говорит о том, что изменение нужно подтвердить повторным чтением.
Часто следом спрашивают: «какие негативные проверки вы сделаете для эндпоинта, который принимает JSON». Поэтому полезно сразу подготовить обе части.
Как построить сильный ответ
Говорите по слоям — от запроса к ответу и дальше к системе.
1. Контракт и позитивный сценарий
- Запрос по документации проходит, возвращается ожидаемый код: 200, 201 при создании, 204 при удалении без тела.
- Тело соответствует схеме: все обязательные поля на месте, типы верные (цена — число, а не строка), форматы дат согласованы.
- В ответе нет лишнего: хэшей паролей, внутренних идентификаторов, служебных полей, чужих персональных данных.
- Заголовки:
Content-Typeсоответствует телу, для ответов с личными данными задан запрет кэширования, при создании может прийтиLocation.
2. Состояние после изменения
Код 201 говорит лишь о том, что сервер так ответил. Проверка, что данные действительно сохранились, — отдельный GET после POST, PUT, PATCH или DELETE. Это одна из самых ценных привычек: так ловятся ответы «успешно», за которыми ничего не записалось.
3. Негативные проверки
| Группа | Примеры | Ожидание |
|---|---|---|
| Структура тела | пустое тело, битый JSON, не тот Content-Type | 400 |
| Обязательные поля | поле отсутствует, равно null, пустая строка | 400 или 422 |
| Типы и форматы | строка вместо числа, неверный формат даты | 400 или 422 |
| Границы | 0, отрицательное, очень большое значение, длинная строка | 4xx по требованиям |
| Лишние поля | неизвестное поле, попытка передать role или price |
игнор или 400, но не применение |
| Ресурс | несуществующий id, id другого типа | 404 или 400 |
| Повтор | тот же POST дважды | без незапланированных дублей |
Главное правило: на любой некорректный ввод сервер отвечает 4xx с понятным сообщением. 5xx в ответ на ошибку клиента — это дефект.
4. Аутентификация и права
- Без токена, с истёкшим, с испорченным — 401.
- С токеном пользователя без нужной роли — 403.
- С токеном другого пользователя к чужому объекту — 403 или 404, но не чужие данные.
5. Нефункциональное
Время ответа, пагинация и фильтры на больших списках, лимиты запросов (429), поведение при одновременных запросах к одному объекту.
Пример автотеста, который проверяет и ответ, и сохранение:
import requests
def test_create_order_is_persisted(base_url, auth_headers, product_id):
payload = {"items": [{"productId": product_id, "qty": 2}]}
created = requests.post(f"{base_url}/api/shop/orders",
json=payload, headers=auth_headers, timeout=10)
assert created.status_code in (200, 201)
order_id = created.json()["id"]
orders = requests.get(f"{base_url}/api/orders",
headers=auth_headers, timeout=10).json()
assert any(o["id"] == order_id for o in orders)
Поля в примере условные — настоящую схему берите из Swagger.
Пример ответа
Я иду по слоям. Сначала позитивный сценарий по контракту: код ответа соответствует ситуации, тело совпадает со схемой — обязательные поля, типы, форматы, — и в нём нет ничего лишнего, вроде паролей или внутренних данных. Смотрю заголовки, например Content-Type. Если запрос что-то меняет, отдельным GET проверяю, что данные действительно сохранились. Потом негатив: пустое тело, битый JSON, нет обязательного поля, неверный тип, null, граничные значения, несуществующий id, повтор запроса. Везде жду 4xx с понятной ошибкой, а 5xx считаю багом. Отдельно права: без токена — 401, без роли — 403, с чужим токеном к чужому объекту — не должен получить данные. И держу в голове время ответа.
Частые ошибки
- Ограничиваться проверкой статуса и не смотреть тело.
- Верить коду 201 без повторного чтения данных.
- Перечислять случайные негативные примеры вместо групп с ожидаемыми кодами.
- Забывать про права доступа к чужим объектам — это одна из самых опасных категорий дефектов.
- Не замечать лишние поля в ответе, хотя утечка данных бывает серьёзнее падения.
Пример на MarketCove
Как бы вы проверяли оформление заказа через API учебного магазина MarketCove:
- Позитив. Войдите, оформите заказ через
/api/shop/ordersс товаром изGET /api/products. Сверьте ответ со схемой в Swagger на/api/docs, затем найдите заказ вGET /api/ordersи в истории профиля. - Гость. Магазин разрешает оформление без входа — проверьте, что гостевой заказ создаётся, но не появляется в истории чужого аккаунта.
- Негатив. Несуществующий
productId, строка вместо числа в идентификаторе, отсутствующее поле «Адрес», битый JSON, неверныйContent-Type. Подумайте, какие коды и сообщения ожидаете, и запишите их до отправки. - Каталог по контракту. Сравните
GET /api/productsиGET /api/products/{id}со схемой в Swagger: типы полей, формат цены, полеoldPrice, которое есть только у части товаров, — схема должна это допускать. Несуществующийidдолжен давать 404, а не 500. - Права и сессия. Создайте два аккаунта и проверьте, что
GET /api/users/meс токеном одного не возвращает данные другого, а без токена или с испорченным токеном отвечает 401. Отдельный вопрос к контракту: что должен вернутьGET /api/orders/{id}с номером чужого заказа — 403 или 404, и что сказано об этом в Swagger.
Задание для практики
Выберите один эндпоинт в API-песочнице и составьте по нему чек-лист из пяти групп этой статьи — минимум по две проверки в каждой, с ожидаемым кодом. Выполните проверки и отметьте, где результат расходится с ожиданием. Если раньше коды ответа давались с трудом, повторите статью про коды ответа HTTP, а для повтора запросов пригодится работа в Postman.
