Какой у вас опыт интеграционного тестирования API?

Ответ

Опыт включает тестирование REST API как вручную, так и с помощью автоматизации. Основной стек: Postman (для ручных проверок и коллекций), Python с библиотеками Requests и Pytest (для автотестов).

Типичные проверки в интеграционных тестах API:

  • Корректность HTTP-статусов: 200 OK, 201 Created, 400 Bad Request, 401 Unauthorized, 404 Not Found, 500 Internal Server Error.
  • Валидация структуры и данных ответа:
    • Соответствие JSON-схеме (используется библиотека jsonschema).
    • Проверка типов данных, обязательных полей, форматов значений (например, date-time).
  • Проверка бизнес-логики: Корректность вычислений, состояние данных после выполнения запроса.
  • Проверка заголовков (headers): Content-Type, Authorization (JWT, OAuth2).
  • Обработка граничных случаев и ошибок: Передача невалидных данных, проверка валидационных сообщений.

Пример автотеста для цепочки запросов (создание -> чтение -> удаление ресурса):

import requests
import pytest

BASE_URL = "https://api.example.com/v1"

@pytest.fixture
def auth_headers():
    # Получение токена для авторизации
    auth_resp = requests.post(f"{BASE_URL}/auth", json={"login": "user", "pass": "pass"})
    token = auth_resp.json()["access_token"]
    return {"Authorization": f"Bearer {token}"}

def test_user_crud_lifecycle(auth_headers):
    # 1. CREATE (POST)
    new_user = {"name": "John Doe", "email": "john@example.com"}
    create_resp = requests.post(f"{BASE_URL}/users", json=new_user, headers=auth_headers)
    assert create_resp.status_code == 201
    user_id = create_resp.json()["id"]

    # 2. READ (GET) - проверяем, что пользователь создан
    get_resp = requests.get(f"{BASE_URL}/users/{user_id}", headers=auth_headers)
    assert get_resp.status_code == 200
    assert get_resp.json()["name"] == new_user["name"]

    # 3. DELETE (DELETE) - очистка тестовых данных
    delete_resp = requests.delete(f"{BASE_URL}/users/{user_id}", headers=auth_headers)
    assert delete_resp.status_code == 204

    # 4. Проверяем, что пользователь удален
    get_resp_after = requests.get(f"{BASE_URL}/users/{user_id}", headers=auth_headers)
    assert get_resp_after.status_code == 404

Ответ 18+ 🔞

А, вот это я понимаю — тестирование API! Ты знаешь, это как пытаться объяснить глухонемому Герасиму, что его Муму не срет на крыше, блядь. Только вместо собаки у тебя — эти ебучие эндпоинты, которые то работают, то отдают 500-й статус просто потому что луна в Водолее, ёпта.

Так вот, смотри. Опыт у меня — овердохуища. И руками в Postman'е полапать могу, когда надо быстро проверить, не сломал ли чего фронтенд-разработчик, пока кофе пил. И на автомате, когда уже всё приелось и хочется, чтобы скрипты сами всё проверили, пока ты смотришь видосики про котиков.

Основной мой инструментарий — это Postman, конечно. Для коллекций, для ручных прогонов, когда надо понять, где именно система начинает истерить. А для серьёзных, долгих проверок — Python, библиотеки Requests да Pytest. Красота, блядь!

И что я там обычно проверяю, спросишь? Да всё, на что хватит терпения, а терпения, я тебе скажу, ноль ебать после пятого бага в одном и том же методе.

  • Статусы HTTP, мать их. Это святое. Должен 200 — получи 200. Должен 404 — на, получи свою «не найдено», сука. 401, когда токен протух — это вообще отдельная песня. А 500-й... Ну, 500-й — это когда разработчики совсем уже, в рот меня чих-пых, накосячили.
  • А ответ-то что внутри? JSON? А он правильный? Все поля на месте? id — integer, а не строка? created_at — дата, а не число? Вот для этого jsonschema — лучший друг. Засунул схему — и пусть библиотека сама орёт, если что не так.
  • Логика бизнес-. Ну вот создал ты заказ. А сумма-то правильно посчиталась? Скидка применилась? Вот это всё. Чтобы не вышло как в том анекдоте: «заказали один, а пришло сто, потому что в цикле ошибка».
  • Заголовки, блядь (headers). Особенно Authorization. Тыкаешься с этим Bearer токеном, с OAuth2... Иногда кажется, что проще самому стать сервером и всем ответы писать, чем разобраться в ихней системе прав.
  • И самое весёлое — обработка ошибок. Вот смотри: ты передаёшь в поле email строку «абвгд». Ну и? Сервер должен тебе вежливо сказать: «Чувак, это не имейл». А не падать с 500-й ошибкой и молча умирать в логах. Проверяем, что валидационные сообщения адекватные, а не «Internal server error», ёбта.

А вот тебе пример, как это выглядит в коде. Цепочка: создали юзера, проверили, что создался, потом удалили и убедились, что его нет. Чисто, аккуратно.

import requests
import pytest

BASE_URL = "https://api.example.com/v1"

@pytest.fixture
def auth_headers():
    # Тут мы получаем токен, чтобы нас не послали нахуй с первого же запроса
    auth_resp = requests.post(f"{BASE_URL}/auth", json={"login": "user", "pass": "pass"})
    token = auth_resp.json()["access_token"]
    return {"Authorization": f"Bearer {token}"}

def test_user_crud_lifecycle(auth_headers):
    # 1. СОЗДАЁМ (POST) — типа, давайте нового человека в систему
    new_user = {"name": "John Doe", "email": "john@example.com"}
    create_resp = requests.post(f"{BASE_URL}/users", json=new_user, headers=auth_headers)
    assert create_resp.status_code == 201  # Должен сказать «Создано!»
    user_id = create_resp.json()["id"]  # Вытаскиваем ID, он нам ещё пригодится

    # 2. ЧИТАЕМ (GET) — а правда создался? Проверим-ка
    get_resp = requests.get(f"{BASE_URL}/users/{user_id}", headers=auth_headers)
    assert get_resp.status_code == 200  # Всё ок, пользователь есть
    assert get_resp.json()["name"] == new_user["name"]  # И имя совпадает, красота

    # 3. УДАЛЯЕМ (DELETE) — чтобы не засорять базу тестовым хламом
    delete_resp = requests.delete(f"{BASE_URL}/users/{user_id}", headers=auth_headers)
    assert delete_resp.status_code == 204  # «Нет содержимого», всё удалено

    # 4. ФИНАЛЬНАЯ ПРОВЕРКА (GET) — а теперь его точно нет?
    get_resp_after = requests.get(f"{BASE_URL}/users/{user_id}", headers=auth_headers)
    assert get_resp_after.status_code == 404  # Вот теперь «Не найдено». Идеально.

Вот так-то, друг. Кажется, просто, да? А попробуй это на продакшене, где ползапроса в секунду, и смотри, как твои тесты падают из-за таймаутов. Но это уже совсем другая история, блядь.