Skip to content

Commit c537e5b

Browse files
authored
Merge pull request #4 from sumaro2101/develop
Tests
2 parents 375537f + 3e29459 commit c537e5b

10 files changed

Lines changed: 146 additions & 9 deletions

File tree

.env.sample

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,14 @@ GF_SECURITY_ADMIN_USER=admin
2222
GF_SECURITY_ADMIN_PASSWORD=admin
2323
# ==================CADDY==================
2424
ADMIN_USER=admin
25-
ADMIN_PASSWORD=admin
25+
ADMIN_PASSWORD=admin
26+
# ==================TESTS==================
27+
TEST_POSTGRES_DB=test_analizer
28+
TEST_POSTGRES_PASSWORD=
29+
30+
TEST_DB_ENGINE=postgresql+asyncpg
31+
TEST_DB_NAME=test_analizer
32+
TEST_DB_USER=postgres
33+
TEST_DB_PASSWORD=
34+
TEST_DB_HOST=test_db
35+
TEST_DB_PORT=5431

api_v1/tests/__init__.py

Whitespace-only changes.

api_v1/tests/conftest.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import sys
2+
import asyncio
3+
import httpx
4+
import pytest_asyncio
5+
import pytest
6+
7+
from typing import Any, AsyncGenerator
8+
from contextlib import asynccontextmanager
9+
from asgi_lifespan import LifespanManager
10+
from fastapi import FastAPI
11+
from sqlalchemy.pool import NullPool
12+
13+
from config import test_connection, settings, BaseModel
14+
from config import db_connection
15+
from api_v1.routers import register_routers
16+
17+
18+
db_setup = test_connection(
19+
settings.test_db.url,
20+
poolclass=NullPool,
21+
)
22+
23+
24+
@pytest.fixture(scope='session', autouse=True)
25+
def event_loop(request):
26+
loop = asyncio.get_event_loop_policy().new_event_loop()
27+
yield loop
28+
loop.close()
29+
30+
31+
async def override_get_async_session():
32+
async with db_setup.session() as session:
33+
yield session
34+
35+
36+
@pytest_asyncio.fixture(scope='session', autouse=True)
37+
async def app():
38+
@asynccontextmanager
39+
async def lifespan(app: FastAPI):
40+
async with db_setup.engine.begin() as conn:
41+
await conn.run_sync(BaseModel.metadata.create_all)
42+
sys.stdout.write('alembic upgrade head')
43+
yield
44+
await conn.run_sync(BaseModel.metadata.drop_all)
45+
46+
app = FastAPI(docs_url=None, redoc_url=None)
47+
register_routers(app=app)
48+
app.dependency_overrides[db_connection.session_geter] = override_get_async_session
49+
50+
async with LifespanManager(app) as manager:
51+
yield manager.app
52+
53+
54+
@pytest_asyncio.fixture(scope='session')
55+
async def client(app: FastAPI) -> AsyncGenerator[httpx.AsyncClient, Any]:
56+
current_home = settings.CURRENT_ORIGIN
57+
current_api = settings.API_PREFIX
58+
async with httpx.AsyncClient(
59+
app=app,
60+
base_url=current_home + current_api,
61+
) as client:
62+
yield client

api_v1/tests/test_users.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import pytest
2+
3+
from httpx import AsyncClient
4+
5+
6+
@pytest.mark.asyncio
7+
async def test_get_user_error(client: AsyncClient):
8+
response = await client.get(
9+
'/users/get',
10+
)
11+
assert response.status_code == 400

config/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
from .config import settings
22
from .celery.connection import app as celery_app
33
from .database.db_helper import db_helper as db_connection
4+
from .database.db_helper import db_test as test_connection
45
from .models.base import Base as BaseModel
56

67

78
__all__ = ('settings',
89
'celery_app',
910
'db_connection',
11+
'test_connection',
1012
'BaseModel',
1113
)

config/config.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,18 @@
1111
config = Config('.env')
1212

1313

