Files
wecom_it_smart_desk/backend/tests/test_automation_session_manager.py
T

308 lines
9.3 KiB
Python
Raw Normal View History

# =============================================================================
# 阶段5 自动化 - 会话管理服务单元测试
# =============================================================================
# 测试范围:session_manager.py - 会话生命周期、状态机、关单判定
# =============================================================================
import pytest
from unittest.mock import AsyncMock, MagicMock, patch
from datetime import datetime, timezone
from app.services.automation.session_manager import AutoSessionService
from app.models.automation import AutoSession, AutoAction
class TestAutoSessionService:
"""会话管理服务测试用例"""
@pytest.mark.asyncio
async def test_create_session(self, db_session):
"""测试创建会话"""
# Arrange
svc = AutoSessionService(db_session)
# Act
session = await svc.create_session(
conversation_id="conv_001",
employee_id="emp_001",
description="测试会话",
mode="real_exec"
)
# Assert
assert session.id is not None
assert session.conversation_id == "conv_001"
assert session.employee_id == "emp_001"
assert session.status == "created"
assert session.mode == "real_exec"
assert session.title == "测试会话"
@pytest.mark.asyncio
async def test_get_session(self, db_session):
"""测试获取会话"""
# Arrange - 先创建会话
svc = AutoSessionService(db_session)
created = await svc.create_session(
conversation_id="conv_002",
employee_id="emp_002",
description="查询测试"
)
await db_session.flush()
# Act
session = await svc.get_session(created.id)
# Assert
assert session is not None
assert session.id == created.id
assert session.employee_id == "emp_002"
@pytest.mark.asyncio
async def test_get_session_not_found(self, db_session):
"""测试获取不存在的会话返回 None"""
# Arrange
svc = AutoSessionService(db_session)
# Act
session = await svc.get_session("nonexistent_id")
# Assert
assert session is None
@pytest.mark.asyncio
async def test_list_sessions_with_filters(self, db_session):
"""测试列出会话(支持过滤)"""
# Arrange - 创建多个会话
svc = AutoSessionService(db_session)
await svc.create_session(
employee_id="emp_001",
description="会话1"
)
await svc.create_session(
employee_id="emp_001",
description="会话2"
)
await svc.create_session(
employee_id="emp_002",
description="会话3"
)
await db_session.flush()
# Act - 按 employee_id 过滤
sessions = await svc.list_sessions(employee_id="emp_001")
# Assert
assert len(sessions) == 2
assert all(s.employee_id == "emp_001" for s in sessions)
@pytest.mark.asyncio
async def test_list_sessions_by_status(self, db_session):
"""测试按状态过滤会话"""
# Arrange
svc = AutoSessionService(db_session)
# 创建一个 running 会话
session = await svc.create_session(
employee_id="emp_001",
description="测试"
)
session.status = "running"
await db_session.flush()
# Act
running = await svc.list_sessions(status="running")
closed = await svc.list_sessions(status="closed")
# Assert
assert len(running) >= 1
assert all(s.status == "running" for s in running)
assert len(closed) == 0
@pytest.mark.asyncio
async def test_takeover(self, db_session):
"""测试转人工接管"""
# Arrange
svc = AutoSessionService(db_session)
session = await svc.create_session(
employee_id="emp_001",
description="测试转人工"
)
await db_session.flush()
# Act
result = await svc.takeover(
session_id=session.id,
agent_id="agent_001",
note="我来接管处理"
)
# Assert
assert result.status == "handoff"
assert result.agent_id == "agent_001"
assert result.closed_by == "agent_001"
@pytest.mark.asyncio
async def test_resolve_feedback_satisfied(self, db_session):
"""测试反馈处理 - 满意则关单"""
# Arrange
svc = AutoSessionService(db_session)
session = await svc.create_session(
employee_id="emp_001",
description="测试反馈"
)
await db_session.flush()
# Act - 满意
result = await svc.resolve_feedback(
session_id=session.id,
satisfied=True,
note="处理得很好"
)
# Assert
assert result.status == "closed"
assert result.closed_by == session.employee_id
@pytest.mark.asyncio
async def test_resolve_feedback_unsatisfied(self, db_session):
"""测试反馈处理 - 不满意则转人工"""
# Arrange
svc = AutoSessionService(db_session)
session = await svc.create_session(
employee_id="emp_001",
description="测试反馈"
)
await db_session.flush()
# Act - 不满意
result = await svc.resolve_feedback(
session_id=session.id,
satisfied=False,
note="没有解决我的问题"
)
# Assert
assert result.status == "handoff"
assert result.closed_by == "employee(reject)"
@pytest.mark.asyncio
async def test_auto_close_resolved_session(self, db_session):
"""测试静默关单 - 仅 resolved 态可关"""
# Arrange
svc = AutoSessionService(db_session)
session = await svc.create_session(
employee_id="emp_001",
description="测试关单"
)
# Case 1: 非 resolved 状态不应关单
session.status = "running"
await db_session.flush()
await svc.auto_close(session.id)
await db_session.refresh(session)
assert session.status == "running" # 状态未变
# Case 2: resolved 状态应关单
session.status = "resolved"
await db_session.flush()
await svc.auto_close(session.id)
await db_session.refresh(session)
assert session.status == "closed"
assert session.closed_by == "system(auto)"
@pytest.mark.asyncio
async def test_get_session_detail_with_actions(self, db_session):
"""测试获取会话详情(含动作列表)"""
# Arrange
svc = AutoSessionService(db_session)
session = await svc.create_session(
employee_id="emp_001",
description="测试详情"
)
await db_session.flush()
# 添加动作
action1 = AutoAction(
session_id=session.id,
action_index=0,
action_type="terminal_locate",
status="pending",
title="定位终端"
)
action2 = AutoAction(
session_id=session.id,
action_index=1,
action_type="virus_scan",
status="success",
title="病毒扫描"
)
db_session.add(action1)
db_session.add(action2)
await db_session.flush()
# Act
detail = await svc.get_session_detail(session.id)
# Assert
assert detail is not None
assert detail["session"].id == session.id
assert len(detail["actions"]) == 2
# 验证动作按 action_index 排序
assert detail["actions"][0].action_type == "terminal_locate"
assert detail["actions"][1].action_type == "virus_scan"
@pytest.mark.asyncio
async def test_get_session_detail_not_found(self, db_session):
"""测试获取不存在的会话详情返回 None"""
# Arrange
svc = AutoSessionService(db_session)
# Act
detail = await svc.get_session_detail("nonexistent_id")
# Assert
assert detail is None
@pytest.mark.asyncio
async def test_session_status_flow(self, db_session):
"""测试会话状态流转"""
# Arrange
svc = AutoSessionService(db_session)
session = await svc.create_session(
employee_id="emp_001",
description="状态流转测试"
)
await db_session.flush()
# Assert - 初始状态
assert session.status == "created"
# 模拟 start 后的状态变化
session.status = "running"
await db_session.flush()
await db_session.refresh(session)
assert session.status == "running"
# 审批暂停
session.status = "paused"
await db_session.flush()
await db_session.refresh(session)
assert session.status == "paused"
# 处置成功
session.status = "resolved"
await db_session.flush()
await db_session.refresh(session)
assert session.status == "resolved"
# 静默关单
session.status = "closed"
await db_session.flush()
await db_session.refresh(session)
assert session.status == "closed"