Привет, Хабр! Меня зовут Ваня (23 года), и я AQA-инженер. Как и многие из вас, я занимаюсь обучением будущих покорителей Postman и Pytest. И, как многие из вас, я столкнулся с проблемой: все существующие тестовые API — невыносимо скучные.
Todo-листы, интернет-магазины с товарами Item 1, Item 2, API для управления книгами… Серьезно? После пятого GET /todos начинаешь сомневаться не только в своей карьере, но и в смысле бытия. Данные в них стерильны, как операционная, а сценарии предсказуемы, как сюжет российского сериала.
Моим ученикам было скучно. Мне было скучно. Я понял, что нужен свой API. С блэкджеком и… ну, вы поняли. С API, который будет не просто функциональным, но и забавным. Который захочется «потыкать» просто ради того, чтобы увидеть очередной перл в ответе сервера.
Так родился «Cynical Circle API» — API для тех, кто понял жизнь и устал от ванильных примеров.
(Так выглядит наша интерактивная документация. Уже интригует, не правда ли?)
Концепция: тестовый бэкенд для циников
Идея проста: создать API, который имитирует небольшую социальную сеть для… уставших от всего людей. Вместо абстрактных «задач» и «продуктов» у нас есть две сущности:
-
Пользователи (
/users): Бедолаги, решившие зарегистрироваться в системе. О каждом можно сказать, что он «просто занимает место в базе данных». -
Посты (
/posts): Тленные мысли, крики души и бессмысленные изречения, которые эти пользователи могут публиковать.
Ключевые особенности проекта:
-
Черный юмор: Все описания эндпоинтов, моделей и даже сообщения об ошибках пропитаны здоровой долей цинизма.
404 Not Found? Нет, «Пользователь не найден. Возможно, он обрёл свободу». -
Zero-dependency (почти): Проект работает «in-memory». Никаких баз данных, Docker-контейнеров и прочих сложностей. Данные хранятся в обычном Python-списке и сбрасываются при перезапуске. Идеально для быстрых тестов.
-
Современный стек: Написан на FastAPI, что дает нам асинхронность, высокую скорость и, самое главное, автоматическую интерактивную документацию (Swagger UI и ReDoc). Для обучения — это киллер-фича.
-
Прозрачная структура: Код разбит на логические модули (роутеры, модели), что позволяет на его примере объяснять базовые принципы построения бэкенд-приложений.
Заглянем под капот
Давайте быстро пробежимся по архитектуре, чтобы вы понимали, насколько всё просто и прозрачно.
Структура проекта:
cynical_circle_api/ │ ├── app/ │ ├── main.py # Точка входа, здесь живет экземпляр FastAPI │ ├── routers/ # Логика обработки запросов │ │ ├── users.py │ │ └── posts.py │ └── models/ # Модели данных Pydantic для валидации │ ├── user.py │ └── post.py │ └── requirements.txt # Зависимости
Модели данных (Pydantic)
Вся валидация входящих и исходящих данных лежит на плечах Pydantic. Модели описаны предельно просто и с саркастичными комментариями.
app/models/user.py
from pydantic import BaseModel, Field from uuid import UUID class UserBase(BaseModel): username: str = Field(..., description="Имя пользователя, которое он забудет через неделю") email: str = Field(..., description="Почта для спама и уведомлений, которые никто не читает") class User(UserBase): id: UUID is_active: bool = Field(True, description="Активен ли пользователь или просто занимает место в базе данных")
Роутеры (Endpoints)
Логика каждого эндпоинта — это отдельная функция, обернутая в декоратор FastAPI. Вот, например, как выглядит создание пользователя. Обратите внимание на обработку ошибок.
app/routers/users.py
from fastapi import APIRouter, HTTPException, status # ... импорты router = APIRouter() # Наша "in-memory" база данных fake_users_db = [] @router.post("/", response_model=User, status_code=status.HTTP_201_CREATED, summary="Создать нового бедолагу") async def create_user(user_in: UserCreate): """ Регистрирует нового пользователя в системе. - **username**: Имя, которое скоро станет частью статистики. - **email**: Адрес для получения рекламы казино. - **password**: Секретная комбинация, известная вашему провайдеру. """ if any(u.email == user_in.email for u in fake_users_db): raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Эта почта уже занята кем-то более удачливым." ) # ... логика создания пользователя
Каждая функция подробно документирована с помощью docstring. FastAPI автоматически подтягивает эти описания в Swagger, делая документацию живой и полезной.
Как запустить этот островок безысходности?
Всё до смешного просто. Понадобится Python 3.8+ и пара минут времени.
1. Создаем и активируем виртуальное окружение:
# Windows python -m venv venv && venv\Scripts\activate # macOS/Linux python3 -m venv venv && source venv/bin/activate
2. Устанавливаем зависимости:
Проекту нужны всего три библиотеки: fastapi, uvicorn для запуска сервера и pydantic.
pip install fastapi uvicorn[standard] pydantic
3. Запускаем сервер:
Сохраните код из [репозитория](ссылка на ваш GitHub репозиторий) и выполните в терминале команду:
uvicorn app.main:app --reload
Сервер поднимется на http://127.0.0.1:8000.
4. Наслаждаемся!
Теперь можно открыть браузер и перейти по одному из адресов:
-
http://127.0.0.1:8000/docs— интерактивная документация Swagger UI. -
http://127.0.0.1:8000/redoc— альтернативный вариант документации ReDoc.
В Swagger можно не только посмотреть все эндпоинты, но и сразу же отправить на них запросы, посмотреть модели и коды ответов. Для новичков — это идеальная среда для знакомства с REST API.
Пример взаимодействия (для настоящих гуру терминала, ну или просто вставь в Postman)
Конечно, можно использовать и старый добрый cURL.
1. Создадим пользователя:
curl -X 'POST' \ 'http://127.0.0.1:8000/users/' \ -H 'Content-Type: application/json' \ -d '{ "username": "Existential_Coder", "email": "coder@example.com", "password": "my_eternal_suffering_123" }'
В ответ получим JSON с id нашего нового пользователя. Сохраним его.
2. Напишем пост от его имени:
curl -X 'POST' \ 'http://127.0.0.1:8000/posts/?user_id=...ВАШ_ID_ПОЛЬЗОВАТЕЛЯ...' \ -H 'Content-Type: application/json' \ -d '{ "title": "Ода рефакторингу", "content": "Вчера я 8 часов рефакторил код, который работал. Теперь он не работает, но зато красивый." }'
3. Посмотрим на всеобщее уныние:
curl -X 'GET' 'http://127.0.0.1:8000/posts/'
UPD: Добавил документацию для этого API, в котором можно посмотреть всю актуальную реализацию проекта. Это так же будет полезно для наших маленьких любителей подёргать ручки.
Вместо заключения
«Cynical Circle API» — это не просто набор эндпоинтов. Это мой маленький протест против унылых и безжизненных учебных материалов. Это инструмент, который позволяет моим ученикам не просто писать автотесты, но и делать это с улыбкой. Когда твой тест падает, потому что API ответил 404 с сообщением «Удалять нечего. Мир и так пуст», это запоминается лучше, чем безликий {"detail": "Not Found"}.
Проект абсолютно открыт. Берите, пользуйтесь, дорабатывайте. Добавляйте новые эндпоинты (например, комментарии, полные пассивной агрессии), расширяйте модели, меняйте тексты на еще более абсурдные.
Буду рад, если этот проект поможет кому-то сделать процесс обучения автоматизации тестирования чуть менее пресным и чуть более человечным.
Весь код доступен на GitHub.
Спасибо за внимание и всем релизов без багов на проде!
ссылка на оригинал статьи https://habr.com/ru/articles/937716/
Добавить комментарий