Skip to content

Commit 9c38fbb

Browse files
committed
add infra tests
1 parent c4870ce commit 9c38fbb

File tree

6 files changed

+221
-0
lines changed

6 files changed

+221
-0
lines changed

tests/infrastructure/__init__.py

Whitespace-only changes.

tests/infrastructure/api.py

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import pytest
2+
from fastapi import HTTPException, status
3+
4+
from src.infrastructure.api import ExceptionHandler
5+
from src.infrastructure.exceptions import Exc
6+
7+
8+
class TestExceptionHandler:
9+
@pytest.fixture(scope="function")
10+
def exceptions(self) -> dict[type[Exc], HTTPException]:
11+
return {Exc: HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="detail")}
12+
13+
async def test_exception_handler(self, exceptions: dict[type[Exc], HTTPException]) -> None:
14+
with pytest.raises(HTTPException):
15+
async with ExceptionHandler(exceptions=exceptions):
16+
raise Exc()

tests/infrastructure/email.py

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import pytest
2+
3+
from src.infrastructure.email import HTMLPage, Templater, TemplateSyntaxError
4+
5+
6+
class TestTemplater:
7+
@pytest.fixture(scope="function")
8+
def html_template(self) -> HTMLPage:
9+
return HTMLPage("<html><p>{{param1}}</p><p>{{param2}}</p></html>")
10+
11+
async def test_templater(self, html_template: HTMLPage):
12+
async with Templater() as templater:
13+
response = await templater.parse(html_page=html_template, param1="value1", param2="value2")
14+
15+
assert isinstance(response, HTMLPage)
16+
assert response == HTMLPage("<html><p>value1</p><p>value2</p></html>")
17+
18+
with pytest.raises(TemplateSyntaxError):
19+
async with Templater() as templater:
20+
await templater.parse(html_page=HTMLPage("<html>{{param1</html"), param1="value1", param2="value2")
21+
22+
23+
class TestSMTPSessionMixin:
24+
async def test_send_email(self, message: HTMLPage, recipient: str, subject: str) -> None:
25+
...

tests/infrastructure/pages.py

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import pytest
2+
3+
from src.infrastructure.pages import get_page, get_has_previous, get_has_next
4+
5+
6+
class TestPagination:
7+
@pytest.fixture(scope="function")
8+
def start(self) -> int:
9+
return 20
10+
11+
@pytest.fixture(scope="function")
12+
def size(self) -> int:
13+
return 10
14+
15+
@pytest.fixture(scope="function")
16+
def total(self) -> int:
17+
return 100
18+
19+
@pytest.mark.parametrize(
20+
"size,expected_value",
21+
[
22+
(10, 3),
23+
(3, 7),
24+
(30, 2),
25+
]
26+
)
27+
def test_get_page(self, start: int, size: int, expected_value: int) -> None:
28+
assert get_page(start, size) == expected_value
29+
30+
@pytest.mark.parametrize(
31+
"start,expected_value",
32+
[
33+
(1, False),
34+
(2, True),
35+
]
36+
)
37+
def test_get_has_previous(self, start: int, expected_value: bool) -> None:
38+
assert get_has_previous(start) is expected_value
39+
40+
@pytest.mark.parametrize(
41+
"size,expected_value",
42+
[
43+
(200, False),
44+
(4, True),
45+
]
46+
)
47+
def test_get_has_next(self, total: int, start: int, size: int, expected_value: bool) -> None:
48+
assert get_has_next(total, start, size) is expected_value

