Negative API testing

Почему негативные проверки API так важны и какие классы невалидных запросов QA должен использовать постоянно.

Обновлено:

Содержание

Позитивные проверки показывают, что API умеет работать в ожидаемом сценарии. Негативные проверки показывают, насколько оно устойчиво к плохим, неожиданным и опасным входам. Для QA это один из самых полезных классов тестирования, потому что именно здесь часто всплывают слабые места в валидации, обработке ошибок, безопасности и стабильности сервиса.

Если говорить совсем прямо, пользователь и интеграции почти никогда не ведут себя идеально. Кто-то отправит пустое поле, кто-то неправильный тип, кто-то просроченный токен, кто-то слишком большой payload, а кто-то попробует вызвать endpoint в недопустимом состоянии. Хороший API должен не просто "не падать", а предсказуемо и безопасно реагировать на такие запросы.

Что такое negative testing в API

Negative API testing - это проверка поведения системы на невалидных, неожиданных, запрещённых или конфликтных входных данных.

Это не только про "отправить пустое поле". Сюда входят разные классы ситуаций:

  • →отсутствуют обязательные поля
  • →значения переданы в неправильном формате
  • →тип данных не совпадает
  • →значение выходит за допустимый диапазон
  • →нарушена бизнес-логика комбинации полей
  • →пользователь не аутентифицирован или не авторизован
  • →payload слишком большой
  • →передан неожиданный Content-Type
  • →клиент вызывает метод, который здесь не должен работать
  • →запрос повторяется там, где это создаёт конфликт

То есть negative testing проверяет не только корректность входных данных, но и устойчивость API к неправильному использованию.

Почему это особенно важно для API

У UI есть хотя бы какой-то слой защиты: форма, маска, выпадающий список, disabled-кнопка. У API этой защиты нет в таком виде. Оно получает сырой запрос и должно само решить, что с ним делать.

Именно поэтому слабое negative testing у API обычно означает один из трёх рисков:

  • →сервис ломается на плохом входе
  • →сервис ведёт себя непредсказуемо
  • →сервис принимает то, что принимать не должен

Для QA это означает простую вещь: если ты проверяешь только happy path, ты видишь очень ограниченную часть реального поведения системы.

Что именно стоит ломать

Хороший negative testing строится по классам входов, а не по случайным "попробую вбить ерунду".

Полезно регулярно проверять такие группы:

  • →обязательные поля отсутствуют
  • →поле есть, но пустое
  • →поле есть, но null
  • →тип данных неверный: строка вместо числа, объект вместо массива
  • →длина строки больше допустимой
  • →число выходит за минимальную или максимальную границу
  • →формат даты, email, phone, UUID, enum невалиден
  • →недопустимая комбинация параметров
  • →лишние неожиданные поля
  • →неверный метод запроса
  • →неверный Content-Type
  • →повреждённый или просроченный токен
  • →доступ к чужому ресурсу
  • →слишком большой request body
  • →повторная отправка запроса в конфликтном состоянии

Если QA работает системно, эти проверки превращаются не в хаотичное "сломай как-нибудь", а в повторяемую модель качества API.

Что делает хороший negative test

Слабый negative test проверяет только то, что "пришла ошибка". Сильный negative test проверяет гораздо больше.

  • →правильный ли пришёл статус-код
  • →понятна ли ошибка клиенту
  • →не раскрывает ли ответ лишние внутренние детали
  • →не изменились ли данные там, где не должны были измениться
  • →не создались ли побочные эффекты
  • →одинаково ли система ведёт себя при повторе того же плохого запроса
  • →не уходит ли сервис в 500, если проблема на стороне клиента

Например, если отправить невалидный JSON, от сервиса обычно логично ждать 400, а не 500. Если пользователь пытается изменить чужой ресурс, ожидание обычно ближе к 403 или 404, но точно не к успешному ответу. Если тело слишком большое, корректной реакцией может быть 413. Для QA здесь важно не угадать "один идеальный код на все случаи", а проверить, что ошибка обрабатывается последовательно и внятно.

Что важно QA кроме самой ошибки

