From 3cda5811cd9938d9ca22b81554ac0010a88f28dc Mon Sep 17 00:00:00 2001 From: grillazz Date: Wed, 2 Feb 2022 12:55:26 +0100 Subject: [PATCH] for AsyncEngine created in function scope, close and clean-up pooled connections adding await engine.dispose() --- Makefile | 8 ++++---- Pipfile.lock | 9 ++++++--- docker-compose.test.yml | 11 +++++++++++ pytest.ini | 1 + tests/conftest.py | 33 ++++----------------------------- the_app/config.py | 2 -- the_app/database.py | 3 +++ 7 files changed, 29 insertions(+), 38 deletions(-) create mode 100644 docker-compose.test.yml diff --git a/Makefile b/Makefile index e4a093c..78a7a6b 100644 --- a/Makefile +++ b/Makefile @@ -10,9 +10,9 @@ build: ## Build project with compose up: ## Run project with compose docker-compose up --remove-orphans -.PHONY: down -down: ## Reset project containers with compose - docker-compose down +.PHONY: clean +clean: ## Clean Reset project containers with compose + docker-compose down -v --remove-orphans .PHONY: lock lock: ## Refresh pipfile.lock @@ -24,7 +24,7 @@ requirements: ## Refresh requirements.txt from pipfile.lock .PHONY: test test: ## Run project tests - docker-compose run --rm app pytest + docker-compose -f docker-compose.yml -f docker-compose.test.yml run --rm app pytest .PHONY: safety safety: ## Check project and dependencies with safety https://github.com/pyupio/safety diff --git a/Pipfile.lock b/Pipfile.lock index 0fc4c7a..2002203 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "628f478121edd35aa12ccc88be545920a333b3a9b3f427de1feb55d26f2bffc7" + "sha256": "285d79d1ea6cc1173f0db1f9369ab590f6287d79c63c50e0cc086f52ef8289f9" }, "pipfile-spec": 6, "requires": { @@ -637,6 +637,9 @@ "version": "==1.2.0" }, "sqlalchemy": { + "extras": [ + "asyncio" + ], "hashes": [ "sha256:05fa14f279d43df68964ad066f653193187909950aa0163320b728edfc400167", "sha256:0ddc5e5ccc0160e7ad190e5c61eb57560f38559e22586955f205e537cda26034", @@ -889,7 +892,7 @@ "sha256:1fe43e3e9acf3a7c0f6b88f5338cad37044d2f156c43cb6b080b5f9da8a76f06", "sha256:20fa2a8ca2decac50116edb42e6af0a1253ef639ad79941249b840531889c65a" ], - "markers": "python_version >= '3.6' and python_version < '4.0'", + "markers": "python_version >= '3.6' and python_version < '4'", "version": "==1.3.2" }, "icecream": { @@ -1260,7 +1263,7 @@ "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed", "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4.0'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", "version": "==1.26.8" }, "wcwidth": { diff --git a/docker-compose.test.yml b/docker-compose.test.yml new file mode 100644 index 0000000..ebe97b9 --- /dev/null +++ b/docker-compose.test.yml @@ -0,0 +1,11 @@ +version: '3' + +services: + app: + environment: + - SQL_DB=testdb + + db: + environment: + - POSTGRES_USER=${SQL_USER} + - SQL_DB=testdb \ No newline at end of file diff --git a/pytest.ini b/pytest.ini index 0261ac6..1ec3b3a 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,4 +1,5 @@ [pytest] +asyncio_mode=strict python_files = tests.py test_*.py *_tests.py addopts = --cov=. --cov-report html:htmlcov diff --git a/tests/conftest.py b/tests/conftest.py index a844f3a..23a0dd1 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,14 +1,8 @@ import pytest from httpx import AsyncClient -from sqlalchemy.exc import SQLAlchemyError -from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine -from sqlalchemy.orm import sessionmaker -from sqlalchemy.pool import NullPool - -from the_app import config -from the_app.database import get_db from the_app.main import app from the_app.models.base import Base +from the_app.database import engine @pytest.fixture( @@ -20,32 +14,13 @@ def anyio_backend(request): return request.param -global_settings = config.get_settings() -url = global_settings.asyncpg_test_url -engine = create_async_engine(url, poolclass=NullPool, future=True) - -async_session = sessionmaker(engine, expire_on_commit=False, class_=AsyncSession) - - -async def get_test_db(): - session = async_session() - try: - yield session - await session.commit() - except SQLAlchemyError as ex: - await session.rollback() - raise ex - finally: - await session.close() - - -app.dependency_overrides[get_db] = get_test_db - - async def start_db(): async with engine.begin() as conn: await conn.run_sync(Base.metadata.drop_all) await conn.run_sync(Base.metadata.create_all) + # for AsyncEngine created in function scope, close and + # clean-up pooled connections + await engine.dispose() @pytest.fixture diff --git a/the_app/config.py b/the_app/config.py index 280b497..116b3b4 100644 --- a/the_app/config.py +++ b/the_app/config.py @@ -31,9 +31,7 @@ class Settings(BaseSettings): pg_pass: str = os.getenv("POSTGRES_PASSWORD", "") pg_host: str = os.getenv("SQL_HOST", "") pg_database: str = os.getenv("SQL_DB", "") - pg_test_database: str = os.getenv("SQL_TEST_DB", "") asyncpg_url: str = f"postgresql+asyncpg://{pg_user}:{pg_pass}@{pg_host}:5432/{pg_database}" - asyncpg_test_url: str = f"postgresql+asyncpg://{pg_user}:{pg_pass}@{pg_host}:5432/{pg_test_database}" jwt_secret_key: str = os.getenv("SECRET_KEY", "") jwt_algorithm: str = os.getenv("ALGORITHM", "") diff --git a/the_app/database.py b/the_app/database.py index 3a3d02e..05e9487 100644 --- a/the_app/database.py +++ b/the_app/database.py @@ -31,3 +31,6 @@ async def get_db() -> AsyncGenerator: raise ex finally: await session.close() + # for AsyncEngine created in function scope, close and + # clean-up pooled connections + await engine.dispose()