From b3509d698d844782fa8867b3c1851b37d0c14e4a Mon Sep 17 00:00:00 2001 From: pi3c Date: Mon, 5 Feb 2024 23:14:23 +0300 Subject: [PATCH] fix --- Dockerfile | 4 +- README.md | 124 ++++++---------------------------------------- compose_app.yml | 3 ++ tests/conftest.py | 2 +- tests/urls.py | 7 +++ 5 files changed, 28 insertions(+), 112 deletions(-) diff --git a/Dockerfile b/Dockerfile index dc34eac..54cdab7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,9 +8,9 @@ RUN mkdir -p /usr/src/fastfood WORKDIR /usr/src/fastfood -COPY ./pyproject.toml . +COPY . . -COPY ./poetry.lock . +COPY ./example.env ./.env RUN touch /usr/src/RUN_IN_DOCKER diff --git a/README.md b/README.md index 04456a3..87ef887 100644 --- a/README.md +++ b/README.md @@ -5,78 +5,31 @@ Fastapi веб приложение реализующее api для общеп Данный проект, это результат выполнения практических домашних заданий интенсива от YLAB Development. Проект реализован на фреймворке fastapi, с использованием sqlalchemy. В качестве базы данных используется postgresql. ## Техническое задание -### Спринт 1 - Создание API -Написать проект на FastAPI с использованием PostgreSQL в качестве БД. В проекте следует реализовать REST API по работе с меню ресторана, все CRUD операции. Для проверки задания, к презентаций будет приложена Postman коллекция с тестами. Задание выполнено, если все тесты проходят успешно. -Даны 3 сущности: Меню, Подменю, Блюдо. +### Спринт 3 - Паттерны и принципы разработки -Зависимости: -- У меню есть подменю, которые к ней привязаны. -- У подменю есть блюда. +1.Вынести бизнес логику и запросы в БД в отдельные слои приложения. -Условия: -- Блюдо не может быть привязано напрямую к меню, минуя подменю. -- Блюдо не может находиться в 2-х подменю одновременно. -- Подменю не может находиться в 2-х меню одновременно. -- Если удалить меню, должны удалиться все подменю и блюда этого меню. -- Если удалить подменю, должны удалиться все блюда этого подменю. -- Цены блюд выводить с округлением до 2 знаков после запятой. -- Во время выдачи списка меню, для каждого меню добавлять кол-во подменю и блюд в этом меню. -- Во время выдачи списка подменю, для каждого подменю добавлять кол-во блюд в этом подменю. -- Во время запуска тестового сценария БД должна быть пуста. +2.Добавить кэширование запросов к API с использованием Redis. Не забыть про инвалидацию кэша. -В папке ./postman_scripts находятся фалы тестов Postman, для тестирования функционала проекта. +3.Добавить pre-commit хуки в проект. Файл yaml будет прикреплен к ДЗ. -### Спринт 2 - Docker && pytest -В этом домашнем задании надо написать тесты для ранее разработанных ендпоинтов вашего API после Вебинара №1. +4.Покрыть проект type hints (тайпхинтами) -Обернуть программные компоненты в контейнеры. Контейнеры должны запускаться по одной команде “docker-compose up -d” или той которая описана вами в readme.md. +5.* Описать ручки API в соответствий c OpenAPI -Образы для Docker: -(API) python:3.10-slim -(DB) postgres:15.1-alpine +6.** Реализовать в тестах аналог Django reverse() для FastAPI -1.Написать CRUD тесты для ранее разработанного API с помощью библиотеки pytest -2.Подготовить отдельный контейнер для запуска тестов. Команду для запуска указать в README.md -3.* Реализовать вывод количества подменю и блюд для Меню через один (сложный) ORM запрос. -4.** Реализовать тестовый сценарий «Проверка кол-ва блюд и подменю в меню» из Postman с помощью pytest -Если FastAPI синхронное - тесты синхронные, Если асинхронное - тесты асинхронные +Требования: +●Код должен проходить все линтеры. +●Код должен соответствовать принципам SOLID, DRY, KISS. +●Проект должен запускаться по одной команде (докер). +●Проект должен проходить все Postman тесты (коллекция с Вебинара №1). +●Тесты написанные вами после Вебинара №2, должны быть актуальны, запускать и успешно проходить - -*Оборачиваем приложение в докер. -**CRUD – create/update/retrieve/delete. - -Дополнительные материалы - -## Возможности -### Спринт 1 -В проекте реализованы 3 сущности: Menu, SubMenu и Dish. Для каждого них реализованы 4 метода http запросов: GET, POST, PATCH и DELETE c помощью которых можно управлять данными. -Для Menu доступен метод GET возвращающий все его SubMenu. Аналогично для SubMenu реализован метод для возврата всех Dish. - -### Спринт 2 -- 1й пункт ТЗ -Тесты реализованы в виде 2х классов -`TastBaseCrud` включает 3 подкласса `Menu`, `Submenu`, `Dish` которые реализуют интерфейсы взаимодействия с endpoint'ами реализованных на предыдущем спринте сущностей. Каждый подкласс реализует методы GET(получение всех сущностей), Get(получение конкректной сущности), Post(создание), Patch(обновление), Delete(удаления). Так же в классе реализованы 3 тестовых функции, которые осуществляют тестирование соответствующих endpoint'ов -`TestContinuity` реализует последовательность сценария «Проверка кол-ва блюд и подменю в меню» из Postman - -- 2й пункт ТЗ -Реализованы 3 контейнера(db, app, tests). В db написан блок "проверки здоровья", от которого зависят контейнеры app и test, который гарантирует, что зависимые контейнеры не будут запущены о полной готовности db. - -- 3й пункт ТЗ -см. функцию `get_menu_item` на 28 строке в файле -/fastfood/crud/menu.py - -- 4й пункт ТЗ -см. класс `TestContinuity` в файле -/tests/test_api.py +Дополнительно: +Контейнеры с проектом и с тестами запускаются разными командами. ## Зависимости -Для локальной установки -- postgresql Для работы сервиса необходима установленная СУБД. Должна быть создана база данных и пользователь с правами на нее. -- poetry - Система управления зависимостями в Python. - -Остальное добавится автоматически на этапе установки. - -Для запуска в контейнере - docker - docker-compose @@ -88,14 +41,6 @@ Fastapi веб приложение реализующее api для общеп Перейдите в каталог > `$ cd fastfood` -Создадим файл .env из шаблона ->`$ cp ./example.env ./.env` - -Если планируется запуск проекта в Docker контейнере, то `.env` можно не изменять. Если запуск будет локальным, то необходимо изменить переменные окружения, для подключения к БД postgres. - -### Docker -Для запуска необходимы установленные приложения docker и docker-compose - Запуск/остановка образов: - Запуск FAstAPI приложения @@ -113,48 +58,9 @@ Fastapi веб приложение реализующее api для общеп > `$ docker-compose -f compose_test.yml down` -### Linux -Установите и настройте postgresql согласно офф. документации. Создайте пользователя и бд. - -Установите систему управления зависимостями -> `$ pip[x] install poetry` - -Клонируйте репозиторий -> `$ git clone https://git.pi3c.ru/pi3c/fastfood.git` - -Перейдите в каталог - -> `$ cd fastfood` - -> `$ poetry install --no-root` - -Создастся виртуальное окружение и установятся зависимости - -## Запуск -Запуск проекта возможен в 2х режимах: -- Запуск в режиме "prod" с ключем --run-server - Подразумевает наличие уже созданных таблиц в базе данных(например с помощью Alembic). Манипуляций со структурой БД не происходит. Данные не удаляются. - -- Запуск в режиме "dev" c ключем --run-test-server - В этом случае при каждом запуске проекта все таблицы с данными удаляются из БД и создаются снова согласно описанных моделей. - - -Для запуска проекта сначала активируем виртуальное окружение - -> `$ poetry shell` - -и запускаем проект в соответстующем режиме - ->`$ python[x] manage.py --ключ` - -вместо этого, так же допускается и другой вариант запуска одной командой без предварительной активации окружения - ->`$ poetry run python[x] manage.py --ключ` - ## TODO - Написать тесты для кривых данных -- Провести рефакторинг, много дублирующего кода - Много чего другого :) ## Авторы diff --git a/compose_app.yml b/compose_app.yml index a8ad9a8..3d9007a 100644 --- a/compose_app.yml +++ b/compose_app.yml @@ -55,6 +55,9 @@ services: redis: condition: service_healthy + volumes: + - .:/usr/src/fastfood + restart: always command: /bin/bash -c 'poetry run python /usr/src/fastfood/manage.py --run-test-server' diff --git a/tests/conftest.py b/tests/conftest.py index f5d3c60..e64f40a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -45,7 +45,7 @@ async def get_test_session() -> AsyncGenerator[AsyncSession, None]: yield session -@pytest_asyncio.fixture(scope='session') +@pytest_asyncio.fixture(scope='session', autouse=True) async def client(event_loop) -> AsyncGenerator[AsyncClient, None]: app: FastAPI = create_app() app.dependency_overrides[get_async_session] = get_test_session diff --git a/tests/urls.py b/tests/urls.py index bc16268..169912f 100644 --- a/tests/urls.py +++ b/tests/urls.py @@ -2,17 +2,24 @@ def reverse_url(loc: str, **kwargs) -> str: menu_pref = '/' submenu_pref = menu_pref + str(kwargs.get('menu_id', '')) + '/submenus/' dish_pref = submenu_pref + str(kwargs.get('submenu_id', '')) + '/dishes/' + match loc: case 'menus': return menu_pref + case 'menu': return menu_pref + str(kwargs.get('menu_id', '')) + case 'submenus': return submenu_pref + case 'submenu': return submenu_pref + str(kwargs.get('submenu_id', '')) + case 'dishes': return dish_pref + case 'dish': return dish_pref + str(kwargs.get('dish_id', '')) + return menu_pref