Add comprehensive unit tests for all agent service components
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
186
tests/test_registry.py
Normal file
186
tests/test_registry.py
Normal file
@@ -0,0 +1,186 @@
|
||||
"""Unit tests for AgentRegistry."""
|
||||
import pytest
|
||||
from unittest.mock import AsyncMock, MagicMock
|
||||
from agent_service.agents.registry import AgentRegistry
|
||||
|
||||
|
||||
def _make_registry():
|
||||
return AgentRegistry()
|
||||
|
||||
|
||||
def _make_agent(name='test_agent'):
|
||||
agent = MagicMock()
|
||||
agent.name = name
|
||||
return agent
|
||||
|
||||
|
||||
# ── register / get_agent_instance ───────────────────────────────────────────
|
||||
|
||||
def test_register_stores_instance():
|
||||
reg = _make_registry()
|
||||
agent = _make_agent()
|
||||
reg.register('test_agent', agent)
|
||||
assert reg.get_agent_instance('test_agent') is agent
|
||||
|
||||
|
||||
def test_register_missing_returns_none():
|
||||
reg = _make_registry()
|
||||
assert reg.get_agent_instance('nonexistent') is None
|
||||
|
||||
|
||||
def test_register_activates_agent():
|
||||
reg = _make_registry()
|
||||
reg.register('test_agent', _make_agent())
|
||||
assert 'test_agent' in reg._active
|
||||
|
||||
|
||||
def test_register_assigns_default_capability():
|
||||
reg = _make_registry()
|
||||
reg.register('test_agent', _make_agent())
|
||||
assert reg._capabilities.get('test_agent')
|
||||
|
||||
|
||||
def test_register_known_agent_uses_default_description():
|
||||
reg = _make_registry()
|
||||
reg.register('crm_agent', _make_agent('crm_agent'))
|
||||
assert 'crm' in reg._capabilities['crm_agent'].lower() or \
|
||||
'lead' in reg._capabilities['crm_agent'].lower()
|
||||
|
||||
|
||||
def test_register_multiple_agents():
|
||||
reg = _make_registry()
|
||||
reg.register('crm_agent', _make_agent('crm_agent'))
|
||||
reg.register('sales_agent', _make_agent('sales_agent'))
|
||||
assert len(reg._agents) == 2
|
||||
|
||||
|
||||
# ── is_active ────────────────────────────────────────────────────────────────
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_is_active_after_register():
|
||||
reg = _make_registry()
|
||||
reg.register('crm_agent', _make_agent())
|
||||
assert await reg.is_active('crm_agent') is True
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_is_active_unknown_agent():
|
||||
reg = _make_registry()
|
||||
assert await reg.is_active('ghost_agent') is False
|
||||
|
||||
|
||||
# ── get_active_agents ────────────────────────────────────────────────────────
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_active_agents_returns_only_registered():
|
||||
reg = _make_registry()
|
||||
reg.register('crm_agent', _make_agent())
|
||||
reg._active.add('ghost_agent') # active but no instance
|
||||
result = await reg.get_active_agents()
|
||||
keys = {r['agent_key'] for r in result}
|
||||
assert 'crm_agent' in keys
|
||||
assert 'ghost_agent' not in keys
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_active_agents_includes_capabilities():
|
||||
reg = _make_registry()
|
||||
reg.register('crm_agent', _make_agent())
|
||||
result = await reg.get_active_agents()
|
||||
assert any('capabilities_summary' in r for r in result)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_active_agents_empty_registry():
|
||||
reg = _make_registry()
|
||||
result = await reg.get_active_agents()
|
||||
assert result == []
|
||||
|
||||
|
||||
# ── get_all ──────────────────────────────────────────────────────────────────
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_all_includes_all_registered():
|
||||
reg = _make_registry()
|
||||
reg.register('crm_agent', _make_agent())
|
||||
reg.register('sales_agent', _make_agent())
|
||||
result = await reg.get_all()
|
||||
names = {r['name'] for r in result}
|
||||
assert 'crm_agent' in names
|
||||
assert 'sales_agent' in names
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_all_marks_active_flag():
|
||||
reg = _make_registry()
|
||||
reg.register('crm_agent', _make_agent())
|
||||
result = await reg.get_all()
|
||||
crm = next(r for r in result if r['name'] == 'crm_agent')
|
||||
assert crm['active'] is True
|
||||
assert crm['has_instance'] is True
|
||||
|
||||
|
||||
# ── sync ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_sync_replaces_active_set():
|
||||
reg = _make_registry()
|
||||
reg.register('crm_agent', _make_agent())
|
||||
reg.register('sales_agent', _make_agent())
|
||||
await reg.sync(['sales_agent'])
|
||||
assert await reg.is_active('sales_agent') is True
|
||||
assert await reg.is_active('crm_agent') is False
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_sync_with_empty_list_deactivates_all():
|
||||
reg = _make_registry()
|
||||
reg.register('crm_agent', _make_agent())
|
||||
await reg.sync([])
|
||||
assert await reg.is_active('crm_agent') is False
|
||||
|
||||
|
||||
# ── load_from_odoo ───────────────────────────────────────────────────────────
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_load_from_odoo_sets_active_agents():
|
||||
reg = _make_registry()
|
||||
odoo = MagicMock()
|
||||
odoo.search_read = AsyncMock(return_value=[
|
||||
{'agent_name': 'crm_agent', 'domain': 'CRM leads', 'backend': 'local'},
|
||||
{'agent_name': 'sales_agent', 'domain': '', 'backend': 'cloud'},
|
||||
])
|
||||
await reg.load_from_odoo(odoo)
|
||||
assert 'crm_agent' in reg._active
|
||||
assert 'sales_agent' in reg._active
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_load_from_odoo_uses_domain_when_present():
|
||||
reg = _make_registry()
|
||||
odoo = MagicMock()
|
||||
odoo.search_read = AsyncMock(return_value=[
|
||||
{'agent_name': 'crm_agent', 'domain': 'Custom CRM description', 'backend': 'local'},
|
||||
])
|
||||
await reg.load_from_odoo(odoo)
|
||||
assert reg._capabilities['crm_agent'] == 'Custom CRM description'
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_load_from_odoo_falls_back_to_default_when_no_domain():
|
||||
reg = _make_registry()
|
||||
odoo = MagicMock()
|
||||
odoo.search_read = AsyncMock(return_value=[
|
||||
{'agent_name': 'crm_agent', 'domain': '', 'backend': 'local'},
|
||||
])
|
||||
await reg.load_from_odoo(odoo)
|
||||
assert reg._capabilities.get('crm_agent')
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_load_from_odoo_handles_exception_gracefully():
|
||||
reg = _make_registry()
|
||||
odoo = MagicMock()
|
||||
odoo.search_read = AsyncMock(side_effect=Exception('DB error'))
|
||||
await reg.load_from_odoo(odoo)
|
||||
assert reg._active == set()
|
||||
Reference in New Issue
Block a user