All checks were successful
CI / test (push) Successful in 3m8s
架构审查候选④:ADR-0008 收敛调度域时为保测试兼容留下的过渡 wrapper 使命结束。 删除 8 个浅封装:task_queue 的 _is_slot_due / _calculate_session_deficit (零调用死函数)+ _calculate_priority / _get_attention_reason,decision 的 _parse_time_slot(零调用死函数)+ _get_current_slot / _count_sessions_in_slot / _has_high_severity_issues。调用方直接使用 domain 模块。 5 个隔着 wrapper 测 domain 行为的测试迁到新文件 test_intelligent_eval_domain.py,直接锁定 domain,覆盖零丢失。 删除测试通过:复杂度直接消失,时段/欠账/优先级知识只剩 domain 一处。 870 tests passed,零行为变化。
135 lines
4.7 KiB
Python
135 lines
4.7 KiB
Python
"""Unit tests for the intelligent-eval scheduling domain (domain.py).
|
||
|
||
从 test_intelligent_eval_task_queue.py 迁移:原先隔着 task_queue 的过渡
|
||
wrapper 测试,ADR-0008 残留 wrapper 删除后直接锁定 domain 模块——
|
||
时段解析、欠账、优先级、注意原因的唯一实现。
|
||
"""
|
||
|
||
from datetime import timedelta
|
||
|
||
from agenteval.intelligent_eval import domain
|
||
from agenteval.intelligent_eval.models import IntelligentEvalStatus
|
||
from agenteval.storage.db import IntelligentEvalDB, IntelligentEvalSessionDB, utc_now
|
||
from sqlmodel import Session
|
||
|
||
|
||
def test_is_slot_due():
|
||
"""Test time slot due detection."""
|
||
# Slot "8-10h" should be due after 8 hours
|
||
slot = {"time_slot": "8-10h", "sessions": 2}
|
||
assert domain.is_slot_due(slot, timedelta(hours=7)) is False
|
||
assert domain.is_slot_due(slot, timedelta(hours=8)) is True
|
||
assert domain.is_slot_due(slot, timedelta(hours=9)) is True
|
||
|
||
# Invalid slot format
|
||
assert domain.is_slot_due({"time_slot": "invalid"}, timedelta(hours=1)) is False
|
||
assert domain.is_slot_due({}, timedelta(hours=1)) is False
|
||
|
||
|
||
def test_is_slot_due_minute_format():
|
||
"""Minute-level slots (1h window: "0-20min") must be parsed and due on time."""
|
||
# 0-20min: due at 0min, not before
|
||
assert domain.is_slot_due({"time_slot": "0-20min"}, timedelta(minutes=-1)) is False
|
||
assert domain.is_slot_due({"time_slot": "0-20min"}, timedelta(minutes=0)) is True
|
||
assert domain.is_slot_due({"time_slot": "0-20min"}, timedelta(minutes=5)) is True
|
||
# 20-40min: not due before 20min, due at 20min
|
||
assert domain.is_slot_due({"time_slot": "20-40min"}, timedelta(minutes=19)) is False
|
||
assert domain.is_slot_due({"time_slot": "20-40min"}, timedelta(minutes=20)) is True
|
||
|
||
# parse both formats consistently (hours)
|
||
assert domain.parse_time_slot("8-10h") == (8.0, 10.0)
|
||
assert domain.parse_time_slot("0-20min") == (0.0, 1.0 / 3)
|
||
assert domain.parse_time_slot("20-40min") == (1.0 / 3, 2.0 / 3)
|
||
assert domain.parse_time_slot("bad") is None
|
||
|
||
|
||
def test_calculate_session_deficit(db_session: Session):
|
||
"""Test session deficit calculation."""
|
||
# Create eval with plan
|
||
eval_db = IntelligentEvalDB(
|
||
name="test",
|
||
target_id="target1",
|
||
status=IntelligentEvalStatus.EXECUTING.value,
|
||
started_at=utc_now() - timedelta(hours=9),
|
||
)
|
||
eval_db.set_plan({
|
||
"time_distribution": [
|
||
{"time_slot": "0-2h", "sessions": 1},
|
||
{"time_slot": "8-10h", "sessions": 2},
|
||
],
|
||
"estimated_sessions": 3,
|
||
})
|
||
db_session.add(eval_db)
|
||
db_session.commit()
|
||
|
||
# No sessions yet, should have 3 (1 from 0-2h, 2 from 8-10h)
|
||
deficit = domain.calculate_session_deficit(eval_db, db_session)
|
||
assert deficit == 3
|
||
|
||
# Add 1 session
|
||
session_db = IntelligentEvalSessionDB(
|
||
eval_id=eval_db.id,
|
||
target_id="target1",
|
||
status="completed",
|
||
)
|
||
db_session.add(session_db)
|
||
db_session.commit()
|
||
|
||
# Should have 3, has 1, deficit = 2
|
||
deficit = domain.calculate_session_deficit(eval_db, db_session)
|
||
assert deficit == 2
|
||
|
||
|
||
def test_calculate_priority(db_session: Session):
|
||
"""Test task priority calculation."""
|
||
# Eval with due slot and deficit
|
||
eval_db = IntelligentEvalDB(
|
||
name="test",
|
||
target_id="target1",
|
||
status=IntelligentEvalStatus.EXECUTING.value,
|
||
started_at=utc_now() - timedelta(hours=9),
|
||
)
|
||
eval_db.set_plan({
|
||
"time_distribution": [{"time_slot": "8-10h", "sessions": 2}],
|
||
"estimated_sessions": 2,
|
||
})
|
||
db_session.add(eval_db)
|
||
db_session.commit()
|
||
|
||
priority = domain.calculate_priority(eval_db, db_session)
|
||
# Base 100 - 50 (slot due) - 20 (deficit 2 * 10) - 20 (wait 9h / 10min = 54, capped at 20)
|
||
assert priority == 10
|
||
|
||
|
||
def test_get_attention_reason(db_session: Session):
|
||
"""Test attention reason detection."""
|
||
# Eval with due slot
|
||
eval_db = IntelligentEvalDB(
|
||
name="test",
|
||
target_id="target1",
|
||
status=IntelligentEvalStatus.EXECUTING.value,
|
||
started_at=utc_now() - timedelta(hours=9),
|
||
)
|
||
eval_db.set_plan({
|
||
"time_distribution": [{"time_slot": "8-10h", "sessions": 2}],
|
||
"estimated_sessions": 2,
|
||
})
|
||
db_session.add(eval_db)
|
||
db_session.commit()
|
||
|
||
reason = domain.get_attention_reason(eval_db, db_session)
|
||
assert reason == "slot_due"
|
||
|
||
# Add all sessions as completed
|
||
for _ in range(2):
|
||
session_db = IntelligentEvalSessionDB(
|
||
eval_id=eval_db.id,
|
||
target_id="target1",
|
||
status="completed",
|
||
)
|
||
db_session.add(session_db)
|
||
db_session.commit()
|
||
|
||
reason = domain.get_attention_reason(eval_db, db_session)
|
||
assert reason == "all_sessions_completed"
|