Одна из лучших привычек в negative API testing - всегда смотреть на состояние системы после неуспешного запроса.

  • →запись действительно не создалась?
  • →статус объекта не изменился?
  • →деньги не списались?
  • →письмо не отправилось?
  • →аудит и логирование сохранили событие корректно?
  • →повторный запрос не привёл систему в странное состояние?

Очень много опасных дефектов скрывается именно тут. Снаружи API вернул ошибку, но внутри уже частично успел изменить данные. Для пользователя это может проявиться позже и выглядеть как "странный случайный баг", хотя корень проблемы был в плохой обработке негативного сценария.

Практический пример

Представь endpoint создания пользователя.

Позитивный сценарий простой: отправляем валидный email, имя и пароль, получаем 201 Created.

Теперь negative scenarios:

  • →email отсутствует
  • →email пустой
  • →email невалидный
  • →пароль слишком короткий
  • →в body пришёл неожиданный тип поля
  • →запрос отправлен без авторизации, если она нужна
  • →тот же email создаётся повторно
  • →body слишком большой
  • →Content-Type не application/json

Что важно проверить QA:

  • →сервер отвечает предсказуемо
  • →ошибка описана достаточно понятно для клиента
  • →статус-код соответствует классу проблемы
  • →не создаётся битая запись
  • →не отправляются лишние побочные действия
  • →повтор одного и того же невалидного запроса не ломает систему сильнее

Вот здесь negative testing перестаёт быть "дополнением" и становится реальной проверкой зрелости API.

Что должен вынести QA из этой темы

  • →Negative API testing проверяет не только ошибки ввода, но и устойчивость системы.
  • →Хороший negative test смотрит не только на код ошибки, но и на состояние системы после неё.
  • →Один из главных признаков сильного API - оно безопасно и предсказуемо обрабатывает плохие запросы.
  • →Happy path почти никогда не показывает настоящую надёжность сервиса.
  • →Негативные проверки нужно строить по классам рисков, а не случайным попыткам "сломать что-нибудь".

Что ещё почитать

  • →Внутри базы: Методы, статус-коды, заголовки
  • →Внутри базы: Аутентификация и авторизация
  • →Внешний материал: OWASP REST Security Cheat Sheet

Локальная матрица негативных проверок с контролем побочных эффектов

Используйте явный учебный контракт, а не догадки о поведении любого API. Подготовленная локальная фикстура принимает POST /items с учебным токеном администратора, Content-Type application/json, именем из 3–12 букв ASCII и целым quantity от 1 до 5. В теле должны быть ровно эти два поля. Данные хранятся в памяти; для независимого теста запускайте чистый сервер.

plain text
Случай	Пример	Ожидание этой фикстуры
Нет поля	{"name":"abc"}	422 invalid_fields
Неверный тип	{"name":"abc","quantity":"1"}	422 invalid_quantity
Вне диапазона	{"name":"abc","quantity":6}	422 invalid_quantity
Лишнее поле	{"name":"abc","quantity":1,"admin":true}	422 invalid_fields
Сломанный JSON	{	400 malformed_json
Неверный media type	Content-Type: text/plain	415 json_required
Тело больше 1024 байт	1025 байт	413 payload_too_large

До отклоняемой записи выполните GET /items и сохраните total; после неё повторите запрос и требуйте прежнее значение. Так выявляется запись, которая успела сохраниться до ошибки. Для нового валидного имени ожидаются 201 и total + 1; повтор имени даёт 409 без второй записи. Эти коды относятся к объявленному контракту, а не являются обязательными для всех продуктов.

plain text
python3 mock_api.py --port 8765
# Во втором терминале; токен только синтетический и локальный:
curl -i http://127.0.0.1:8765/items -H "Authorization: Bearer demo-admin" -H "Content-Type: application/json" --data '{"name":"abc","quantity":6}'
python3 -m unittest test_mock_api.py -v

Фикстура намеренно локальная и упрощённая. Она нужна для выбора входных данных и сбора доказательств; фиксированные токены и учебный HTTP-сервер не следует переносить в промышленную аутентификацию.

Продолжить изучение

Скачать локальную учебную лабораторию (ZIP)

Проверка прав отдельно от валидации

Выбор граничных значений