smart tdee
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
import unittest
|
||||
|
||||
from app.fitness.activity_budget import estimate_workout_active_kcal, infer_met, workouts_kcal_total
|
||||
from app.fitness.calculators import (
|
||||
DEFAULT_NEAT_KCAL,
|
||||
bmr_mifflin,
|
||||
compute_daily_targets,
|
||||
compute_targets,
|
||||
compute_tdee,
|
||||
macro_targets,
|
||||
steps_kcal,
|
||||
water_target_l,
|
||||
)
|
||||
|
||||
PROFILE = {
|
||||
"sex": "male",
|
||||
"age": 30,
|
||||
"height_cm": 180,
|
||||
"weight_kg": 86,
|
||||
"goal": "maintain",
|
||||
"neat_base_kcal": 200,
|
||||
}
|
||||
|
||||
|
||||
class TdeeComponentsTests(unittest.TestCase):
|
||||
def test_rest_day_tdee_is_bmr_plus_neat(self) -> None:
|
||||
breakdown = compute_tdee(PROFILE, steps_total=0, workouts=[])
|
||||
bmr = bmr_mifflin(sex="male", weight_kg=86, height_cm=180, age=30)
|
||||
self.assertEqual(breakdown["bmr"], round(bmr, 0))
|
||||
self.assertEqual(breakdown["neat_kcal"], DEFAULT_NEAT_KCAL)
|
||||
self.assertEqual(breakdown["steps_kcal"], 0.0)
|
||||
self.assertEqual(breakdown["workout_kcal"], 0.0)
|
||||
self.assertEqual(breakdown["tdee"], round(bmr + DEFAULT_NEAT_KCAL, 0))
|
||||
|
||||
def test_steps_kcal_at_reference_weight(self) -> None:
|
||||
kcal = steps_kcal(steps=10000, weight_kg=86)
|
||||
self.assertAlmostEqual(kcal, 400.0, delta=1.0)
|
||||
|
||||
def test_daily_targets_include_activity(self) -> None:
|
||||
daily = compute_daily_targets(
|
||||
PROFILE,
|
||||
steps_total=8000,
|
||||
workouts=[{"active_calories": 450}],
|
||||
)
|
||||
self.assertGreater(daily["steps_kcal"], 0)
|
||||
self.assertEqual(daily["workout_kcal"], 450.0)
|
||||
self.assertEqual(
|
||||
daily["tdee"],
|
||||
daily["bmr"] + daily["neat_kcal"] + daily["steps_kcal"] + daily["workout_kcal"],
|
||||
)
|
||||
self.assertEqual(daily["calorie_target"], daily["tdee"])
|
||||
|
||||
def test_compute_targets_rest_day(self) -> None:
|
||||
targets = compute_targets(PROFILE)
|
||||
self.assertEqual(targets["steps_kcal"], 0)
|
||||
self.assertEqual(targets["workout_kcal"], 0)
|
||||
self.assertEqual(targets["calorie_target"], targets["tdee"])
|
||||
|
||||
def test_water_target(self) -> None:
|
||||
self.assertEqual(water_target_l(70), 2.3)
|
||||
|
||||
def test_workout_active_calories_priority(self) -> None:
|
||||
kcal = estimate_workout_active_kcal(
|
||||
{"active_calories": 300, "duration_min": 60, "met": 9.8},
|
||||
weight_kg=86,
|
||||
)
|
||||
self.assertEqual(kcal, 300.0)
|
||||
|
||||
def test_workout_met_fallback(self) -> None:
|
||||
kcal = estimate_workout_active_kcal(
|
||||
{"title": "бег", "duration_min": 60},
|
||||
weight_kg=86,
|
||||
)
|
||||
self.assertAlmostEqual(kcal, 9.8 * 86, delta=1.0)
|
||||
|
||||
def test_workout_no_data_returns_zero(self) -> None:
|
||||
self.assertEqual(estimate_workout_active_kcal({}, weight_kg=70), 0.0)
|
||||
|
||||
def test_infer_met_from_title(self) -> None:
|
||||
self.assertEqual(infer_met({"title": "пробежал триатлон"}), 10.0)
|
||||
|
||||
def test_workouts_kcal_total(self) -> None:
|
||||
total = workouts_kcal_total(
|
||||
[
|
||||
{"active_calories": 100},
|
||||
{"title": "ходьба", "duration_min": 30},
|
||||
],
|
||||
weight_kg=86,
|
||||
)
|
||||
self.assertGreater(total, 100)
|
||||
|
||||
|
||||
class MacroTargetsTests(unittest.TestCase):
|
||||
def test_lose_macros_from_weight(self) -> None:
|
||||
macros = macro_targets(2363, 86, "lose")
|
||||
self.assertEqual(macros["protein_g"], 189)
|
||||
self.assertEqual(macros["fat_g"], 86)
|
||||
self.assertEqual(macros["carbs_g"], 208)
|
||||
|
||||
def test_maintain_macros_from_weight(self) -> None:
|
||||
macros = macro_targets(2000, 86, "maintain")
|
||||
self.assertEqual(macros["protein_g"], 155)
|
||||
self.assertEqual(macros["fat_g"], 86)
|
||||
self.assertEqual(macros["carbs_g"], 152)
|
||||
|
||||
def test_active_day_increases_carbs_only(self) -> None:
|
||||
rest = compute_daily_targets(PROFILE, steps_total=0, workouts=[])
|
||||
active = compute_daily_targets(
|
||||
PROFILE,
|
||||
steps_total=8000,
|
||||
workouts=[{"active_calories": 450}],
|
||||
)
|
||||
self.assertEqual(rest["protein_g"], active["protein_g"])
|
||||
self.assertEqual(rest["fat_g"], active["fat_g"])
|
||||
self.assertGreater(active["calorie_target"], rest["calorie_target"])
|
||||
self.assertGreater(active["carbs_g"], rest["carbs_g"])
|
||||
|
||||
def test_low_calorie_target_floors_carbs_at_zero(self) -> None:
|
||||
macros = macro_targets(1000, 86, "lose")
|
||||
self.assertEqual(macros["protein_g"], 189)
|
||||
self.assertEqual(macros["fat_g"], 86)
|
||||
self.assertEqual(macros["carbs_g"], 0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user