299 lines
8.7 KiB
Python
299 lines
8.7 KiB
Python
"""报告生成测试"""
|
|
|
|
from datetime import date, time, timedelta
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from src.vitals.core import database as db
|
|
from src.vitals.core.models import Exercise, Meal, Sleep, Weight, UserConfig
|
|
from src.vitals.core.report import (
|
|
generate_weekly_report,
|
|
generate_monthly_report,
|
|
render_weekly_report_terminal,
|
|
render_weekly_report_markdown,
|
|
render_weekly_report_html,
|
|
export_report,
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def populated_db():
|
|
"""填充测试数据"""
|
|
today = date.today()
|
|
|
|
# 添加用户配置
|
|
config = UserConfig(
|
|
age=28, gender="male", height=175.0, weight=72.0,
|
|
activity_level="moderate", goal="lose",
|
|
)
|
|
db.save_config(config)
|
|
|
|
# 添加本周数据
|
|
for i in range(7):
|
|
day = today - timedelta(days=today.weekday()) + timedelta(days=i)
|
|
|
|
# 运动
|
|
if i % 2 == 0:
|
|
db.add_exercise(Exercise(
|
|
date=day, type="跑步", duration=30, calories=240,
|
|
))
|
|
|
|
# 饮食
|
|
db.add_meal(Meal(
|
|
date=day, meal_type="午餐",
|
|
description="米饭+鸡肉", calories=500,
|
|
))
|
|
|
|
# 睡眠
|
|
db.add_sleep(Sleep(
|
|
date=day, duration=7.0 + i * 0.1, quality=3 + (i % 3),
|
|
))
|
|
|
|
# 体重
|
|
db.add_weight(Weight(
|
|
date=day, weight_kg=72.0 - i * 0.1,
|
|
))
|
|
|
|
return today
|
|
|
|
|
|
class TestGenerateWeeklyReport:
|
|
"""周报生成测试"""
|
|
|
|
def test_generate_report(self, populated_db):
|
|
"""测试生成周报"""
|
|
report = generate_weekly_report()
|
|
|
|
assert report is not None
|
|
assert report.exercise_count > 0
|
|
assert report.exercise_duration > 0
|
|
|
|
def test_report_date_range(self, populated_db):
|
|
"""测试日期范围"""
|
|
report = generate_weekly_report()
|
|
|
|
# 本周应该是周一到周日
|
|
assert report.end_date - report.start_date == timedelta(days=6)
|
|
assert report.start_date.weekday() == 0 # 周一
|
|
|
|
def test_report_exercise_stats(self, populated_db):
|
|
"""测试运动统计"""
|
|
report = generate_weekly_report()
|
|
|
|
assert report.exercise_count > 0
|
|
assert report.exercise_duration > 0
|
|
assert report.exercise_calories > 0
|
|
assert "跑步" in report.exercise_types
|
|
|
|
def test_report_sleep_stats(self, populated_db):
|
|
"""测试睡眠统计"""
|
|
report = generate_weekly_report()
|
|
|
|
assert report.avg_sleep_duration > 0
|
|
assert 1 <= report.avg_sleep_quality <= 5
|
|
|
|
def test_report_weight_stats(self, populated_db):
|
|
"""测试体重统计"""
|
|
report = generate_weekly_report()
|
|
|
|
assert report.weight_start is not None
|
|
assert report.weight_end is not None
|
|
assert report.weight_change is not None
|
|
|
|
def test_report_daily_stats(self, populated_db):
|
|
"""测试每日统计"""
|
|
report = generate_weekly_report()
|
|
|
|
assert len(report.daily_stats) == 7
|
|
for stat in report.daily_stats:
|
|
assert stat.weekday in ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]
|
|
|
|
def test_report_with_custom_date(self, populated_db):
|
|
"""测试指定日期"""
|
|
report = generate_weekly_report(date(2026, 1, 15))
|
|
|
|
# 2026-01-15 是周四, 那周的周一是 01-12
|
|
assert report.start_date == date(2026, 1, 12)
|
|
assert report.end_date == date(2026, 1, 18)
|
|
|
|
|
|
class TestGenerateMonthlyReport:
|
|
"""月报生成测试"""
|
|
|
|
def test_generate_report(self, populated_db):
|
|
"""测试生成月报"""
|
|
report = generate_monthly_report()
|
|
|
|
assert report is not None
|
|
assert report.year > 0
|
|
assert 1 <= report.month <= 12
|
|
|
|
def test_report_date_range(self, populated_db):
|
|
"""测试日期范围"""
|
|
report = generate_monthly_report(2026, 1)
|
|
|
|
assert report.start_date == date(2026, 1, 1)
|
|
assert report.end_date == date(2026, 1, 31)
|
|
|
|
def test_report_exercise_stats(self, populated_db):
|
|
"""测试运动统计"""
|
|
report = generate_monthly_report()
|
|
|
|
assert report.exercise_count >= 0
|
|
assert report.exercise_days >= 0
|
|
|
|
def test_report_weekly_summaries(self, populated_db):
|
|
"""测试周汇总"""
|
|
report = generate_monthly_report()
|
|
|
|
assert len(report.weekly_summaries) > 0
|
|
for week in report.weekly_summaries:
|
|
assert "week" in week
|
|
assert "exercise_duration" in week
|
|
|
|
def test_report_with_custom_month(self):
|
|
"""测试指定月份"""
|
|
report = generate_monthly_report(2025, 6)
|
|
|
|
assert report.year == 2025
|
|
assert report.month == 6
|
|
|
|
|
|
class TestRenderWeeklyReportTerminal:
|
|
"""终端渲染测试"""
|
|
|
|
def test_render_contains_sections(self, populated_db):
|
|
"""测试包含各部分"""
|
|
report = generate_weekly_report()
|
|
output = render_weekly_report_terminal(report)
|
|
|
|
assert "运动" in output
|
|
assert "睡眠" in output
|
|
assert "饮食" in output
|
|
assert "体重" in output
|
|
assert "每日明细" in output
|
|
|
|
def test_render_contains_stats(self, populated_db):
|
|
"""测试包含统计数据"""
|
|
report = generate_weekly_report()
|
|
output = render_weekly_report_terminal(report)
|
|
|
|
assert "分钟" in output
|
|
assert "卡" in output
|
|
|
|
|
|
class TestRenderWeeklyReportMarkdown:
|
|
"""Markdown 渲染测试"""
|
|
|
|
def test_render_is_valid_markdown(self, populated_db):
|
|
"""测试是有效的 Markdown"""
|
|
report = generate_weekly_report()
|
|
output = render_weekly_report_markdown(report)
|
|
|
|
assert output.startswith("# ")
|
|
assert "## " in output
|
|
assert "| " in output # 表格
|
|
|
|
def test_render_contains_sections(self, populated_db):
|
|
"""测试包含各部分"""
|
|
report = generate_weekly_report()
|
|
output = render_weekly_report_markdown(report)
|
|
|
|
assert "## 运动" in output
|
|
assert "## 睡眠" in output
|
|
assert "## 饮食" in output
|
|
assert "## 体重" in output
|
|
|
|
|
|
class TestRenderWeeklyReportHtml:
|
|
"""HTML 渲染测试"""
|
|
|
|
def test_render_is_valid_html(self, populated_db):
|
|
"""测试是有效的 HTML"""
|
|
report = generate_weekly_report()
|
|
output = render_weekly_report_html(report)
|
|
|
|
assert "<!DOCTYPE html>" in output
|
|
assert "<html" in output
|
|
assert "</html>" in output
|
|
|
|
def test_render_contains_styles(self, populated_db):
|
|
"""测试包含样式"""
|
|
report = generate_weekly_report()
|
|
output = render_weekly_report_html(report)
|
|
|
|
assert "<style>" in output
|
|
assert "</style>" in output
|
|
|
|
def test_render_contains_data(self, populated_db):
|
|
"""测试包含数据"""
|
|
report = generate_weekly_report()
|
|
output = render_weekly_report_html(report)
|
|
|
|
assert "运动" in output
|
|
assert "睡眠" in output
|
|
|
|
|
|
class TestExportReport:
|
|
"""报告导出测试"""
|
|
|
|
def test_export_markdown(self, populated_db, tmp_path):
|
|
"""测试导出 Markdown"""
|
|
report = generate_weekly_report()
|
|
output_path = tmp_path / "report.md"
|
|
|
|
result = export_report(report, output_path)
|
|
|
|
assert result is True
|
|
assert output_path.exists()
|
|
content = output_path.read_text()
|
|
assert "# " in content
|
|
|
|
def test_export_html(self, populated_db, tmp_path):
|
|
"""测试导出 HTML"""
|
|
report = generate_weekly_report()
|
|
output_path = tmp_path / "report.html"
|
|
|
|
result = export_report(report, output_path)
|
|
|
|
assert result is True
|
|
assert output_path.exists()
|
|
content = output_path.read_text()
|
|
assert "<!DOCTYPE html>" in content
|
|
|
|
def test_export_unsupported_format(self, populated_db, tmp_path):
|
|
"""测试不支持的格式"""
|
|
report = generate_weekly_report()
|
|
output_path = tmp_path / "report.xyz"
|
|
|
|
result = export_report(report, output_path)
|
|
|
|
assert result is False
|
|
|
|
|
|
class TestEmptyData:
|
|
"""空数据测试"""
|
|
|
|
def test_weekly_report_empty(self):
|
|
"""测试空数据周报"""
|
|
report = generate_weekly_report()
|
|
|
|
assert report.exercise_count == 0
|
|
assert report.avg_sleep_duration == 0
|
|
assert report.weight_start is None
|
|
|
|
def test_monthly_report_empty(self):
|
|
"""测试空数据月报"""
|
|
report = generate_monthly_report()
|
|
|
|
assert report.exercise_count == 0
|
|
assert report.avg_sleep_duration == 0
|
|
|
|
def test_render_empty_report(self):
|
|
"""测试渲染空报告"""
|
|
report = generate_weekly_report()
|
|
output = render_weekly_report_terminal(report)
|
|
|
|
assert "暂无记录" in output or "0" in output
|