minions-ai-agents/tests/test_triage_agent.py

185 lines
5.9 KiB
Python

"""
Tests for Triage Agent.
Tests entity extraction and classification logic.
"""
import pytest
from unittest.mock import Mock, patch, AsyncMock
from src.agents.triage_agent import (
TriageAgent,
TriageResult,
ExtractedEntities,
Priority,
Category,
get_triage_agent
)
class TestExtractedEntities:
"""Tests for ExtractedEntities dataclass."""
def test_default_values(self):
"""Test default entity values."""
entities = ExtractedEntities()
assert entities.problem_summary == ""
assert entities.hostname is None
assert entities.category == Category.OTHER
assert entities.priority == Priority.MEDIUM
assert entities.is_urgent is False
def test_with_values(self):
"""Test entity with values."""
entities = ExtractedEntities(
hostname="srv-app01",
ip_address="192.168.1.10",
category=Category.INFRASTRUCTURE,
priority=Priority.HIGH,
is_urgent=True
)
assert entities.hostname == "srv-app01"
assert entities.priority == Priority.HIGH
assert entities.is_urgent is True
class TestTriageAgent:
"""Tests for TriageAgent class."""
@pytest.fixture
def agent(self):
"""Create a triage agent with mocked dependencies."""
# Patch at module level before creating agent
patcher1 = patch('src.agents.triage_agent.get_ollama_client')
patcher2 = patch('src.agents.triage_agent.get_financial_client')
mock_ollama = patcher1.start()
mock_financial = patcher2.start()
mock_ollama.return_value = Mock()
mock_financial.return_value = Mock()
agent = TriageAgent()
yield agent
patcher1.stop()
patcher2.stop()
def test_fallback_hostname_extraction(self, agent):
"""Test regex fallback for hostname extraction."""
content = "O servidor srv-app01 está com problema de memória"
entities = ExtractedEntities()
result = agent._fallback_extraction(content, entities)
assert result.hostname == "srv-app01"
def test_fallback_ip_extraction(self, agent):
"""Test regex fallback for IP extraction."""
content = "O servidor 192.168.1.50 não está respondendo"
entities = ExtractedEntities()
result = agent._fallback_extraction(content, entities)
assert result.ip_address == "192.168.1.50"
def test_fallback_service_extraction(self, agent):
"""Test regex fallback for service extraction."""
content = "O serviço nginx está retornando erro 502"
entities = ExtractedEntities()
result = agent._fallback_extraction(content, entities)
assert result.service_name.lower() == "nginx"
def test_urgency_detection(self, agent):
"""Test urgency keyword detection."""
content = "URGENTE: Sistema caiu e precisa de atenção imediata"
entities = ExtractedEntities(priority=Priority.MEDIUM)
result = agent._fallback_extraction(content, entities)
assert result.is_urgent is True
assert result.priority == Priority.HIGH
def test_production_detection(self, agent):
"""Test production keyword detection."""
content = "Servidor de produção com clientes afetados"
entities = ExtractedEntities(priority=Priority.MEDIUM)
result = agent._fallback_extraction(content, entities)
assert result.affects_production is True
assert result.priority == Priority.HIGH
def test_recommend_tools_with_host(self, agent):
"""Test tool recommendation with hostname."""
entities = ExtractedEntities(
hostname="srv-db01",
category=Category.DATABASE
)
tenant = Mock()
tenant.id = "tenant-001"
tools = agent._recommend_tools(entities, tenant)
assert "zabbix_get_host_status" in tools
assert "zabbix_get_problems" in tools
assert "rag_search_manuals" in tools
def test_build_reasoning(self, agent):
"""Test reasoning generation."""
entities = ExtractedEntities(
hostname="srv-app01",
category=Category.INFRASTRUCTURE,
priority=Priority.HIGH,
is_urgent=True,
affects_production=True,
problem_summary="Servidor não responde"
)
tenant = Mock()
tenant.name = "OESTEPAN"
reasoning = agent._build_reasoning(entities, tenant)
assert "OESTEPAN" in reasoning
assert "infrastructure" in reasoning
assert "high" in reasoning
assert "URGÊNCIA" in reasoning
assert "PRODUÇÃO" in reasoning
@pytest.mark.asyncio
async def test_process_ticket_without_tenant(self, agent):
"""Test ticket processing when tenant cannot be resolved."""
agent._financial.get_tenant_by_email = AsyncMock(return_value=None)
result = await agent.process_ticket(
ticket_id="TKT-001",
sender_email="unknown@unknowndomain.com",
subject="Problema",
body="Teste"
)
assert result.success is False
assert "Tenant não identificado" in result.error
class TestTriageAgentSingleton:
"""Tests for singleton."""
def test_singleton(self):
"""Test singleton returns same instance."""
import src.agents.triage_agent as module
module._triage_agent = None
with patch('src.agents.triage_agent.get_ollama_client'), \
patch('src.agents.triage_agent.get_financial_client'):
agent1 = get_triage_agent()
agent2 = get_triage_agent()
assert agent1 is agent2