Самая частая практическая задача на собесе: «Вот эндпоинт, как будете тестировать?». Хороший ответ структурирован и не сводится к «отправлю запрос и посмотрю на 200».
Каркас ответа
Для любого эндпоинта идите по слоям:
- Позитив: минимальный набор полей и полный. Код, заголовки, тело, схема.
- Валидация: обязательность, типы, форматы, границы.
- Бизнес-правила: дубли, переходы статусов, расчёты.
- Доступ: без токена, чужая роль, чужой объект.
- Состояние: что реально изменилось в системе.
- Надёжность: повторы, параллельность, таймауты зависимостей.
Валидация полей
Для каждого поля берите классы эквивалентности и границы. Пример: qty целое от 1 до 99.
| Класс | Значения | Ожидание |
|---|---|---|
| границы | 0, 1, 99, 100 | 400, 201, 201, 400 |
| тип | "5", 1.5, true | 400 |
| пустота | null, поле отсутствует | 400 |
Строки: пустая, только пробелы, длина на границах и сильно больше (бывает 500 из-за ограничения колонки), кириллица и эмодзи, <script>, кавычки и ' OR 1=1 --.
Ожидание для невалидного ввода всегда одно: 4xx с понятным сообщением и указанием поля. 500 означает, что валидации нет.
Проверка ответа
Мало проверить код. Хороший API-тест смотрит:
- тело: значения ключевых полей;
- схему: типы и обязательные поля (JSON Schema);
- заголовки:
Content-Type,Location, кеш; - время ответа;
- что в ответе нет лишнего: хешей паролей, внутренних id, стектрейсов.
Побочные эффекты
201 Created с красивым телом ничего не гарантирует. Ответ мог быть собран из запроса, а в базу записалось не то. Проверяйте состояние:
GETсозданного объекта;- запрос в БД: статус, суммы, связанные таблицы;
- событие в очереди или outbox;
- письмо, уведомление, списание остатка.
Повторы и гонки
- Повтор: таймаут не значит, что операция не выполнилась. Клиент повторяет оплату, и без ключа идемпотентности деньги спишутся дважды. Тест: повтор с тем же
Idempotency-Keyвозвращает тот же результат, тот же ключ с другим телом даёт ошибку. - Гонка: промокод на одно использование, последний товар на складе, регистрация того же email. Последовательный повтор этого не ловит. Отправьте 10-20 одинаковых запросов параллельно и проверьте данные. Защита бывает только в базе: уникальное ограничение или блокировка.
Зависимости и моки
Чтобы проверить, как сервис переживает падение соседа, его заменяют стабом (WireMock, MockServer): ответ через 30 секунд, 503, битый JSON, пустое тело. На настоящем платёжном шлюзе такого не дождаться, а в проде так проверять нельзя.
Данные для тестов
Тесты, которые делят данные, падают через раз при параллельном запуске. Правило: каждый тест создаёт своё (уникальные email с суффиксом, uuid) и убирает за собой в блоке, который выполнится и при падении.
Где API в пирамиде
Бизнес-логику выгоднее проверять на уровне API: быстро, стабильно, падает рядом с причиной. UI-тестов немного, на ключевые пути. Между сервисами контрактные тесты.
Частые ошибки
- Проверять только happy path и код 200.
- Не смотреть в базу после успешного ответа.
- Считать, что повтор и параллельность одно и то же.
- Тестировать права через интерфейс, а не прямыми запросами.
Что спросят на собесе
- Как протестировать
POST /users(или форму регистрации через API)? - Какие граничные значения вы возьмёте для поля?
- Что проверить кроме кода ответа?
- Как проверить, что оплата не спишется дважды?
- Зачем нужны моки и стабы?