AgentEvalTool/tests/unit/test_intelligent_eval_decision.py
sinohqb fe3399297c feat(intelligent-eval): implement decision logic and e2e flow (ticket 04)
- Add decision.py with worker decision logic (execute_session/wait/start_analysis)
- Implement time slot parsing and current slot detection
- Implement session deficit calculation per time slot
- Implement high severity issue detection
- Implement eval completion detection
- Add 12 unit tests for decision logic
- Add 2 end-to-end tests for complete lifecycle

All 798 tests passing.
2026-08-12 10:10:42 +08:00

287 lines
9.2 KiB
Python

"""Unit tests for worker decision logic."""
from datetime import timedelta
import pytest
from sqlmodel import Session
from agenteval.intelligent_eval.decision import DecisionType, is_eval_completed, make_decision
from agenteval.intelligent_eval.models import IntelligentEvalStatus
from agenteval.storage.db import IntelligentEvalDB, IntelligentEvalSessionDB, utc_now
def test_decision_wait_not_executing(db_session: Session):
"""Test decision is WAIT when eval is not executing."""
eval_db = IntelligentEvalDB(
name="test",
target_id="target1",
status=IntelligentEvalStatus.COMPLETED.value,
)
db_session.add(eval_db)
db_session.commit()
decision = make_decision(eval_db, db_session)
assert decision.decision_type == DecisionType.WAIT
assert "不在执行中" in decision.reason
def test_decision_wait_no_plan(db_session: Session):
"""Test decision is WAIT when eval has no plan."""
eval_db = IntelligentEvalDB(
name="test",
target_id="target1",
status=IntelligentEvalStatus.EXECUTING.value,
started_at=utc_now(),
)
db_session.add(eval_db)
db_session.commit()
decision = make_decision(eval_db, db_session)
assert decision.decision_type == DecisionType.WAIT
assert "缺少计划" in decision.reason
def test_decision_start_analysis_all_completed(db_session: Session):
"""Test decision is START_ANALYSIS when all sessions completed."""
eval_db = IntelligentEvalDB(
name="test",
target_id="target1",
status=IntelligentEvalStatus.EXECUTING.value,
started_at=utc_now() - timedelta(hours=10),
)
eval_db.set_plan({
"time_distribution": [{"time_slot": "8-10h", "sessions": 2}],
"estimated_sessions": 2,
})
db_session.add(eval_db)
db_session.commit()
# Add 2 completed sessions
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()
decision = make_decision(eval_db, db_session)
assert decision.decision_type == DecisionType.START_ANALYSIS
assert "所有 2 个会话已完成" in decision.reason
def test_decision_execute_session_slot_deficit(db_session: Session):
"""Test decision is EXECUTE_SESSION when current slot has deficit."""
eval_db = IntelligentEvalDB(
name="test",
target_id="target1",
status=IntelligentEvalStatus.EXECUTING.value,
started_at=utc_now() - timedelta(hours=8, minutes=30), # 8.5 hours ago
)
eval_db.set_plan({
"time_distribution": [{"time_slot": "8-10h", "sessions": 2}],
"estimated_sessions": 2,
})
db_session.add(eval_db)
db_session.commit()
# Add 1 session created within the 8-10h slot (deficit = 1)
# Slot starts at started_at + 8h = 0.5h ago
session_db = IntelligentEvalSessionDB(
eval_id=eval_db.id,
target_id="target1",
status="running",
created_at=utc_now() - timedelta(minutes=20), # 20 minutes ago, within slot
)
db_session.add(session_db)
db_session.commit()
decision = make_decision(eval_db, db_session)
assert decision.decision_type == DecisionType.EXECUTE_SESSION
assert "欠账 1 个会话" in decision.reason
assert decision.context["current_slot"] == "8-10h"
assert decision.context["deficit"] == 1
def test_decision_execute_session_high_severity(db_session: Session):
"""Test decision is EXECUTE_SESSION when high severity issue found."""
eval_db = IntelligentEvalDB(
name="test",
target_id="target1",
status=IntelligentEvalStatus.EXECUTING.value,
started_at=utc_now() - timedelta(hours=8, minutes=30),
)
eval_db.set_plan({
"time_distribution": [{"time_slot": "8-10h", "sessions": 2}],
"estimated_sessions": 3, # Not all completed yet
})
db_session.add(eval_db)
db_session.commit()
# Add 2 completed sessions within the slot (no deficit)
for _ in range(2):
session_db = IntelligentEvalSessionDB(
eval_id=eval_db.id,
target_id="target1",
status="completed",
created_at=utc_now() - timedelta(minutes=20), # Within slot
)
# One with high severity
session_db.set_verdict({"severity": "high", "issues": ["critical bug"]})
db_session.add(session_db)
db_session.commit()
decision = make_decision(eval_db, db_session)
assert decision.decision_type == DecisionType.EXECUTE_SESSION
assert "高严重度问题" in decision.reason
def test_decision_wait_no_deficit(db_session: Session):
"""Test decision is WAIT when no deficit in current slot."""
eval_db = IntelligentEvalDB(
name="test",
target_id="target1",
status=IntelligentEvalStatus.EXECUTING.value,
started_at=utc_now() - timedelta(hours=8, minutes=30),
)
eval_db.set_plan({
"time_distribution": [{"time_slot": "8-10h", "sessions": 2}],
"estimated_sessions": 3, # Not all completed yet
})
db_session.add(eval_db)
db_session.commit()
# Add 2 sessions within the slot (no deficit)
for _ in range(2):
session_db = IntelligentEvalSessionDB(
eval_id=eval_db.id,
target_id="target1",
status="running",
created_at=utc_now() - timedelta(minutes=20), # Within slot
)
db_session.add(session_db)
db_session.commit()
decision = make_decision(eval_db, db_session)
assert decision.decision_type == DecisionType.WAIT
assert "无欠账" in decision.reason
def test_decision_wait_outside_slots(db_session: Session):
"""Test decision is WAIT when current time is outside all slots."""
eval_db = IntelligentEvalDB(
name="test",
target_id="target1",
status=IntelligentEvalStatus.EXECUTING.value,
started_at=utc_now() - timedelta(hours=5), # 5 hours ago, outside 8-10h
)
eval_db.set_plan({
"time_distribution": [{"time_slot": "8-10h", "sessions": 2}],
"estimated_sessions": 2,
})
db_session.add(eval_db)
db_session.commit()
decision = make_decision(eval_db, db_session)
assert decision.decision_type == DecisionType.WAIT
assert "不在任何时段内" in decision.reason
def test_is_eval_completed_not_executing(db_session: Session):
"""Test is_eval_completed returns False when eval is not executing."""
eval_db = IntelligentEvalDB(
name="test",
target_id="target1",
status=IntelligentEvalStatus.COMPLETED.value,
)
db_session.add(eval_db)
db_session.commit()
assert is_eval_completed(eval_db, db_session) is False
def test_is_eval_completed_no_plan(db_session: Session):
"""Test is_eval_completed returns False when eval has no plan."""
eval_db = IntelligentEvalDB(
name="test",
target_id="target1",
status=IntelligentEvalStatus.EXECUTING.value,
)
db_session.add(eval_db)
db_session.commit()
assert is_eval_completed(eval_db, db_session) is False
def test_is_eval_completed_sessions_not_finished(db_session: Session):
"""Test is_eval_completed returns False when not all sessions completed."""
eval_db = IntelligentEvalDB(
name="test",
target_id="target1",
status=IntelligentEvalStatus.EXECUTING.value,
)
eval_db.set_plan({"estimated_sessions": 2})
db_session.add(eval_db)
db_session.commit()
# Add only 1 completed session
session_db = IntelligentEvalSessionDB(
eval_id=eval_db.id,
target_id="target1",
status="completed",
)
db_session.add(session_db)
db_session.commit()
assert is_eval_completed(eval_db, db_session) is False
def test_is_eval_completed_no_report(db_session: Session):
"""Test is_eval_completed returns False when report not submitted."""
eval_db = IntelligentEvalDB(
name="test",
target_id="target1",
status=IntelligentEvalStatus.EXECUTING.value,
)
eval_db.set_plan({"estimated_sessions": 2})
db_session.add(eval_db)
db_session.commit()
# Add 2 completed sessions
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()
assert is_eval_completed(eval_db, db_session) is False
def test_is_eval_completed_true(db_session: Session):
"""Test is_eval_completed returns True when all conditions met."""
eval_db = IntelligentEvalDB(
name="test",
target_id="target1",
status=IntelligentEvalStatus.EXECUTING.value,
)
eval_db.set_plan({"estimated_sessions": 2})
eval_db.set_report({"summary": "test report"})
db_session.add(eval_db)
db_session.commit()
# Add 2 completed sessions
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()
assert is_eval_completed(eval_db, db_session) is True