feat: async pytest, testcases for starting and finishing shifts
This commit is contained in:
105
tests/conftest.py
Normal file
105
tests/conftest.py
Normal file
@@ -0,0 +1,105 @@
|
||||
import asyncio
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import AsyncGenerator
|
||||
|
||||
import jwt
|
||||
import pytest
|
||||
from dotenv import load_dotenv
|
||||
from httpx import ASGITransport, AsyncClient
|
||||
from sqlalchemy import StaticPool
|
||||
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker
|
||||
|
||||
from backend.session import get_session
|
||||
from main import app
|
||||
from models import BaseModel
|
||||
from tests.fixture_loader import FixtureLoader
|
||||
|
||||
project_root = Path(__file__).parent.parent
|
||||
env_path = project_root / ".env"
|
||||
load_dotenv(env_path)
|
||||
|
||||
SECRET_KEY = os.getenv("SECRET_KEY")
|
||||
PG_LOGIN = os.environ.get("PG_LOGIN")
|
||||
PG_PASSWORD = os.environ.get("PG_PASSWORD")
|
||||
TEST_DATABASE_URL = f"postgresql+asyncpg://{PG_LOGIN}:{PG_PASSWORD}@127.0.0.1/test"
|
||||
TEST_DATABASE_URL_FOR_ASYNCPG = f"postgresql://{PG_LOGIN}:{PG_PASSWORD}@127.0.0.1/test"
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Create test database + connection pool
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def event_loop():
|
||||
"""Force pytest to use a session-scoped event loop (needed for asyncpg)."""
|
||||
loop = asyncio.get_event_loop_policy().new_event_loop()
|
||||
yield loop
|
||||
loop.close()
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
async def db_session() -> AsyncGenerator[AsyncSession, None]:
|
||||
# Create test engine
|
||||
test_engine = create_async_engine(
|
||||
TEST_DATABASE_URL,
|
||||
poolclass=StaticPool, # Useful for tests
|
||||
)
|
||||
|
||||
# Test session factory
|
||||
TestAsyncSessionLocal = async_sessionmaker(
|
||||
test_engine,
|
||||
class_=AsyncSession,
|
||||
expire_on_commit=False,
|
||||
)
|
||||
|
||||
async with test_engine.begin() as conn:
|
||||
await conn.run_sync(BaseModel.metadata.drop_all)
|
||||
await conn.run_sync(BaseModel.metadata.create_all)
|
||||
|
||||
session = TestAsyncSessionLocal()
|
||||
|
||||
await FixtureLoader().load_fixtures(session)
|
||||
|
||||
try:
|
||||
yield session
|
||||
finally:
|
||||
await session.close()
|
||||
async with test_engine.begin() as conn:
|
||||
await conn.run_sync(BaseModel.metadata.drop_all)
|
||||
await test_engine.dispose()
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# HTTPX AsyncClient for FastAPI tests
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
async def client(db_session: AsyncSession):
|
||||
def override_get_session():
|
||||
try:
|
||||
yield db_session
|
||||
finally:
|
||||
db_session.close()
|
||||
|
||||
app.dependency_overrides[get_session] = override_get_session
|
||||
|
||||
async with AsyncClient(
|
||||
transport=ASGITransport(app=app), base_url="http://localhost:8000/api"
|
||||
) as ac:
|
||||
yield ac
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Auth token fixture
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
async def admin_client(client: AsyncClient):
|
||||
payload = {
|
||||
"sub": "1",
|
||||
"role": "admin",
|
||||
}
|
||||
auth_token = jwt.encode(payload, SECRET_KEY, algorithm="HS256")
|
||||
client.headers.update({"Authorization": f"Bearer {auth_token}"})
|
||||
return client
|
||||
Reference in New Issue
Block a user