Files
Home_assistant/backend/tests/test_body_composition.py
T
2026-07-01 05:04:47 +00:00

159 lines
3.9 KiB
Python

import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from app.db.base import Base
from app.db.models import BodyMetric, FitnessProfile, User
from app.fitness.body_composition import (
compute_body_composition,
ffmi,
lean_body_mass,
navy_body_fat_pct,
whr,
)
def test_navy_male_reasonable_range():
bf = navy_body_fat_pct(
sex="male",
height_cm=180,
neck_cm=38,
waist_cm=84,
)
assert bf == pytest.approx(15.3)
def test_navy_female_requires_hip():
assert navy_body_fat_pct(
sex="female",
height_cm=165,
neck_cm=34,
waist_cm=72,
hip_cm=None,
) is None
bf = navy_body_fat_pct(
sex="female",
height_cm=165,
neck_cm=34,
waist_cm=72,
hip_cm=98,
)
assert bf == pytest.approx(26.4)
def test_navy_invalid_waist_neck():
assert navy_body_fat_pct(
sex="male",
height_cm=180,
neck_cm=40,
waist_cm=39,
) is None
def test_whr():
assert whr(80, 100) == 0.8
def test_lean_body_mass_and_ffmi():
lbm = lean_body_mass(80, 20)
assert lbm == 64.0
score = ffmi(80, 180, 20)
assert score is not None
assert 15 <= score <= 25
def test_compute_manual_body_fat():
result = compute_body_composition(
sex="male",
height_cm=180,
weight_kg=80,
body_fat_pct=18,
waist_cm=84,
hip_cm=100,
)
assert result["body_fat_pct"] == 18.0
assert result["body_fat_method"] == "manual"
assert result["whr"] == 0.84
assert result["lbm_kg"] == 65.6
assert result["ffmi"] is not None
def test_compute_navy_auto():
result = compute_body_composition(
sex="male",
height_cm=180,
weight_kg=82,
neck_cm=38,
waist_cm=84,
)
assert result["body_fat_pct"] is not None
assert result["body_fat_method"] == "navy"
assert result["lbm_kg"] is not None
def test_compute_female_warning_without_hip():
result = compute_body_composition(
sex="female",
height_cm=165,
weight_kg=60,
neck_cm=34,
waist_cm=72,
)
assert result["body_fat_pct"] is None
assert any("бёдер" in w for w in result["warnings"])
def test_update_body_metric_recomputes_composition_and_latest_profile_weight():
from app.fitness.service import FitnessService
engine = create_engine("sqlite:///:memory:")
Base.metadata.create_all(engine)
Session = sessionmaker(bind=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=82,
goal="maintain",
)
)
metric = BodyMetric(
user_id=user.id,
weight_kg=82,
body_fat_pct=9.0,
body_fat_method="navy",
waist_cm=84,
neck_cm=38,
)
db.add(metric)
db.commit()
metric_id = metric.id
user_id = user.id
result = FitnessService(db, user_id).update_body_metric(
metric_id,
{"weight_kg": 83, "waist_cm": 86, "neck_cm": 38},
)
assert result is not None
expected = compute_body_composition(
sex="male",
height_cm=180,
weight_kg=83,
waist_cm=86,
neck_cm=38,
)
assert result["metric"]["weight_kg"] == 83
assert result["metric"]["body_fat_method"] == "navy"
assert result["metric"]["body_fat_pct"] == expected["body_fat_pct"]
assert result["metric"]["lbm_kg"] == expected["lbm_kg"]
assert result["metric"]["ffmi"] == expected["ffmi"]
assert db.query(FitnessProfile).one().weight_kg == 83