smart tdee
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
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()
|
||||
Reference in New Issue
Block a user