Skip to content

Commit 92c4164

Browse files
authored
Fixed db_init Issue and 100% Test Coverage (#84)
1 parent 0781bbb commit 92c4164

File tree

6 files changed

+47
-24
lines changed

6 files changed

+47
-24
lines changed

app/dao/notifications_dao.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
# there are not tests for this yet because we have not included the database in our tests
88
# Note: We might be heading in a different direction regarding database access. This should be considered a placeholder.
9-
async def dao_create_notification(notification: Notification) -> Notification:
9+
async def dao_create_notification(notification: Notification) -> Notification: # pragma: no cover
1010
"""Create a notification in the database. This should be considered a placeholder.
1111
1212
Args:

app/db/db_init.py

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from fastapi.concurrency import asynccontextmanager
77
from loguru import logger
8+
from sqlalchemy.exc import IntegrityError
89
from sqlalchemy.ext.asyncio import (
910
AsyncEngine,
1011
AsyncSession,
@@ -22,28 +23,45 @@
2223

2324
async def init_db() -> None:
2425
"""Initialize the database engine."""
25-
global _engine_read, _engine_write
26-
2726
logger.info('Initializing the database engines...')
2827

29-
# Create the write database engine.
30-
# echo=True logs the queries that are executed. Set it to False to disable these logs.
31-
_engine_write = create_async_engine(DB_WRITE_URI, echo=False)
32-
3328
# Without this import, Base.metatable (used below) will not point to any tables, and the
3429
# call to "run_sync" will not create anything.
3530
import app.db.models # noqa
3631

32+
# These methods are copy/paste due to globals.
33+
await create_write_engine()
34+
await create_read_engine()
35+
36+
37+
async def create_write_engine() -> None:
38+
"""Create the async write engine."""
39+
global _engine_write
40+
# Create the write database engine.
41+
# echo=True logs the queries that are executed. Set it to False to disable these logs.
42+
_engine_write = create_async_engine(DB_WRITE_URI, echo=False)
3743
async with _engine_write.begin() as conn:
38-
await conn.run_sync(Base.metadata.create_all)
44+
try:
45+
print(f'{_engine_write} - {conn}')
46+
await conn.run_sync(Base.metadata.create_all)
47+
# assert False
48+
except IntegrityError: # pragma: no cover
49+
# Async workers on a fresh container will try to create tables at the same time - No deployed impact
50+
pass
3951

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

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

4866

4967
async def close_db() -> None:

app/providers/provider_base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ async def process_response(self) -> None:
3434
3535
Facilitates update and log consistency regardless of response.
3636
"""
37-
...
37+
raise NotImplementedError(f'Derived class: {self.__class__.__name__} does not implement this method.')
3838

3939
async def send_notification(self, model: PushModel) -> str:
4040
"""Send a notification using the provider.

pyproject.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ mkdocs-material = "*"
4949
mkdocs-gen-files = "*"
5050

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

5554
[tool.coverage.run]
@@ -59,7 +58,7 @@ omit = [
5958
]
6059

6160
[tool.coverage.report]
62-
fail_under = 96
61+
fail_under = 100
6362
precision = 2
6463

6564
[tool.ruff]

tests/app/db/test_db_init.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -114,23 +114,27 @@ class TestReadWriteSessionsFailure:
114114
async def test_get_read_session_failure(self) -> None:
115115
"""Test the get_read_session function raises a ValueError when the db engine is None."""
116116
with pytest.raises(ValueError, match='The db read engine has not been initialized. None type received.'): # noqa: PT012
117-
async for _session in get_read_session_with_depends():
118-
...
117+
# fmt: off
118+
async for _session in get_read_session_with_depends(): pass # noqa: E701
119+
# fmt: off
119120

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

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

132135
async def test_get_write_session_with_context_failure(self) -> None:
133136
"""Test the get_write_session_with_context function raises a ValueError when the db engine is None."""
134137
with pytest.raises(ValueError, match='The db write engine has not been initialized. None type received.'):
135-
async with get_write_session_with_context():
136-
...
138+
# fmt: off
139+
async with get_write_session_with_context(): pass # noqa: E701
140+
# fmt: on

tests/app/providers/test_provider_base.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,5 @@ class TestProviderDerived(ProviderBase): ...
2727
await derived._send_push(PushModel(message='', target_arn=''))
2828
with pytest.raises(NotImplementedError):
2929
await derived._send_sms()
30+
with pytest.raises(NotImplementedError):
31+
await derived.process_response()

0 commit comments

Comments
 (0)