"""数据模型测试""" from datetime import date, time import pytest from src.vitals.core.models import ( Exercise, Meal, Sleep, Weight, UserConfig, MealType, ExerciseType, ActivityLevel, Goal, User, DataClearRequest, ) class TestExercise: """运动记录模型测试""" def test_create_exercise(self): """测试创建运动记录""" exercise = Exercise( date=date(2026, 1, 18), type="跑步", duration=30, calories=240, ) assert exercise.type == "跑步" assert exercise.duration == 30 assert exercise.calories == 240 def test_exercise_to_dict(self, sample_exercise): """测试转换为字典""" data = sample_exercise.to_dict() assert data["type"] == "跑步" assert data["duration"] == 30 assert data["distance"] == 5.0 assert data["date"] == "2026-01-18" def test_exercise_default_values(self): """测试默认值""" exercise = Exercise() assert exercise.duration == 0 assert exercise.calories == 0 assert exercise.source == "手动" class TestMeal: """饮食记录模型测试""" def test_create_meal(self): """测试创建饮食记录""" meal = Meal( meal_type="早餐", description="燕麦+鸡蛋", calories=350, ) assert meal.meal_type == "早餐" assert meal.calories == 350 def test_meal_to_dict(self, sample_meal): """测试转换为字典""" data = sample_meal.to_dict() assert data["meal_type"] == "午餐" assert data["calories"] == 650 assert data["protein"] == 25.0 def test_meal_with_food_items(self): """测试带食物条目的饮食记录""" meal = Meal( meal_type="午餐", description="测试", food_items=[{"name": "米饭", "calories": 200}], ) data = meal.to_dict() assert "米饭" in data["food_items"] class TestSleep: """睡眠记录模型测试""" def test_create_sleep(self): """测试创建睡眠记录""" sleep = Sleep( bedtime=time(23, 0), wake_time=time(7, 0), duration=8.0, quality=4, ) assert sleep.duration == 8.0 assert sleep.quality == 4 def test_sleep_to_dict(self, sample_sleep): """测试转换为字典""" data = sample_sleep.to_dict() assert data["duration"] == 7.5 assert data["quality"] == 4 assert data["bedtime"] == "23:30:00" class TestWeight: """体重记录模型测试""" def test_create_weight(self): """测试创建体重记录""" weight = Weight(weight_kg=72.5) assert weight.weight_kg == 72.5 def test_weight_to_dict(self, sample_weight): """测试转换为字典""" data = sample_weight.to_dict() assert data["weight_kg"] == 72.5 assert data["body_fat_pct"] == 18.5 class TestUserConfig: """用户配置模型测试""" def test_bmr_calculation_male(self): """测试男性 BMR 计算""" config = UserConfig( age=28, gender="male", height=175.0, weight=72.0, ) # Mifflin-St Jeor: 10 * 72 + 6.25 * 175 - 5 * 28 + 5 = 1678 assert config.bmr == 1678 def test_bmr_calculation_female(self): """测试女性 BMR 计算""" config = UserConfig( age=25, gender="female", height=165.0, weight=55.0, ) # Mifflin-St Jeor: 10 * 55 + 6.25 * 165 - 5 * 25 - 161 = 1295 assert config.bmr == 1295 def test_bmr_none_when_incomplete(self): """测试不完整时 BMR 为 None""" config = UserConfig(age=28) assert config.bmr is None def test_tdee_calculation(self, sample_config): """测试 TDEE 计算""" # BMR * 1.55 (moderate) expected_tdee = int(sample_config.bmr * 1.55) assert sample_config.tdee == expected_tdee def test_tdee_different_activity_levels(self): """测试不同活动水平的 TDEE""" base_config = { "age": 30, "gender": "male", "height": 175.0, "weight": 70.0, } sedentary = UserConfig(**base_config, activity_level="sedentary") active = UserConfig(**base_config, activity_level="active") assert sedentary.tdee < active.tdee def test_config_to_dict(self, sample_config): """测试转换为字典""" data = sample_config.to_dict() assert data["age"] == 28 assert data["gender"] == "male" assert data["bmr"] is not None assert data["tdee"] is not None class TestEnums: """枚举类型测试""" def test_meal_type_values(self): """测试餐次类型""" assert MealType.BREAKFAST.value == "早餐" assert MealType.LUNCH.value == "午餐" assert MealType.DINNER.value == "晚餐" assert MealType.SNACK.value == "加餐" def test_exercise_type_values(self): """测试运动类型""" assert ExerciseType.RUNNING.value == "跑步" assert ExerciseType.SWIMMING.value == "游泳" def test_activity_level_values(self): """测试活动水平""" assert ActivityLevel.SEDENTARY.value == "sedentary" assert ActivityLevel.MODERATE.value == "moderate" def test_goal_values(self): """测试目标""" assert Goal.LOSE.value == "lose" assert Goal.MAINTAIN.value == "maintain" assert Goal.GAIN.value == "gain" class TestUser: """用户模型测试""" def test_user_creation(self): """测试创建用户""" from datetime import datetime user = User( name="小明", created_at=datetime.now(), ) assert user.name == "小明" assert user.is_active == False assert user.id is None def test_user_to_dict(self): """测试用户转换为字典""" from datetime import datetime user = User( id=1, name="小红", created_at=datetime(2026, 1, 19, 10, 0, 0), is_active=True, ) d = user.to_dict() assert d["id"] == 1 assert d["name"] == "小红" assert d["is_active"] == True assert "created_at" in d class TestDataClearRequest: """数据清除请求模型测试""" def test_clear_by_range(self): """测试按时间范围清除""" req = DataClearRequest( user_id=1, mode="range", date_from=date(2026, 1, 1), date_to=date(2026, 1, 15), ) assert req.mode == "range" assert req.date_from == date(2026, 1, 1) def test_clear_by_type(self): """测试按类型清除""" req = DataClearRequest( user_id=1, mode="type", data_types=["exercise", "meal"], ) assert req.mode == "type" assert "exercise" in req.data_types def test_clear_all(self): """测试清除全部""" req = DataClearRequest( user_id=1, mode="all", ) assert req.mode == "all"