Files
DDUp/tests/test_report.py

299 lines
8.7 KiB
Python
Raw Normal View History

2026-01-22 12:57:26 +08:00
"""报告生成测试"""
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