Skip to content

Commit

Permalink
Fixed db_init Issue and 100% Test Coverage (#84)
Browse files Browse the repository at this point in the history
  • Loading branch information
k-macmillan authored Nov 29, 2024
1 parent 0781bbb commit 92c4164
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 24 deletions.
2 changes: 1 addition & 1 deletion app/dao/notifications_dao.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

# there are not tests for this yet because we have not included the database in our tests
# Note: We might be heading in a different direction regarding database access. This should be considered a placeholder.
async def dao_create_notification(notification: Notification) -> Notification:
async def dao_create_notification(notification: Notification) -> Notification: # pragma: no cover
"""Create a notification in the database. This should be considered a placeholder.
Args:
Expand Down
42 changes: 30 additions & 12 deletions app/db/db_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from fastapi.concurrency import asynccontextmanager
from loguru import logger
from sqlalchemy.exc import IntegrityError
from sqlalchemy.ext.asyncio import (
AsyncEngine,
AsyncSession,
Expand All @@ -22,28 +23,45 @@

async def init_db() -> None:
"""Initialize the database engine."""
global _engine_read, _engine_write

logger.info('Initializing the database engines...')

# Create the write database engine.
# echo=True logs the queries that are executed. Set it to False to disable these logs.
_engine_write = create_async_engine(DB_WRITE_URI, echo=False)

# Without this import, Base.metatable (used below) will not point to any tables, and the
# call to "run_sync" will not create anything.
import app.db.models # noqa

# These methods are copy/paste due to globals.
await create_write_engine()
await create_read_engine()


async def create_write_engine() -> None:
"""Create the async write engine."""
global _engine_write
# Create the write database engine.
# echo=True logs the queries that are executed. Set it to False to disable these logs.
_engine_write = create_async_engine(DB_WRITE_URI, echo=False)
async with _engine_write.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
try:
print(f'{_engine_write} - {conn}')
await conn.run_sync(Base.metadata.create_all)
# assert False
except IntegrityError: # pragma: no cover
# Async workers on a fresh container will try to create tables at the same time - No deployed impact
pass

if DB_READ_URI:
# Create the read database engine.
# echo=True logs the queries that are executed. Set it to False to disable these logs.
_engine_read = create_async_engine(DB_READ_URI, echo=False)

async with _engine_read.begin() as conn:
async def create_read_engine() -> None:
"""Create the async read engine."""
global _engine_read
# Create the read database engine.
# echo=True logs the queries that are executed. Set it to False to disable these logs.
_engine_read = create_async_engine(DB_READ_URI, echo=False)
async with _engine_read.begin() as conn:
try:
await conn.run_sync(Base.metadata.create_all)
except IntegrityError: # pragma: no cover
# Async workers on a fresh container will try to create tables at the same time - No deployed impact
pass


async def close_db() -> None:
Expand Down
2 changes: 1 addition & 1 deletion app/providers/provider_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ async def process_response(self) -> None:
Facilitates update and log consistency regardless of response.
"""
...
raise NotImplementedError(f'Derived class: {self.__class__.__name__} does not implement this method.')

async def send_notification(self, model: PushModel) -> str:
"""Send a notification using the provider.
Expand Down
3 changes: 1 addition & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ mkdocs-material = "*"
mkdocs-gen-files = "*"

[tool.bandit]
exclude_dirs = ["tests"]
skips = ["B101"] # https://bandit.readthedocs.io/en/latest/plugins/b101_assert_used.html

[tool.coverage.run]
Expand All @@ -59,7 +58,7 @@ omit = [
]

[tool.coverage.report]
fail_under = 96
fail_under = 100
precision = 2

[tool.ruff]
Expand Down
20 changes: 12 additions & 8 deletions tests/app/db/test_db_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,23 +114,27 @@ class TestReadWriteSessionsFailure:
async def test_get_read_session_failure(self) -> None:
"""Test the get_read_session function raises a ValueError when the db engine is None."""
with pytest.raises(ValueError, match='The db read engine has not been initialized. None type received.'): # noqa: PT012
async for _session in get_read_session_with_depends():
...
# fmt: off
async for _session in get_read_session_with_depends(): pass # noqa: E701
# fmt: off

async def test_get_read_session_with_context_failure(self) -> None:
"""Test the get_read_session_with_context function raises a ValueError when the db engine is None."""
with pytest.raises(ValueError, match='The db read engine has not been initialized. None type received.'):
async with get_read_session_with_context():
...
# fmt: off
async with get_read_session_with_context(): pass # noqa: E701
# fmt: on

async def test_get_write_session_failure(self) -> None:
"""Test the get_write_session function raises a ValueError when the db engine is None."""
with pytest.raises(ValueError, match='The db write engine has not been initialized. None type received.'): # noqa: PT012
async for _session in get_write_session_with_depends():
...
# fmt: off
async for _session in get_write_session_with_depends(): pass # noqa: E701
# fmt: on

async def test_get_write_session_with_context_failure(self) -> None:
"""Test the get_write_session_with_context function raises a ValueError when the db engine is None."""
with pytest.raises(ValueError, match='The db write engine has not been initialized. None type received.'):
async with get_write_session_with_context():
...
# fmt: off
async with get_write_session_with_context(): pass # noqa: E701
# fmt: on
2 changes: 2 additions & 0 deletions tests/app/providers/test_provider_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,5 @@ class TestProviderDerived(ProviderBase): ...
await derived._send_push(PushModel(message='', target_arn=''))
with pytest.raises(NotImplementedError):
await derived._send_sms()
with pytest.raises(NotImplementedError):
await derived.process_response()

0 comments on commit 92c4164

Please sign in to comment.