14+
class TestDBSettings(BaseModel):
15+
"""
16+
Настройки тестовой базы данных
17+
"""
18+
_engine: str = config('TEST_DB_ENGINE')
19+
_owner: str = config('TEST_DB_USER')
20+
_password: str = config('TEST_DB_PASSWORD')
21+
_name: str = config('TEST_DB_HOST')
22+
_db_name: str = config('TEST_DB_NAME')
23+
url: str = f'{_engine}://{_owner}:{_password}@{_name}/{_db_name}'
24+
25+
1426
class DBSettings(BaseModel):
1527
"""
1628
Настройки DataBase
@@ -49,6 +61,7 @@ class Settings(BaseSettings):
4961
extra='ignore',
5062
)
5163
db: DBSettings = DBSettings()
64+
test_db: TestDBSettings = TestDBSettings()
5265
rabbit: RabbitSettings = RabbitSettings()
5366
debug: bool = bool(int(config('DEBUG')))
5467
API_PREFIX: str = '/api/v1'

config/database/db_helper.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,37 @@
33
async_scoped_session,
44
AsyncSession,
55
)
6+
from sqlalchemy.pool import Pool
67
from asyncio import current_task
78

89
from typing import AsyncGenerator, Any
910

1011
from config import settings
1112

1213

14+
DATA_BASE_URL = settings.db.url
15+
16+
1317
class DataBaseHelper:
1418
"""
1519
Вспомогательный класс для работы с Базой Данных
1620
"""
17-
def __init__(self) -> None:
18-
self.engine = create_async_engine(
19-
url=settings.db.url,
21+
def __init__(self,
22+
db_url: str = DATA_BASE_URL,
23+
poolclass: Pool | None = None,
24+
) -> None:
25+
self._db_url = db_url
26+
setup = dict(
27+
url=self._db_url,
2028
echo=settings.debug,
2129
)
30+
if poolclass:
31+
setup.update(
32+
poolclass=poolclass,
33+
)
34+
self.engine = create_async_engine(
35+
**setup
36+
)
2237
self.session = async_sessionmaker(
2338
bind=self.engine,
2439
autoflush=False,
@@ -43,3 +58,4 @@ async def session_geter(self) -> AsyncGenerator[AsyncSession, Any]:
4358

4459

4560
db_helper = DataBaseHelper()
61+
db_test = DataBaseHelper

docker-compose.yml

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ services:
4949
command: /start-flower
5050
volumes:
5151
- .:/app
52-
ports:
53-
- 5555:5555
52+
expose:
53+
- 5555
5454
env_file:
5555
- .env
5656
depends_on:
@@ -68,6 +68,18 @@ services:
6868
env_file:
6969
- .env
7070

71+
test_db:
72+
restart: always
73+
image: postgres:16.3-alpine
74+
volumes:
75+
- test_postgres_data:/var/lib/postgresql/data/
76+
hostname: test_db
77+
expose:
78+
- 5431
79+
environment:
80+
- POSTGRES_DB=${TEST_POSTGRES_DB}
81+
- POSTGRES_PASSWORD=${TEST_POSTGRES_PASSWORD}
82+
7183
prometheus:
7284
image: prom/prometheus
7385
container_name: prometheus
@@ -112,9 +124,14 @@ services:
112124
- grafana-data:/var/lib/grafana
113125
- ./grafana/provisioning:/etc/grafana/provisioning
114126
environment:
127+
- DATABASE_USER=${DB_USER}
128+
- DATABASE_PASS=${DB_PASSWORD}
129+
- DATABASE_NAME=${DB_NAME}
130+
- DATABASE_HOST=${DB_HOST}
131+
- DATABASE_SSL_MODE=disable
115132
- GF_USERS_ALLOW_SIGN_UP=false
116-
env_file:
117-
- .env
133+
- GF_SECURITY_ADMIN_USER=${GF_SECURITY_ADMIN_USER}
134+
- GF_SECURITY_ADMIN_PASSWORD=${GF_SECURITY_ADMIN_PASSWORD}
118135
restart: unless-stopped
119136
expose:
120137
- 3000
@@ -130,6 +147,7 @@ services:
130147
- "3000:3000"
131148
- "9090:9090"
132149
- "9093:9093"
150+
- "5555:5555"
133151
volumes:
134152
- ./caddy:/etc/caddy
135153
environment:
@@ -143,6 +161,7 @@ services:
143161

144162
volumes:
145163
postgres_data:
164+
test_postgres_data:
146165
rabbitmq-data:
147166
prometheus-data: {}
148167
grafana-data: {}

docker/alertmanager/config.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ receivers:
77
- send_resolved: true
88
text: "{{ .CommonAnnotations.description }}"
99
username: 'Prometheus'
10-
channel: '#prometheus'
10+
channel: '#prometheus'
11+
api_url: https://hooks.slack.com/services/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

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ prometheus-fastapi-instrumentator = "^7.0.0"
2323

2424
[tool.poetry.group.dev.dependencies]
2525
black = "^24.10.0"
26+
pytest-asyncio = "^0.24.0"
27+
asgi-lifespan = "^2.1.0"
28+
flake8 = "^7.1.1"
2629

2730
[build-system]
2831
requires = ["poetry-core"]

0 commit comments

Comments
 (0)