- Add pytest config with 90% coverage threshold - 15 test files covering all routers, services, schemas, models - 300 tests: unit tests, integration tests, edge cases, mocked external APIs - Update CI workflow to run pytest with coverage enforcement - Mock external services (Genius, MusicBrainz, RadioBrowser) - In-memory SQLite DB per test via conftest fixtures
70 lines
1.9 KiB
Python
70 lines
1.9 KiB
Python
"""Shared test fixtures for music-app backend tests."""
|
|
import pytest
|
|
import os
|
|
import sys
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _setup_test_db(monkeypatch):
|
|
"""Set up isolated in-memory DB for each test."""
|
|
test_db = tempfile.NamedTemporaryFile(suffix=".db", delete=False)
|
|
test_db.close()
|
|
db_url = f"sqlite:///{test_db.name}"
|
|
monkeypatch.setenv("DATABASE_URL", db_url)
|
|
monkeypatch.setenv("API_KEY", "")
|
|
monkeypatch.setenv("GENIUS_API_KEY", "")
|
|
monkeypatch.setenv("MUSIC_DIR", tempfile.mkdtemp())
|
|
monkeypatch.setenv("UPLOAD_DIR", tempfile.mkdtemp())
|
|
|
|
from sqlalchemy import create_engine
|
|
from sqlalchemy.orm import sessionmaker
|
|
import app.db.database as db_mod
|
|
|
|
old_engine = db_mod.engine
|
|
old_session = db_mod.SessionLocal
|
|
|
|
db_mod.engine = create_engine(db_url, connect_args={"check_same_thread": False})
|
|
db_mod.SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=db_mod.engine)
|
|
db_mod.Base.metadata.create_all(bind=db_mod.engine)
|
|
|
|
def override_get_db():
|
|
session = db_mod.SessionLocal()
|
|
try:
|
|
yield session
|
|
finally:
|
|
session.close()
|
|
|
|
from app.db.database import get_db
|
|
from app.main import app
|
|
app.dependency_overrides[get_db] = override_get_db
|
|
|
|
yield db_mod
|
|
|
|
app.dependency_overrides.clear()
|
|
db_mod.engine = old_engine
|
|
db_mod.SessionLocal = old_session
|
|
try:
|
|
os.unlink(test_db.name)
|
|
except FileNotFoundError:
|
|
pass
|
|
|
|
|
|
@pytest.fixture
|
|
def db_module(_setup_test_db):
|
|
"""Access to the test database module."""
|
|
import app.db.database as dm
|
|
return dm
|
|
|
|
|
|
@pytest.fixture
|
|
def client(_setup_test_db):
|
|
"""FastAPI TestClient with isolated DB."""
|
|
from fastapi.testclient import TestClient
|
|
from app.main import app
|
|
with TestClient(app) as c:
|
|
yield c
|