172 lines
5.3 KiB
Python
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"
|