tests/infrastructure/postgres.py

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
from types import NoneType
2+
from typing import Literal
3+
4+
import pytest
5+
from sqlalchemy import Executable, select
6+
7+
from src.app.social.tags.models import Tag
8+
from src.infrastructure.postgres import PostgresSessionMixin
9+
10+
11+
@pytest.mark.infrastructure
12+
@pytest.mark.postgres
13+
class TestPostgresSessionMixin:
14+
@pytest.fixture(scope="function")
15+
def mixin(self) -> PostgresSessionMixin:
16+
return PostgresSessionMixin(table=Tag)
17+
18+
@pytest.fixture(scope="function")
19+
def obj_id(self) -> int:
20+
return 1
21+
22+
@pytest.fixture(scope="function")
23+
def statement(self, obj_id: int) -> Executable:
24+
return select(Tag).filter(Tag.id == obj_id)
25+
26+
async def test_create(self, obj: Tag, mixin: PostgresSessionMixin) -> None:
27+
async with mixin as session:
28+
await session.create(obj)
29+
30+
@pytest.mark.parametrize(
31+
"obj_id,expected_type",
32+
[(1, Tag), (100, NoneType)]
33+
)
34+
async def test_read(
35+
self,
36+
obj_id: int,
37+
mixin: PostgresSessionMixin,
38+
expected_type: type,
39+
) -> None:
40+
async with mixin as session:
41+
response = await session.read(obj_id=obj_id)
42+
assert isinstance(response, expected_type)
43+
44+
async def test_update(self, obj: Tag, mixin: PostgresSessionMixin) -> None:
45+
async with mixin as session:
46+
await session.update(obj)
47+
48+
async def test_delete(self, obj_id: int, mixin: PostgresSessionMixin) -> None:
49+
async with mixin as session:
50+
await session.delete_(obj_id=obj_id)
51+
52+
@pytest.mark.parametrize(
53+
"method,expected_type",
54+
[
55+
("scalar", Tag),
56+
("scalars", list[Tag])
57+
]
58+
)
59+
async def test_run(
60+
self,
61+
statement: Executable,
62+
method: Literal['scalars', 'scalar', 'execute'],
63+
mixin: PostgresSessionMixin,
64+
expected_type: type,
65+
) -> None:
66+
async with mixin as session:
67+
response = await session.run(statement, method)
68+
assert isinstance(response, expected_type)

tests/infrastructure/s3.py

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import os
2+
from io import BytesIO
3+
from typing import BinaryIO
4+
5+
import pytest
6+
7+
from src.infrastructure.s3 import S3SessionMixin, unique_filename, get_file_stream
8+
9+
10+
class TestS3SessionMixin:
11+
@pytest.fixture(scope="function")
12+
def mixin(self) -> S3SessionMixin:
13+
return S3SessionMixin()
14+
15+
@pytest.fixture(scope="function")
16+
def filename(self) -> str:
17+
return "filename"
18+
19+
@pytest.fixture(scope="function")
20+
def path(self) -> str:
21+
return "/path/"
22+
23+
@pytest.fixture(scope="function")
24+
def file_stream(self) -> BytesIO:
25+
return BytesIO()
26+
27+
async def test_read(self, path: str, filename: str, mixin: S3SessionMixin) -> None:
28+
async with mixin as session:
29+
response = await session.read(path, filename)
30+
assert isinstance(response, str)
31+
assert response.startswith("https://storage.yandexcloud.net/")
32+
assert response.endswith(os.path.join(path, filename))
33+
34+
async def test_write(self, path: str, filename: str, file_stream: BytesIO, mixin: S3SessionMixin) -> None:
35+
async with mixin as session:
36+
response = await session.write(path, filename, file_stream)
37+
assert isinstance(response, str)
38+
39+
async def test_update(self, path: str, filename: str, file_stream: BytesIO, mixin: S3SessionMixin) -> None:
40+
async with mixin as session:
41+
response = await session.update(path, filename, file_stream)
42+
assert isinstance(response, str)
43+
44+
async def test_remove(self, path: str, filename: str, mixin: S3SessionMixin) -> None:
45+
async with mixin as session:
46+
await session.remove(path, filename)
47+
48+
49+
class TestFileActions:
50+
@pytest.fixture(scope="function")
51+
def filename(self) -> str:
52+
return "filename"
53+
54+
@pytest.fixture(scope="function")
55+
def data(self) -> bytes:
56+
return bytes()
57+
58+
def test_unique_filename(self, filename: str) -> None:
59+
response = unique_filename(filename)
60+
assert isinstance(response, str)
61+
62+
def test_get_file_stream(self, data: bytes) -> None:
63+
response = get_file_stream(data)
64+
assert isinstance(response, BinaryIO)

0 commit comments

Comments
 (0)