Что такое API и как его тестируют?

Ответ

API (Application Programming Interface) — это контракт, который определяет, как разные программные компоненты взаимодействуют друг с другом. Он описывает доступные конечные точки (endpoints), форматы запросов и ответов, методы аутентификации и ожидаемое поведение.

Основные типы API в веб-разработке:

  1. REST (Representational State Transfer): Использует HTTP-методы (GET, POST, PUT, DELETE) и стандартные форматы данных, чаще всего JSON.
  2. GraphQL: Позволяет клиенту запрашивать именно те данные, которые ему нужны, в одном запросе.
  3. gRPC: Высокопроизводительный RPC-фреймворк, использующий Protocol Buffers для сериализации.

Ключевые аспекты тестирования API:

  • Функциональное тестирование: Проверка корректности статус-кодов, тела ответа, заголовков и бизнес-логики.
  • Валидация схемы: Использование JSON Schema или аналогичных инструментов для проверки структуры ответа.
  • Тестирование граничных условий и ошибок: Проверка обработки невалидных данных, отсутствующих ресурсов, лимитов скорости (rate limiting).
  • Интеграционное тестирование: Проверка взаимодействия API с базой данных, кэшем или другими сервисами.
  • Нагрузочное тестирование: Оценка производительности (latency, throughput) под нагрузкой.

Пример теста REST API на Python с использованием Pytest и requests:

import pytest
import requests
from jsonschema import validate

# Схема ожидаемого ответа для /users/{id}
USER_SCHEMA = {
    "type": "object",
    "properties": {
        "id": {"type": "integer"},
        "name": {"type": "string"},
        "email": {"type": "string", "format": "email"}
    },
    "required": ["id", "name", "email"]
}

def test_get_user_by_id():
    """Тест на получение пользователя по ID."""
    base_url = "https://api.example.com"
    user_id = 1

    response = requests.get(f"{base_url}/users/{user_id}")

    # Проверка статус-кода
    assert response.status_code == 200

    # Валидация структуры ответа по JSON Schema
    user_data = response.json()
    validate(instance=user_data, schema=USER_SCHEMA)

    # Проверка бизнес-логики
    assert user_data["id"] == user_id
    assert "@" in user_data["email"]

# Тест на обработку ошибки 404
@pytest.mark.parametrize("invalid_id", [0, 99999])
def test_get_user_not_found(invalid_id):
    response = requests.get(f"https://api.example.com/users/{invalid_id}")
    assert response.status_code == 404

Для автоматизации часто используются фреймворки: Pytest/Requests (Python), RestAssured (Java), Supertest (JavaScript).

Ответ 18+ 🔞

Да ты посмотри, что эти ваши API вытворяют, ебать мои старые костыли! Ну, представь, два куска программы, которые друг друга в упор не видят, как два мудака в тёмной комнате. Им же надо как-то общаться! Вот для этого и придумали этот ваш API (Application Programming Interface). Это типа такой контракт, бумажка, где чёрным по белому написано: «Ты, сервер, будешь стоять на таком-то адресе, я, клиент, буду тебе тыкать палкой в определённые дырочки (эндпоинты), а ты в ответ должен плюнуть в меня данными в строго оговорённом формате». Всё, пиздец, никакой самодеятельности!

Какие они бывают, эти ваши API, ёпта:

  1. REST (Representational State Transfer): Самый распиздяйский и популярный. Тыкаешь в него HTTP-командами: GET (посмотреть), POST (сунуть), PUT (поменять), DELETE (удалить). Ответы обычно в JSON, который все якобы понимают.
  2. GraphQL: Это для хитрожопых. Клиент приходит и говорит: «Мне вот это, это и вот то, но без того зелёного поля, а то оно меня ебёт». И получает всё в одном ответе, а не бегает по десяти запросам, как конченый.
  3. gRPC: Это уже для серьёзных пацанов, где скорость — всё. Тут данные жмут в бинарный формат, Protocol Buffers, и шлют нахуй быстрее света. Никаких тебе JSON'ов с лишними кавычками.

А теперь, как это всё протестировать, чтобы не обосраться на проде:

  • Функциональное тестирование: Самый базовый санчек. Отправил запрос — получил ответ. А статус-код 200, а не 500? А в теле ответа нужные поля есть, а не какая-то хуйня? А логика не поехала?
  • Валидация схемы: Это когда ты не просто смотришь, что тебе что-то пришло, а проверяешь по эталону (JSON Schema), что пришло именно ТО, что должно. Что id — число, а не строка «хер знает что», а email содержит собаку, а не пробел.
  • Тестирование ошибок и границ: Вот это самое весёлое! Надо проверить, как API ведёт себя, когда ему в рот лезут с полной хуйнёй. Отправил отрицательный ID, отправил текст вместо числа, отправил запросов овердохуища в секунду (rate limiting). Упадёт красиво с понятной ошибкой или накроется медным тазом, утащив за собой базу?
  • Интеграционное тестирование: А тут мы проверяем, не обосрался ли наш API, когда пошёл общаться с базой данных или другим сервисом. Данные сохранил? Из кэша прочитал? Соседний микросервис не послал нахуй?
  • Нагрузочное тестирование: Сука, а выдержит ли он, когда на него навалится толпа? Запускаем тысячу виртуальных пользователей и смотрим, не станет ли время отклика хуйнёй, а throughput — пиздецом.

Смотри, как это примерно выглядит на Python с Pytest. Код не трогаю, он святой:

import pytest
import requests
from jsonschema import validate

# Схема ожидаемого ответа для /users/{id}
USER_SCHEMA = {
    "type": "object",
    "properties": {
        "id": {"type": "integer"},
        "name": {"type": "string"},
        "email": {"type": "string", "format": "email"}
    },
    "required": ["id", "name", "email"]
}

def test_get_user_by_id():
    """Тест на получение пользователя по ID."""
    base_url = "https://api.example.com"
    user_id = 1

    response = requests.get(f"{base_url}/users/{user_id}")

    # Проверка статус-кода
    assert response.status_code == 200

    # Валидация структуры ответа по JSON Schema
    user_data = response.json()
    validate(instance=user_data, schema=USER_SCHEMA)

    # Проверка бизнес-логики
    assert user_data["id"] == user_id
    assert "@" in user_data["email"]

# Тест на обработку ошибки 404
@pytest.mark.parametrize("invalid_id", [0, 99999])
def test_get_user_not_found(invalid_id):
    response = requests.get(f"https://api.example.com/users/{invalid_id}")
    assert response.status_code == 404

А вообще, инструментов — как говна за баней. Для Python — Pytest с Requests, для Java — RestAssured, для JavaScript — Supertest. Выбирай не хочу, лишь бы работало и не ебало мозг.