117 lines
4.3 KiB
Python
117 lines
4.3 KiB
Python
import unittest
|
|
from unittest.mock import patch
|
|
|
|
from sqlalchemy import create_engine, text
|
|
from sqlalchemy.orm import sessionmaker
|
|
|
|
from app.db.base import Base
|
|
from app.db.models import FitnessProfile, User
|
|
from app.fitness.calculators import compute_targets
|
|
|
|
|
|
class TdeeBackfillTests(unittest.TestCase):
|
|
def setUp(self) -> None:
|
|
self.engine = create_engine("sqlite:///:memory:")
|
|
Base.metadata.create_all(self.engine)
|
|
with self.engine.begin() as conn:
|
|
conn.execute(
|
|
text(
|
|
"CREATE TABLE IF NOT EXISTS _schema_migrations ("
|
|
"name TEXT PRIMARY KEY, "
|
|
"applied_at DATETIME DEFAULT CURRENT_TIMESTAMP)"
|
|
)
|
|
)
|
|
|
|
def _insert_legacy_profile(self) -> None:
|
|
Session = sessionmaker(bind=self.engine)
|
|
with Session() as db:
|
|
user = User(username="tester", api_token_hash="x")
|
|
db.add(user)
|
|
db.flush()
|
|
db.add(
|
|
FitnessProfile(
|
|
user_id=user.id,
|
|
sex="male",
|
|
age=30,
|
|
height_cm=180,
|
|
weight_kg=86,
|
|
goal="maintain",
|
|
activity_level="active",
|
|
calorie_target=3200,
|
|
protein_g=155,
|
|
fat_g=89,
|
|
carbs_g=400,
|
|
water_l=3.0,
|
|
neat_base_kcal=None,
|
|
)
|
|
)
|
|
db.commit()
|
|
|
|
def test_backfill_recalculates_stored_targets(self) -> None:
|
|
from app.db import migrate_fitness
|
|
|
|
self._insert_legacy_profile()
|
|
|
|
with patch.object(migrate_fitness, "engine", self.engine):
|
|
updated = migrate_fitness.backfill_tdee_targets(force=True)
|
|
self.assertEqual(updated, 1)
|
|
|
|
Session = sessionmaker(bind=self.engine)
|
|
with Session() as db:
|
|
row = db.query(FitnessProfile).one()
|
|
expected = compute_targets(
|
|
{
|
|
"sex": row.sex,
|
|
"age": row.age,
|
|
"height_cm": row.height_cm,
|
|
"weight_kg": row.weight_kg,
|
|
"goal": row.goal,
|
|
"neat_base_kcal": 200,
|
|
}
|
|
)
|
|
self.assertEqual(row.neat_base_kcal, 200.0)
|
|
self.assertEqual(row.calorie_target, expected["calorie_target"])
|
|
self.assertEqual(row.protein_g, expected["protein_g"])
|
|
self.assertLess(row.calorie_target, 3200)
|
|
|
|
def test_backfill_runs_once(self) -> None:
|
|
from app.db import migrate_fitness
|
|
|
|
self._insert_legacy_profile()
|
|
|
|
with patch.object(migrate_fitness, "engine", self.engine):
|
|
first = migrate_fitness.backfill_tdee_targets(force=True)
|
|
second = migrate_fitness.backfill_tdee_targets()
|
|
self.assertEqual(first, 1)
|
|
self.assertEqual(second, 0)
|
|
|
|
def test_macros_backfill_updates_bju_only(self) -> None:
|
|
from app.db import migrate_fitness
|
|
from app.fitness.calculators import macro_targets
|
|
|
|
self._insert_legacy_profile()
|
|
|
|
with patch.object(migrate_fitness, "engine", self.engine):
|
|
migrate_fitness.backfill_tdee_targets(force=True)
|
|
Session = sessionmaker(bind=self.engine)
|
|
with Session() as db:
|
|
row = db.query(FitnessProfile).one()
|
|
calorie_before = row.calorie_target
|
|
row.protein_g = 999
|
|
db.commit()
|
|
|
|
updated = migrate_fitness.backfill_macros_gkg(force=True)
|
|
self.assertEqual(updated, 1)
|
|
|
|
with Session() as db:
|
|
row = db.query(FitnessProfile).one()
|
|
expected = macro_targets(calorie_before, row.weight_kg, row.goal)
|
|
self.assertEqual(row.calorie_target, calorie_before)
|
|
self.assertEqual(row.protein_g, expected["protein_g"])
|
|
self.assertEqual(row.fat_g, expected["fat_g"])
|
|
self.assertEqual(row.carbs_g, expected["carbs_g"])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|