第一版
This commit is contained in:
284
tests/test_web.py
Normal file
284
tests/test_web.py
Normal file
@@ -0,0 +1,284 @@
|
||||
"""Web API 测试"""
|
||||
|
||||
from datetime import date, timedelta
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from src.vitals.core import database as db
|
||||
from src.vitals.core.models import Exercise, Meal, Sleep, Weight, UserConfig
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def client():
|
||||
"""创建测试客户端"""
|
||||
from src.vitals.web.app import app
|
||||
return TestClient(app)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def populated_db():
|
||||
"""填充测试数据"""
|
||||
today = date.today()
|
||||
|
||||
# 用户配置
|
||||
config = UserConfig(
|
||||
age=28, gender="male", height=175.0, weight=72.0,
|
||||
activity_level="moderate", goal="maintain",
|
||||
)
|
||||
db.save_config(config)
|
||||
|
||||
# 今日数据
|
||||
db.add_exercise(Exercise(
|
||||
date=today, type="跑步", duration=30, calories=240, distance=5.0,
|
||||
))
|
||||
db.add_meal(Meal(
|
||||
date=today, meal_type="午餐",
|
||||
description="米饭+鸡肉", calories=500,
|
||||
))
|
||||
db.add_meal(Meal(
|
||||
date=today, meal_type="早餐",
|
||||
description="燕麦+鸡蛋", calories=350,
|
||||
))
|
||||
db.add_sleep(Sleep(
|
||||
date=today, duration=7.5, quality=4,
|
||||
))
|
||||
db.add_weight(Weight(
|
||||
date=today, weight_kg=72.5, body_fat_pct=18.5,
|
||||
))
|
||||
|
||||
return today
|
||||
|
||||
|
||||
class TestRootEndpoint:
|
||||
"""根路径测试"""
|
||||
|
||||
def test_root_returns_html(self, client):
|
||||
"""测试返回 HTML"""
|
||||
response = client.get("/")
|
||||
assert response.status_code == 200
|
||||
assert "text/html" in response.headers["content-type"]
|
||||
|
||||
def test_root_contains_dashboard(self, client):
|
||||
"""测试包含仪表盘内容"""
|
||||
response = client.get("/")
|
||||
assert "Vitals" in response.text
|
||||
assert "健康管理" in response.text
|
||||
|
||||
|
||||
class TestConfigEndpoint:
|
||||
"""配置接口测试"""
|
||||
|
||||
def test_get_config(self, client, populated_db):
|
||||
"""测试获取配置"""
|
||||
response = client.get("/api/config")
|
||||
assert response.status_code == 200
|
||||
|
||||
data = response.json()
|
||||
assert data["age"] == 28
|
||||
assert data["gender"] == "male"
|
||||
assert data["bmr"] is not None
|
||||
assert data["tdee"] is not None
|
||||
|
||||
def test_get_config_empty(self, client):
|
||||
"""测试空配置"""
|
||||
response = client.get("/api/config")
|
||||
assert response.status_code == 200
|
||||
|
||||
data = response.json()
|
||||
assert data["activity_level"] == "moderate"
|
||||
|
||||
|
||||
class TestTodayEndpoint:
|
||||
"""今日概览接口测试"""
|
||||
|
||||
def test_get_today(self, client, populated_db):
|
||||
"""测试获取今日数据"""
|
||||
response = client.get("/api/today")
|
||||
assert response.status_code == 200
|
||||
|
||||
data = response.json()
|
||||
assert data["date"] == date.today().isoformat()
|
||||
assert data["calories_intake"] > 0
|
||||
assert data["exercise_count"] == 1
|
||||
|
||||
def test_today_has_meals(self, client, populated_db):
|
||||
"""测试包含饮食"""
|
||||
response = client.get("/api/today")
|
||||
data = response.json()
|
||||
|
||||
assert len(data["meals"]) == 2
|
||||
assert data["meals"][0]["meal_type"] in ["午餐", "早餐"]
|
||||
|
||||
def test_today_has_exercises(self, client, populated_db):
|
||||
"""测试包含运动"""
|
||||
response = client.get("/api/today")
|
||||
data = response.json()
|
||||
|
||||
assert len(data["exercises"]) == 1
|
||||
assert data["exercises"][0]["type"] == "跑步"
|
||||
|
||||
def test_today_empty(self, client):
|
||||
"""测试空数据"""
|
||||
response = client.get("/api/today")
|
||||
assert response.status_code == 200
|
||||
|
||||
data = response.json()
|
||||
assert data["calories_intake"] == 0
|
||||
assert data["exercise_count"] == 0
|
||||
|
||||
|
||||
class TestWeekEndpoint:
|
||||
"""本周汇总接口测试"""
|
||||
|
||||
def test_get_week(self, client, populated_db):
|
||||
"""测试获取本周数据"""
|
||||
response = client.get("/api/week")
|
||||
assert response.status_code == 200
|
||||
|
||||
data = response.json()
|
||||
assert "start_date" in data
|
||||
assert "end_date" in data
|
||||
assert "daily_stats" in data
|
||||
|
||||
def test_week_has_daily_stats(self, client, populated_db):
|
||||
"""测试包含每日统计"""
|
||||
response = client.get("/api/week")
|
||||
data = response.json()
|
||||
|
||||
assert len(data["daily_stats"]) == 7
|
||||
for stat in data["daily_stats"]:
|
||||
assert "date" in stat
|
||||
assert "weekday" in stat
|
||||
|
||||
def test_week_date_range(self, client, populated_db):
|
||||
"""测试日期范围"""
|
||||
response = client.get("/api/week")
|
||||
data = response.json()
|
||||
|
||||
start = date.fromisoformat(data["start_date"])
|
||||
end = date.fromisoformat(data["end_date"])
|
||||
assert (end - start).days == 6
|
||||
|
||||
|
||||
class TestExercisesEndpoint:
|
||||
"""运动记录接口测试"""
|
||||
|
||||
def test_get_exercises(self, client, populated_db):
|
||||
"""测试获取运动记录"""
|
||||
response = client.get("/api/exercises")
|
||||
assert response.status_code == 200
|
||||
|
||||
data = response.json()
|
||||
assert len(data) >= 1
|
||||
|
||||
def test_exercises_with_days_param(self, client, populated_db):
|
||||
"""测试天数参数"""
|
||||
response = client.get("/api/exercises?days=7")
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_exercises_invalid_days(self, client):
|
||||
"""测试无效天数"""
|
||||
response = client.get("/api/exercises?days=0")
|
||||
assert response.status_code == 422 # Validation error
|
||||
|
||||
def test_exercises_empty(self, client):
|
||||
"""测试空数据"""
|
||||
response = client.get("/api/exercises")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == []
|
||||
|
||||
|
||||
class TestMealsEndpoint:
|
||||
"""饮食记录接口测试"""
|
||||
|
||||
def test_get_meals(self, client, populated_db):
|
||||
"""测试获取饮食记录"""
|
||||
response = client.get("/api/meals")
|
||||
assert response.status_code == 200
|
||||
|
||||
data = response.json()
|
||||
assert len(data) >= 2
|
||||
|
||||
def test_meals_structure(self, client, populated_db):
|
||||
"""测试数据结构"""
|
||||
response = client.get("/api/meals")
|
||||
data = response.json()
|
||||
|
||||
meal = data[0]
|
||||
assert "id" in meal
|
||||
assert "date" in meal
|
||||
assert "meal_type" in meal
|
||||
assert "description" in meal
|
||||
assert "calories" in meal
|
||||
|
||||
|
||||
class TestSleepEndpoint:
|
||||
"""睡眠记录接口测试"""
|
||||
|
||||
def test_get_sleep(self, client, populated_db):
|
||||
"""测试获取睡眠记录"""
|
||||
response = client.get("/api/sleep")
|
||||
assert response.status_code == 200
|
||||
|
||||
data = response.json()
|
||||
assert len(data) >= 1
|
||||
|
||||
def test_sleep_structure(self, client, populated_db):
|
||||
"""测试数据结构"""
|
||||
response = client.get("/api/sleep")
|
||||
data = response.json()
|
||||
|
||||
record = data[0]
|
||||
assert "duration" in record
|
||||
assert "quality" in record
|
||||
|
||||
|
||||
class TestWeightEndpoint:
|
||||
"""体重记录接口测试"""
|
||||
|
||||
def test_get_weight(self, client, populated_db):
|
||||
"""测试获取体重记录"""
|
||||
response = client.get("/api/weight")
|
||||
assert response.status_code == 200
|
||||
|
||||
data = response.json()
|
||||
assert len(data) >= 1
|
||||
|
||||
def test_weight_default_days(self, client, populated_db):
|
||||
"""测试默认天数"""
|
||||
response = client.get("/api/weight")
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_weight_structure(self, client, populated_db):
|
||||
"""测试数据结构"""
|
||||
response = client.get("/api/weight")
|
||||
data = response.json()
|
||||
|
||||
record = data[0]
|
||||
assert "weight_kg" in record
|
||||
assert record["weight_kg"] == 72.5
|
||||
|
||||
|
||||
class TestCORS:
|
||||
"""CORS 测试"""
|
||||
|
||||
def test_cors_headers(self, client):
|
||||
"""测试 CORS 头"""
|
||||
response = client.options("/api/config")
|
||||
# FastAPI with CORSMiddleware should handle OPTIONS
|
||||
assert response.status_code in [200, 405]
|
||||
|
||||
|
||||
class TestErrorHandling:
|
||||
"""错误处理测试"""
|
||||
|
||||
def test_not_found(self, client):
|
||||
"""测试 404"""
|
||||
response = client.get("/api/nonexistent")
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_invalid_query_params(self, client):
|
||||
"""测试无效参数"""
|
||||
response = client.get("/api/exercises?days=abc")
|
||||
assert response.status_code == 422
|
||||
Reference in New Issue
Block a user