PregoPal / tests /test_loop.py
J.B-Lin
chore: save current version before UI improvements (i18n + font fix)
ec90eae
Raw
History Blame Contribute Delete
5.69 kB
"""
测试:核心循环引擎
==================
测试 LoopState, DailyStatus, PregoPalLoop
"""
import sys
sys.path.insert(0, '.')
import json
import datetime
from pathlib import Path
from loop import LoopState, DailyStatus, PregoPalLoop, _TRANSITIONS, PRESETS_DIR, STATUS_FILE
class TestLoopState:
"""测试状态枚举"""
def test_all_states_defined(self):
"""所有状态应被定义"""
assert LoopState.LAUNCH.value == "launch"
assert LoopState.FAMILY_QUIZ.value == "family_quiz"
assert LoopState.SUMMARIZE.value == "summarize"
assert LoopState.ANALYZE.value == "analyze"
assert LoopState.BRIEF.value == "brief"
assert LoopState.INTERACT.value == "interact"
assert LoopState.THREE_DAY.value == "three_day"
assert LoopState.CONSOLIDATE.value == "consolidate"
assert LoopState.DONE.value == "done"
def test_state_count(self):
"""应有 9 个状态"""
assert len(LoopState) == 9
class TestTransitions:
"""测试状态转移表"""
def test_launch_transitions(self):
"""LAUNCH 应有 2 个转移"""
assert (LoopState.LAUNCH, "need_summary") in _TRANSITIONS
assert (LoopState.LAUNCH, "already_done") in _TRANSITIONS
def test_full_flow(self):
"""完整流程应能到达 DONE"""
state = LoopState.LAUNCH
events = ["need_summary", "ok", "ok", "ok", "ok", "day_ended", "ok"]
for event in events:
next_state = _TRANSITIONS.get((state, event))
assert next_state is not None, f"No transition from {state} on '{event}'"
state = next_state
assert state == LoopState.DONE
def test_three_day_flow(self):
"""触发三天总结的流程"""
state = LoopState.LAUNCH
events = ["need_summary", "ok", "ok", "ok", "ok", "day_ended", "need_3day", "ok"]
for event in events:
next_state = _TRANSITIONS.get((state, event))
assert next_state is not None
state = next_state
assert state == LoopState.DONE
def test_already_done_flow(self):
"""今日已完成的流程"""
state = LoopState.LAUNCH
next_state = _TRANSITIONS.get((state, "already_done"))
assert next_state == LoopState.INTERACT
class TestDailyStatus:
"""测试状态位管理"""
def setup_method(self):
self._backup = None
if STATUS_FILE.exists():
self._backup = STATUS_FILE.read_text(encoding='utf-8')
def teardown_method(self):
if self._backup:
STATUS_FILE.write_text(self._backup, encoding='utf-8')
elif STATUS_FILE.exists():
STATUS_FILE.unlink()
def test_load_empty(self):
"""空文件应返回空字典"""
if STATUS_FILE.exists():
STATUS_FILE.unlink()
status = DailyStatus.load()
assert status == {}
def test_mark_summary_done(self):
"""标记总结完成"""
DailyStatus.mark_summary_done()
today = datetime.date.today().isoformat()
status = DailyStatus.load()
assert status[today]["summary_done"] is True
def test_is_today_done(self):
"""检查今日是否完成"""
DailyStatus.mark_summary_done()
assert DailyStatus.is_today_done() is True
def test_mark_day_ended(self):
"""标记今日结束"""
DailyStatus.mark_day_ended()
today = datetime.date.today().isoformat()
status = DailyStatus.load()
assert status[today]["day_ended"] is True
def test_get_last_summary_date(self):
"""获取最近总结日期"""
DailyStatus.mark_summary_done()
last = DailyStatus.get_last_summary_date()
assert last == datetime.date.today().isoformat()
def test_days_since_last_summary(self):
"""距离上次总结的天数"""
DailyStatus.mark_summary_done()
days = DailyStatus.days_since_last_summary()
assert days == 0
def test_should_three_day_summary_false(self):
"""刚总结完不应触发三天总结"""
DailyStatus.mark_summary_done()
assert DailyStatus.should_three_day_summary() is False
class TestPregoPalLoop:
"""测试循环引擎"""
def test_loop_initialization(self):
"""初始化应处于 LAUNCH 状态"""
loop = PregoPalLoop()
assert loop.state == LoopState.LAUNCH
def test_default_plugins_registered(self):
"""应注册所有默认插件"""
loop = PregoPalLoop()
plugins = loop.plugins.get_all()
plugin_names = [p.name() for p in plugins]
assert "family_recipe_quiz" in plugin_names
assert "weight_quiz" in plugin_names
assert "diet_summary" in plugin_names
assert "weight_check" in plugin_names
assert "family_memory" in plugin_names
assert "dri_analysis" in plugin_names
assert "briefing_generator" in plugin_names
assert "three_day_summary" in plugin_names
assert "preset_writer" in plugin_names
def test_plugin_count(self):
"""应有 9 个默认插件"""
loop = PregoPalLoop()
assert len(loop.plugins.get_all()) == 9
def test_get_briefing_empty(self):
"""初始简报应为空"""
loop = PregoPalLoop()
assert loop.get_briefing() == {}
def test_get_thinking_keywords(self):
"""初始思考关键词"""
loop = PregoPalLoop()
assert loop.get_thinking_keywords() == ""
def test_get_errors_empty(self):
"""初始错误列表为空"""
loop = PregoPalLoop()
assert loop.get_errors() == []