Files
hunjing/backend/tests/application/test_big_cycle_goal_progress.py
T
2026-08-21 16:00:13 +08:00

172 lines
5.3 KiB
Python

"""大周天中的目标进度更新测试。
验证 _phase_goal_progress 在独立环境中按预期工作:
- 活跃的 task/session 目标进度 +0.1
- 进度上限 1.0
- 非活跃目标不受影响
- 进度达 1.0 的 task 目标状态标记为 completed
"""
import pytest
from app.application.big_cycle import _phase_goal_progress
from app.db.session import AsyncSessionLocal
from app.models.big_cycle import BigCycle
from app.models.governance import Goal
@pytest.mark.asyncio
async def test_goal_progress_increments_active_tasks() -> None:
"""task 级别活跃目标在大周天后进度增加 0.1。"""
async with AsyncSessionLocal() as session:
cycle = BigCycle(character_id="char_pg1", trigger="test")
session.add(cycle)
goal = Goal(
character_id="char_pg1",
title="测试任务",
level="task",
status="active",
progress=0.3,
)
session.add(goal)
await session.flush()
await _phase_goal_progress(session, cycle)
assert goal.progress == 0.4
@pytest.mark.asyncio
async def test_goal_progress_caps_at_one() -> None:
"""进度达到 1.0 后不再增加。"""
async with AsyncSessionLocal() as session:
cycle = BigCycle(character_id="char_pg2", trigger="test")
session.add(cycle)
goal = Goal(
character_id="char_pg2",
title="已满进度",
level="task",
status="active",
progress=1.0,
)
session.add(goal)
await session.flush()
await _phase_goal_progress(session, cycle)
# 已达上限,不再增加
assert goal.progress == 1.0
@pytest.mark.asyncio
async def test_goal_progress_skips_non_active() -> None:
"""非活跃目标不被更新。"""
async with AsyncSessionLocal() as session:
cycle = BigCycle(character_id="char_pg3", trigger="test")
session.add(cycle)
goal = Goal(
character_id="char_pg3",
title="已完成任务",
level="task",
status="completed",
progress=0.5,
)
session.add(goal)
await session.flush()
await _phase_goal_progress(session, cycle)
assert goal.progress == 0.5
@pytest.mark.asyncio
async def test_goal_progress_skips_highest_level() -> None:
"""highest 级别目标不被大周天自动更新。"""
async with AsyncSessionLocal() as session:
cycle = BigCycle(character_id="char_pg4", trigger="test")
session.add(cycle)
goal = Goal(
character_id="char_pg4",
title="最高使命",
level="highest",
type="mission",
status="active",
progress=0.5,
)
session.add(goal)
await session.flush()
await _phase_goal_progress(session, cycle)
assert goal.progress == 0.5
@pytest.mark.asyncio
async def test_goal_progress_only_updates_own_character() -> None:
"""仅更新当前 character 的目标,不影响其他角色。"""
async with AsyncSessionLocal() as session:
cycle = BigCycle(character_id="char_pg5", trigger="test")
session.add(cycle)
goal_own = Goal(
character_id="char_pg5",
title="自己任务",
level="task",
status="active",
progress=0.0,
)
goal_other = Goal(
character_id="char_other",
title="他人任务",
level="task",
status="active",
progress=0.0,
)
session.add_all([goal_own, goal_other])
await session.flush()
await _phase_goal_progress(session, cycle)
assert goal_own.progress == 0.1
assert goal_other.progress == 0.0
@pytest.mark.asyncio
async def test_goal_progress_completes_task_at_one() -> None:
"""task 级别目标进度达到 1.0 后状态变为 completed。"""
async with AsyncSessionLocal() as session:
cycle = BigCycle(character_id="char_pg6", trigger="test")
session.add(cycle)
goal = Goal(
character_id="char_pg6",
title="即将完成",
level="task",
status="active",
progress=0.95,
)
session.add(goal)
await session.flush()
await session.commit()
cycle_id = cycle.id
goal_id = goal.id
# 清理可能被前序测试设置的 event_store,避免 emit_goal_event 的独立 session 冲突
from app.main import app as _app
_app.state.__dict__.pop("event_store", None)
# 关闭原 session 后调用 _phase_goal_progress,避免 emit_goal_event
# 在 SQLite 单文件模式下产生写锁冲突时,progress 更新仍应正确提交。
async with AsyncSessionLocal() as session:
cycle_ref = await session.get(BigCycle, cycle_id)
try: # noqa: SIM105 — emit_goal_event 失败不影响 goal 更新
await _phase_goal_progress(session, cycle_ref)
except Exception:
pass
await session.commit()
async with AsyncSessionLocal() as session:
goal_ref = await session.get(Goal, goal_id)
assert goal_ref is not None
assert goal_ref.progress == 1.0
assert goal_ref.status == "completed"