diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/tests.yml similarity index 84% rename from .github/workflows/integration-tests.yml rename to .github/workflows/tests.yml index 637d14f..199ba13 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/tests.yml @@ -1,7 +1,4 @@ -# This workflow will install Python dependencies, run tests and lint with a single version of Python -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python - -name: integration-tests +name: Tests on: push: @@ -42,11 +39,12 @@ jobs: uses: actions/setup-python@v5 with: python-version: "3.11" + cache: "pip" - name: Install dependencies run: | python -m pip install --upgrade pip - pip install pytest pytest-cov alembic + pip install pytest-cov if [ -f orders_service/requirements-dev.txt ]; then pip install -r orders_service/requirements-dev.txt; fi - name: Wait for Postgres @@ -60,7 +58,7 @@ jobs: # env: # DATABASE_URL: postgresql://test:test@localhost:5432/test_db - - name: Integration tests with pytest + - name: Tests with pytest run: | mkdir -p logs LOGFILE="logs/pytest-$(date +'%Y-%m-%d_%H%M%S').log" diff --git a/docker-compose.yml b/docker-compose.yml index 311d073..f2c0ec5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,7 +7,7 @@ services: POSTGRES_PASSWORD: ${DATABASE_PSWD} POSTGRES_DB: ${DATABASE_DB} ports: - - "15432:5432" + - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data healthcheck: @@ -31,11 +31,43 @@ services: depends_on: db: condition: service_healthy - + + # test: + test-db: + image: postgres:16-bookworm + profiles: ["test"] + env_file: + - ./.env.test + environment: + POSTGRES_USER: ${DATABASE_USER} + POSTGRES_PASSWORD: ${DATABASE_PASSWORD} + POSTGRES_DB: ${DATABASE_DB} + tmpfs: + - /var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U test1"] + interval: 5s + timeout: 5s + retries: 5 + + + orders_service_test: + profiles: ["test"] + build: + context: orders_service/ + target: test + dockerfile: ./Dockerfile + environment: + ENV: TEST + env_file: orders_service/.env.test + depends_on: + test-db: + condition: service_healthy volumes: postgres_data: + # analytics_service: # build: ./analytics_service # ports: diff --git a/orders_service/Dockerfile b/orders_service/Dockerfile index b0c6b87..5223a7d 100644 --- a/orders_service/Dockerfile +++ b/orders_service/Dockerfile @@ -21,9 +21,6 @@ FROM base AS dev COPY requirements-dev.txt . RUN pip install --no-cache-dir -r requirements-dev.txt -# COPY pytest.ini . -COPY tests ./tests/ - COPY alembic.ini . COPY alembic ./alembic @@ -31,6 +28,10 @@ ENV ENV=DEV # TEST FROM dev AS test + +# COPY pytest.ini . +COPY tests ./tests/ + RUN pip install --no-cache-dir pytest-cov ENV ENV=TEST @@ -38,5 +39,3 @@ ENV ENV=TEST FROM base AS prod ENV ENV=PROD - - diff --git a/orders_service/app/db_logic/crud.py b/orders_service/app/db_logic/crud.py index c5c9392..0421df2 100644 --- a/orders_service/app/db_logic/crud.py +++ b/orders_service/app/db_logic/crud.py @@ -34,7 +34,7 @@ def get_orders(db: Session, name: str | None = None, product: str | None = None) def delete_by_id(db: Session, order_id: int): try: - result = get_order_by_id(db, order_id) #catch for none? + result = get_order_by_id(db, order_id) if not result: return None db.delete(result) diff --git a/orders_service/app/main.py b/orders_service/app/main.py index d745e48..f4f80a4 100644 --- a/orders_service/app/main.py +++ b/orders_service/app/main.py @@ -10,7 +10,7 @@ def create_app(): ) @fastapi_app.get("/") async def root(): - return {"message": "Hello World"} + return {"message": "orders_service"} fastapi_app.include_router(orders.router) fastapi_app.include_router(health.router) diff --git a/orders_service/docker-entrypoint.sh b/orders_service/docker-entrypoint.sh index 07a1a14..90314de 100644 --- a/orders_service/docker-entrypoint.sh +++ b/orders_service/docker-entrypoint.sh @@ -11,11 +11,15 @@ if [ "$ENV" = "DEV" ]; then --reload elif [ "$ENV" = "TEST" ]; then echo "Running tests" - exec pytest /app/orders_service/tests --rootdir=/app + exec pytest /app/orders_service --rootdir=/app # exec pytest -v --cov=orders_service elif [ "$ENV" = "PROD" ]; then echo "PROD ENVIRONMENT" + # alembic upgrade head + exec uvicorn orders_service.app.main:app \ + --host 0.0.0.0 \ + --port 8000 exec uvicorn orders_service.app.main:app \ --host 0.0.0.0 \ --port 8000 diff --git a/orders_service/tests/conftest.py b/orders_service/tests/conftest.py new file mode 100644 index 0000000..158f0d6 --- /dev/null +++ b/orders_service/tests/conftest.py @@ -0,0 +1,60 @@ +import os + +os.environ.setdefault( + "DATABASE_URL", + "postgresql+psycopg://test1:test1@localhost:5432/orders_TEST" +) + +import pytest +from pathlib import Path +from alembic import command +from alembic.config import Config +from sqlalchemy import create_engine +from sqlalchemy.orm import Session, sessionmaker +from orders_service.tests.factories.order_factory import OrderFactory +from orders_service.app.core.config import settings +from orders_service.app.models.order import Order + + +@pytest.fixture(scope="session", autouse=True) +def migrate_db(): + base_dir = Path(__file__).resolve().parents[1] + alembic_path = base_dir / "alembic.ini" + + alembic_cfg = Config(str(alembic_path)) + # alembic_cfg = Config("orders_service/alembic.ini") + command.upgrade(alembic_cfg, "head") + print("[TEST] Database migrated") + + yield + + +engine = create_engine(settings.DATABASE_URL, pool_pre_ping=True) +TestingSession = sessionmaker( + autocommit=False, + autoflush=False, + bind=engine, +) + + +@pytest.fixture(scope="function", autouse=True) +def db(): + connection = engine.connect() + transaction = connection.begin() + session = TestingSession(bind=connection) + + yield session + + session.close() + transaction.rollback() + connection.close() + + +@pytest.fixture(autouse=True) +def set_session_for_factories(db: Session): + OrderFactory._meta.sqlalchemy_session = db + + +@pytest.fixture() +def fixture_order(db: Session): + return OrderFactory() diff --git a/orders_service/tests/factories/order_factory.py b/orders_service/tests/factories/order_factory.py index fe126ab..9e2bd38 100644 --- a/orders_service/tests/factories/order_factory.py +++ b/orders_service/tests/factories/order_factory.py @@ -1,5 +1,3 @@ -import random -from uuid import uuid4 import factory from orders_service.app.models import order @@ -8,9 +6,8 @@ class Meta: model = order.Order sqlalchemy_session_persistence = "flush" - id = uuid4 name = factory.Faker("name") - product = "item" - count = random.randint(1, 100) - price = print(round(random.uniform(1.00, 1000.0), 2)) + product = factory.Sequence(lambda n: 'item %d' % n) + count = factory.Faker("random_int", min=1, max=100) + price = factory.Faker("pyfloat", left_digits=3, right_digits=2, positive=True) \ No newline at end of file diff --git a/orders_service/tests/integration_tests/app_api_test.py b/orders_service/tests/integration_tests/app_api_test.py new file mode 100644 index 0000000..19877a2 --- /dev/null +++ b/orders_service/tests/integration_tests/app_api_test.py @@ -0,0 +1,8 @@ +from fastapi import status + +def test_root_endpoint(client): + response = client.get("/") + assert response.status_code == status.HTTP_200_OK + data = response.json() + assert "message" in data + assert data["message"] == "orders_service" diff --git a/orders_service/tests/integration_tests/app_test.py b/orders_service/tests/integration_tests/app_test.py deleted file mode 100644 index fcf6b0e..0000000 --- a/orders_service/tests/integration_tests/app_test.py +++ /dev/null @@ -1,26 +0,0 @@ -from fastapi import status - - - -def test_root_endpoint(client): - """Test the root endpoint returns the expected response.""" - response = client.get("/") - assert response.status_code == status.HTTP_200_OK - data = response.json() - # assert "app" in data - assert "message" in data - # assert data["app"] == "Databricks FastAPI Example" - -def test_isolation(client): - client.post("/order", json={ - "id": 1, - "name": "A", - "product": "B", - "count": 1, - "price": 10.0 - }) - -def test_no_leak(client): - response = client.get("/order/1") - assert response.status_code == 404 - \ No newline at end of file diff --git a/orders_service/tests/integration_tests/conftest.py b/orders_service/tests/integration_tests/conftest.py index e2d7bf1..f950dcc 100644 --- a/orders_service/tests/integration_tests/conftest.py +++ b/orders_service/tests/integration_tests/conftest.py @@ -1,47 +1,40 @@ -import os - -os.environ.setdefault( - "DATABASE_URL", - "postgresql+psycopg://test1:test1@localhost:5432/orders_TEST" -) - import pytest -from pathlib import Path -from alembic import command -from alembic.config import Config -from sqlalchemy import create_engine -from sqlalchemy.orm import sessionmaker, Session +# from pathlib import Path +# from alembic import command +# from alembic.config import Config +# from sqlalchemy import create_engine +from sqlalchemy.orm import Session, sessionmaker from fastapi.testclient import TestClient from orders_service.app.main import create_app -from ..factories.order_factory import OrderFactory -from orders_service.app.core.config import settings +# from ..factories.order_factory import OrderFactory +# from orders_service.app.core.config import settings from orders_service.app.dependencies.db import get_db -print("\n[TEST] SQLAlchemy settings.DATABASE_URL =", settings.DATABASE_URL) -# print("[TEST] Alembic sqlalchemy.url =", alembic_cfg.get_main_option("sqlalchemy.url")) +# print("\n[TEST] SQLAlchemy settings.DATABASE_URL =", settings.DATABASE_URL) + -#TODO: path change - alembic.ini -@pytest.fixture(scope="session", autouse=True) -def migrate_db(): - base_dir = Path(__file__).resolve().parents[2] - alembic_path = base_dir / "alembic.ini" +# #TODO: path change - alembic.ini +# @pytest.fixture(scope="session", autouse=True) +# def migrate_db(): +# base_dir = Path(__file__).resolve().parents[2] +# alembic_path = base_dir / "alembic.ini" - alembic_cfg = Config(str(alembic_path)) - # alembic_cfg = Config("orders_service/alembic.ini") - command.upgrade(alembic_cfg, "head") +# alembic_cfg = Config(str(alembic_path)) +# # alembic_cfg = Config("orders_service/alembic.ini") +# command.upgrade(alembic_cfg, "head") +# print("[TEST] Database migrated") - yield +# yield -print("\n[TEST] SQLAlchemy settings.DATABASE_URL =", settings.DATABASE_URL) -# print("[TEST] Alembic sqlalchemy.url =", alembic_cfg.get_main_option("sqlalchemy.url")) +# print("\n[TEST] SQLAlchemy settings.DATABASE_URL =", settings.DATABASE_URL) -#TODO: put in function? -engine = create_engine(settings.DATABASE_URL) -TestingSession = sessionmaker( - autocommit=False, - autoflush=False, - bind=engine, -) +# #TODO: put in function? +# engine = create_engine(settings.DATABASE_URL) +# TestingSession = sessionmaker( +# autocommit=False, +# autoflush=False, +# bind=engine, +# ) @pytest.fixture @@ -56,19 +49,19 @@ def override_get_db(): app.dependency_overrides.clear() -@pytest.fixture(scope="function", autouse=True) -def db(): - connection = engine.connect() - transaction = connection.begin() - session = TestingSession(bind=connection) +# @pytest.fixture(scope="function", autouse=True) +# def db(): +# connection = engine.connect() +# transaction = connection.begin() +# session = TestingSession(bind=connection) - yield session +# yield session - session.close() - transaction.rollback() - connection.close() +# session.close() +# transaction.rollback() +# connection.close() -@pytest.fixture(autouse=True) -def set_session_for_factories(db: Session): - OrderFactory._meta.sqlalchemy_session = db +# @pytest.fixture(autouse=True) +# def set_session_for_factories(db: Session): +# OrderFactory._meta.sqlalchemy_session = db diff --git a/orders_service/tests/integration_tests/health_test.py b/orders_service/tests/integration_tests/health_api_test.py similarity index 84% rename from orders_service/tests/integration_tests/health_test.py rename to orders_service/tests/integration_tests/health_api_test.py index c270d10..0f0319c 100644 --- a/orders_service/tests/integration_tests/health_test.py +++ b/orders_service/tests/integration_tests/health_api_test.py @@ -1,7 +1,6 @@ from fastapi import status def test_healthcheck(client): - """Test the healthcheck endpoint.""" response = client.get("/health") assert response.status_code == status.HTTP_200_OK data = response.json() @@ -10,7 +9,6 @@ def test_healthcheck(client): # assert "timestamp" in data def test_healthcheck_db(client): - """Test the healthcheck database endpoint.""" response = client.get("/health/db") assert response.status_code == status.HTTP_200_OK data = response.json() diff --git a/orders_service/tests/integration_tests/orders_api_test.py b/orders_service/tests/integration_tests/orders_api_test.py new file mode 100644 index 0000000..4260227 --- /dev/null +++ b/orders_service/tests/integration_tests/orders_api_test.py @@ -0,0 +1,147 @@ +from fastapi import status +from orders_service.tests.factories.order_factory import OrderFactory + +# def test_isolation(client): ? + + +def test_post_order_success(client): + response = client.post("/orders", json={ + "name": "test user", + "product": "test product", + "count": 2, + "price": 10.0 + }) + assert response.status_code == status.HTTP_201_CREATED + assert response.json()["name"] == "test user" + assert response.json()["total"] == 20.0 + +def test_post_order_invalid_payload(client): + response = client.post("/orders", json={ + "name": "test" + }) + + assert response.status_code == 422 + + + +def test_get_all(client): + OrderFactory.create_batch(2) + + response = client.get("/orders") + data = response.json() + + assert response.status_code == status.HTTP_200_OK + assert "items" in data + assert isinstance(data["items"], list) + assert len(data["items"]) == 2 + +def test_get_all_empty(client): + response = client.get("/orders") + assert response.status_code == status.HTTP_200_OK + assert response.json()["items"] == [] + +def test_get_by_name(client): + OrderFactory() + OrderFactory.create_batch(3, name="user") + + response = client.get("/orders/?name=user") + + assert response.status_code == status.HTTP_200_OK + + data = response.json() + assert isinstance(data["items"], list) + assert len(data["items"]) == 3 + assert all(order["name"] == "user" for order in data["items"]) + + +def test_get_by_product(client): + OrderFactory() + OrderFactory.create_batch(2, product="product") + + response = client.get("/orders?product=product") + + assert response.status_code == status.HTTP_200_OK + + data = response.json() + assert isinstance(data["items"], list) + assert len(data["items"]) == 2 + assert all(order["product"] == "product" for order in data["items"]) + +def test_get_by_all_filters(client): + target_name="target_customer" + target_product="target_product" + OrderFactory.create_batch(5, name="temp customer", product="temp product") + OrderFactory.create_batch(10, name=target_name, product="temp product 2") + OrderFactory.create_batch(12, name="temp customer 2", product=target_product) + OrderFactory.create_batch(6, name=target_name, product=target_product) + + response = client.get(f"/orders?name={target_name}&product={target_product}") + + assert response.status_code == status.HTTP_200_OK + + data = response.json() + assert isinstance(data["items"], list) + assert len(data["items"]) == 6 + assert all(order["name"] == target_name for order in data["items"]) + assert all(order["product"] == target_product for order in data["items"]) + +def test_get_by_filters_no_match(client): + target_name = "target_customer" + target_product = "target_product" + + OrderFactory.create_batch(5, name="temp customer", product="temp product") + OrderFactory.create_batch(10, name=target_name, product="temp product 2") + OrderFactory.create_batch(12, name="temp customer 2", product=target_product) + + response = client.get(f"/orders?name={target_name}&product={target_product}") + + assert response.status_code == status.HTTP_200_OK + + data = response.json() + assert isinstance(data["items"], list) + assert len(data["items"]) == 0 + +def test_get_by_id(client, fixture_order): + response = client.get(f"/orders/{fixture_order.id}") + assert response.status_code == status.HTTP_200_OK + data = response.json() + assert data['id'] == fixture_order.id + +def test_get_by_id_invalid_id(client, fixture_order): + response = client.get(f"/orders/{fixture_order.id + 1}") + + assert response.status_code == status.HTTP_404_NOT_FOUND + + + +def test_put_success(client, fixture_order): + response = client.put(f"/orders/{fixture_order.id}", json={"name": "new name"}) + assert response.status_code == status.HTTP_200_OK + data = response.json() + assert data["name"] == "new name" + +def test_put_invalid_id(client, fixture_order): + response = client.put(f"/orders/{fixture_order.id + 1}", json={"name": "new name"}) + assert response.status_code == status.HTTP_404_NOT_FOUND + +def test_put_invalid_data(client, fixture_order): + response = client.put(f"/orders/{fixture_order.id}", json={"name": "x"}) + assert response.status_code == status.HTTP_422_UNPROCESSABLE_CONTENT + + + +def test_delete_success(client, fixture_order): + response = client.delete(f"/orders/{fixture_order.id}") + + assert response.status_code == status.HTTP_204_NO_CONTENT + +def test_delete_persists(client, fixture_order): + client.delete(f"/orders/{fixture_order.id}") + + response = client.get(f"/orders/{fixture_order.id}") + assert response.status_code == 404 + +def test_delete_invalid(client, fixture_order): + response = client.delete(f"/orders/{fixture_order.id+1}") + + assert response.status_code == status.HTTP_404_NOT_FOUND diff --git a/orders_service/tests/crud/__init__.py b/orders_service/tests/unit/crud/__init__.py similarity index 100% rename from orders_service/tests/crud/__init__.py rename to orders_service/tests/unit/crud/__init__.py diff --git a/orders_service/tests/unit/crud/orders_table_test.py b/orders_service/tests/unit/crud/orders_table_test.py new file mode 100644 index 0000000..345ff2d --- /dev/null +++ b/orders_service/tests/unit/crud/orders_table_test.py @@ -0,0 +1,202 @@ +from sqlalchemy.orm import Session + +from orders_service.app.db_logic import crud +from orders_service.app.models.order import Order +from orders_service.app.schemas.order import OrderCreate, OrderUpdate +from orders_service.tests.factories.order_factory import OrderFactory + + +### CREATE TESTS ### +def test_create_order(db: Session) -> None: + data: Order = OrderFactory.build() + new_order = OrderCreate( + name=data.name, + product=data.product, + count=data.count, + price=data.price, + ) + + result = crud.create_order(db=db, new_order=new_order) + assert result.id is not None + assert result.name == data.name + +def test_created_order_persists_correctly(db: Session) -> None: + data: Order = OrderFactory.build() + new_order = OrderCreate( + name=data.name, + product=data.product, + count=data.count, + price=data.price, + ) + + result = crud.create_order(db=db, new_order=new_order) + stored = db.query(Order).filter(Order.id == result.id).first() + + assert stored is not None + assert stored.name == data.name + assert stored.product == data.product + assert stored.count == data.count + assert stored.price == data.price + + orders = db.query(Order).all() + assert len(orders) == 1 + + + +### RETRIEVE TESTS ### +def test_get_order_by_id(db: Session, fixture_order: Order) -> None: + stored_order = crud.get_order_by_id(db=db, order_id=fixture_order.id) + assert stored_order + assert fixture_order.id == stored_order.id + assert fixture_order.name == stored_order.name + +def test_get_order_by_id_not_found(db: Session) -> None: + OrderFactory.create_batch(5) + order = crud.get_order_by_id(db=db, order_id=9999) + assert order is None + +def test_get_orders_all(db: Session) -> None: + OrderFactory.create_batch(50) + retrieved_orders = crud.get_orders(db=db) + assert len(retrieved_orders) == 50 + +def test_get_orders_empty_db(db: Session) -> None: + retrieved_orders = crud.get_orders(db=db) + assert retrieved_orders == [] + +def test_get_orders_by_name(db: Session) -> None: + target = "target_customer" + OrderFactory.create_batch(15, name="buffer customer") + OrderFactory.create_batch(10, name=target) + + retrieved_orders = crud.get_orders(db=db, name=target) + assert len(retrieved_orders) == 10 + assert all(order.name == target for order in retrieved_orders) + +def test_get_orders_by_product(db: Session) -> None: + target = "target_product" + OrderFactory.create_batch(15, product="buffer product") + OrderFactory.create_batch(10, product=target) + + retrieved_orders = crud.get_orders(db=db, product=target) + assert len(retrieved_orders) == 10 + assert all(order.product == target for order in retrieved_orders) + +def test_get_orders_by_all_filters(db: Session) -> None: + target_name = "target_customer" + target_product = "target_product" + + OrderFactory.create_batch(5, name="temp customer", product="temp product") + OrderFactory.create_batch(10, name=target_name, product="temp product 2") + OrderFactory.create_batch(12, name="temp customer 2", product=target_product) + OrderFactory.create_batch(6, name=target_name, product=target_product) + + retrieved_orders = crud.get_orders(db=db, name=target_name, product=target_product) + assert len(retrieved_orders) == 6 + assert all(order.name == target_name for order in retrieved_orders) + assert all(order.product == target_product for order in retrieved_orders) + +def test_get_orders_by_filters_no_match(db: Session) -> None: + target_name = "target_customer" + target_product = "target_product" + + OrderFactory.create_batch(5, name="temp customer", product="temp product") + OrderFactory.create_batch(10, name=target_name, product="temp product 2") + OrderFactory.create_batch(12, name="temp customer 2", product=target_product) + + retrieved_orders = crud.get_orders(db=db, name=target_name, product=target_product) + assert retrieved_orders == [] + + + +### UPDATE TESTS ### +def test_update_order(db: Session) -> None: + order = OrderFactory(name="old name") + old_name = order.name + old_count = order.count + old_price = order.price + old_product = order.product + order_id = order.id + + updated_data = OrderUpdate(name="new name", count=old_count + 1) + result = crud.update_order(db, order_id=order_id, data=updated_data) + + assert result + assert result.id == order_id + assert result.name != old_name + assert result.name == "new name" + assert result.count == old_count + 1 + assert result.price == old_price + assert result.product == old_product + +def test_update_order_no_changes(db: Session) -> None: + order = OrderFactory() + old_name = order.name + old_count = order.count + old_price = order.price + old_product = order.product + order_id = order.id + + updated_data = OrderUpdate() + result = crud.update_order(db, order_id=order_id, data=updated_data) + + assert result + assert result.id == order_id + assert result.name == old_name + assert result.count == old_count + assert result.price == old_price + assert result.product == old_product + +def test_update_order_invalid_id(db: Session) -> None: + OrderFactory.create_batch(5) + data = OrderUpdate() + result = crud.update_order(db, order_id=9999, data=data) + assert not result + +def test_update_order_row_count_unchanged(db: Session): + db_list = OrderFactory.create_batch(5, name="old name") + updated_data = OrderUpdate(name="updated") + result = crud.update_order(db, order_id=db_list[0].id, data=updated_data) + + assert result + count = db.query(Order).count() + assert count == 5 + +def test_update_persists_changes(db: Session): + order = OrderFactory() + updated_data = OrderUpdate(name="persisted") + + crud.update_order(db, order_id=order.id, data=updated_data) + stored = db.query(Order).filter(Order.id == order.id).first() + + assert stored.name == "persisted" + + + +### DELETE TESTS ### +def test_delete_by_id(db: Session, fixture_order: Order) -> None: + result = crud.delete_by_id(db, order_id=fixture_order.id) + assert result + assert result.id == fixture_order.id + + deleted = db.query(Order).filter(Order.id == fixture_order.id).first() + assert deleted is None + +def test_delete_by_id_not_found(db: Session) -> None: + OrderFactory.create_batch(5) + order = crud.delete_by_id(db=db, order_id=9999) + assert order is None + +def test_delete_reduces_row_count(db: Session): + OrderFactory.create_batch(5) + order = db.query(Order).first() + crud.delete_by_id(db, order.id) + + remaining = db.query(Order).count() + assert remaining == 4 + +def test_delete_same_id_twice(db: Session, fixture_order: Order): + crud.delete_by_id(db, fixture_order.id) + result = crud.delete_by_id(db, fixture_order.id) + + assert result is None diff --git a/orders_service/tests/unit/schemas/__init__.py b/orders_service/tests/unit/schemas/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/orders_service/tests/unit/schemas/order_schemas_test.py b/orders_service/tests/unit/schemas/order_schemas_test.py new file mode 100644 index 0000000..932a8e1 --- /dev/null +++ b/orders_service/tests/unit/schemas/order_schemas_test.py @@ -0,0 +1,40 @@ +import pytest +from pydantic import ValidationError +from orders_service.app.schemas import order + + +def test_order_create_invalid_name(): + with pytest.raises(ValidationError): + order.OrderCreate( + name="", + product="apple", + count=1, + price=5.0, + ) + +def test_order_create_invalid_product(): + with pytest.raises(ValidationError): + order.OrderCreate( + name="test1", + product="a", + count=1, + price=5.0, + ) + +def test_order_create_invalid_count(): + with pytest.raises(ValidationError): + order.OrderCreate( + name="test1", + product="a", + count=0, + price=5.0, + ) + +def test_order_create_invalid_price(): + with pytest.raises(ValidationError): + order.OrderCreate( + name="test1", + product="a", + count=1, + price=-5.0, + )