Как вы тестировали API в вашем последнем проекте?

Ответ

Мы использовали комбинированный подход: автоматизированные тесты на Python (pytest) для CI/CD и Postman для ручного exploratory-тестирования и коллекции запросов.

Стек и подход:

  1. Модульные и интеграционные тесты (pytest): Проверяли логику обработчиков и интеграцию с БД/сервисами.
  2. API-тесты (requests + pytest): Автоматические скрипты для проверки эндпоинтов.
  3. Контрактное тестирование (Pact): Гарантировали совместимость между потребителем (frontend) и поставщиком (backend) API.
  4. Нагрузочное тестирование (Locust): Оценивали поведение системы под нагрузкой.

Пример автотеста для REST API:

import pytest
import requests
from schemas import USER_SCHEMA  # Схема для валидации ответа

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

@pytest.mark.parametrize("user_id, expected_status", [
    (1, 200),
    (999, 404),  # Негативный сценарий
    ("invalid", 422)  # Проверка валидации
])
def test_get_user_by_id(user_id, expected_status):
    """Тест эндпоинта GET /users/{id}"""
    response = requests.get(f"{BASE_URL}/users/{user_id}")

    assert response.status_code == expected_status

    if expected_status == 200:
        # Валидация структуры ответа по JSON Schema
        data = response.json()
        assert validate_schema(data, USER_SCHEMA) is True
        # Проверка бизнес-логики
        assert data["id"] == user_id
        assert "email" in data
        assert "@" in data["email"]

Что покрывали тестами:

  • Коды ответов HTTP (200, 201, 400, 401, 403, 404, 422, 500).
  • Корректность JSON-схемы ответа и типов данных.
  • Бизнес-логику и правильность возвращаемых данных.
  • Авторизацию и права доступа (JWT-токены, роли).
  • Граничные случаи и валидацию входных данных.
  • Скорость ответа (падал тест при превышении лимита, например, 500 мс).

Тесты запускались в пайплайне CI/CD (GitLab CI) при каждом пулл-реквесте и деплое.

Ответ 18+ 🔞

А, ну это ж классика, блядь! Сейчас расскажу, как мы эту хуйню тестировали, а то у нас там был целый ёперный театр, в рот меня чих-пых!

Так, слушай сюда, сука. Мы не просто так, как мартышлюшки, по кнопкам тыкали. Нет, блядь! У нас был целый комбинированный подход, чтоб его в сраку. С одной стороны — автоматические тесты на Python, через этот самый pytest, чтобы в CI/CD всё летало само, как по маслу. А с другой — Postman, для ручного, так сказать, разведовательного тестирования и всяких коллекций запросов, чтобы можно было быстро чё-то проверить, не заморачиваясь.

Вот наш стек и подход, блядь, держи:

  1. Модульные и интеграционные тесты (pytest): Это чтобы проверить, не обосралась ли логика наших обработчиков и как они там с базой данных или другими сервисами целуются. Без этого — никуда, иначе потом хуй разберёшь, что сломалось.
  2. API-тесты (requests + pytest): Автоматические скрипты, которые просто долбят по нашим эндпоинтам и смотрят, не отвалилось ли чего. Просто, но овердохуища эффективно.
  3. Контрактное тестирование (Pact): А это, блядь, чтобы гарантировать, что фронтенд и бэкенд друг друга понимают. Чтоб не вышло, что бэк что-то поменял, а фронт словил пиздец и всё разъехалось. Святая святых, ебать!
  4. Нагрузочное тестирование (Locust): Ну это чтобы понять, выдержит ли наша система, когда на неё налетит толпа пидаров-пользователей. Оценивали, как она под нагрузкой пыхтит.

Вот, смотри, пример одного такого автотеста для REST API, чтоб ты понимал масштаб:

import pytest
import requests
from schemas import USER_SCHEMA  # Схема для валидации ответа

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

@pytest.mark.parametrize("user_id, expected_status", [
    (1, 200),
    (999, 404),  # Негативный сценарий
    ("invalid", 422)  # Проверка валидации
])
def test_get_user_by_id(user_id, expected_status):
    """Тест эндпоинта GET /users/{id}"""
    response = requests.get(f"{BASE_URL}/users/{user_id}")

    assert response.status_code == expected_status

    if expected_status == 200:
        # Валидация структуры ответа по JSON Schema
        data = response.json()
        assert validate_schema(data, USER_SCHEMA) is True
        # Проверка бизнес-логики
        assert data["id"] == user_id
        assert "email" in data
        assert "@" in data["email"]

И чё мы этим всем покрывали, спросишь ты? А вот чё, блядь:

  • Коды ответов HTTP (200, 201, 400, 401, 403, 404, 422, 500). Чтобы не было такого, что запросил пользователя, а тебе сервер 500-ю ошибку в жопу сунул.
  • Корректность JSON-схемы ответа и типов данных. Чтоб не пришло вместо числа строку, а мы бы тут сидели и ебались.
  • Бизнес-логику и правильность возвращаемых данных. Ну, там, если запросил юзера с ID 1, то должен получить именно его, а не какую-то левую тётку.
  • Авторизацию и права доступа (JWT-токены, роли). Чтобы не вышло, что любой левый чувак может админские штуки делать.
  • Граничные случаи и валидацию входных данных. Типа, что будет, если передать в ID буквы? Правильно — пиздец и 422-я ошибка.
  • Скорость ответа. У нас тест падал, если ответ приходил дольше, чем за 500 мс, например. А то потом пользователи начнут материться, что всё тормозит.

И вся эта хуйня запускалась у нас в пайплайне CI/CD, в этом самом GitLab CI, при каждом пулл-реквесте и деплое. Чтобы ни одна кривая сборка не проскочила, блядь! Вот так-то.