FastAPI backend for personal health and skincare data with MCP export. Includes SQLModel models for products, inventory, medications, lab results, routines, and skin condition snapshots. Pytest suite with 111 tests running on SQLite in-memory (no PostgreSQL required). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
87 lines
2.2 KiB
Python
87 lines
2.2 KiB
Python
import os
|
|
|
|
# Must be set before importing db (which calls create_engine at module level)
|
|
os.environ.setdefault("DATABASE_URL", "sqlite://")
|
|
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
from sqlmodel import Session, SQLModel, create_engine
|
|
from sqlmodel.pool import StaticPool
|
|
|
|
import db as db_module
|
|
from db import get_session
|
|
from main import app
|
|
|
|
|
|
@pytest.fixture()
|
|
def session(monkeypatch):
|
|
"""Per-test fresh SQLite in-memory database with full isolation."""
|
|
engine = create_engine(
|
|
"sqlite://",
|
|
connect_args={"check_same_thread": False},
|
|
poolclass=StaticPool,
|
|
)
|
|
# Patch before TestClient triggers lifespan (which calls create_db_and_tables)
|
|
monkeypatch.setattr(db_module, "engine", engine)
|
|
import innercontext.models # noqa: F401 — populate SQLModel.metadata
|
|
|
|
SQLModel.metadata.create_all(engine)
|
|
with Session(engine) as s:
|
|
yield s
|
|
# monkeypatch auto-restores db_module.engine after test
|
|
|
|
|
|
@pytest.fixture()
|
|
def client(session):
|
|
"""TestClient using the per-test session for every request."""
|
|
|
|
def _override():
|
|
yield session
|
|
|
|
app.dependency_overrides[get_session] = _override
|
|
with TestClient(app) as c:
|
|
yield c
|
|
app.dependency_overrides.clear()
|
|
|
|
|
|
# ---- Shared data fixtures ----
|
|
|
|
|
|
@pytest.fixture()
|
|
def product_data():
|
|
return {
|
|
"name": "CeraVe Moisturising Cream",
|
|
"brand": "CeraVe",
|
|
"category": "moisturizer",
|
|
"routine_role": "seal",
|
|
"recommended_time": "both",
|
|
"leave_on": True,
|
|
}
|
|
|
|
|
|
@pytest.fixture()
|
|
def created_product(client, product_data):
|
|
r = client.post("/products/", json=product_data)
|
|
assert r.status_code == 201
|
|
return r.json()
|
|
|
|
|
|
@pytest.fixture()
|
|
def medication_data():
|
|
return {"kind": "prescription", "product_name": "Epiduo"}
|
|
|
|
|
|
@pytest.fixture()
|
|
def created_medication(client, medication_data):
|
|
r = client.post("/health/medications", json=medication_data)
|
|
assert r.status_code == 201
|
|
return r.json()
|
|
|
|
|
|
@pytest.fixture()
|
|
def created_routine(client):
|
|
r = client.post(
|
|
"/routines/", json={"routine_date": "2026-02-26", "part_of_day": "am"}
|
|
)
|
|
assert r.status_code == 201
|
|
return r.json()
|