Files
cleverclaude-core/tests/conftest.py
T
2025-08-10 12:00:13 -04:00

191 lines
5.6 KiB
Python

"""Pytest configuration and shared fixtures for CleverClaude tests."""
import asyncio
import tempfile
from collections.abc import AsyncGenerator, Generator
from pathlib import Path
from unittest.mock import AsyncMock, MagicMock
import pytest
import pytest_asyncio
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.pool import StaticPool
from cleverclaude.config.settings import Settings
from cleverclaude.database.models import Base
@pytest.fixture(scope="session")
def event_loop():
"""Create an instance of the default event loop for the test session."""
loop = asyncio.new_event_loop()
yield loop
loop.close()
@pytest.fixture
def temp_dir() -> Generator[Path]:
"""Create a temporary directory for test files."""
with tempfile.TemporaryDirectory(prefix="cleverclaude_test_") as temp_path:
yield Path(temp_path)
@pytest.fixture
def test_settings(temp_dir: Path) -> Settings:
"""Create test settings with temporary directories."""
config_dir = temp_dir / ".cleverclaude"
config_dir.mkdir(exist_ok=True)
return Settings(
app=Settings.AppConfig(name="CleverClaude Test", version="2.0.0-test", environment="testing", debug=True),
database=Settings.DatabaseConfig(url=f"sqlite+aiosqlite:///{config_dir}/test.db", echo=False),
redis=Settings.RedisConfig(
url="redis://localhost:6379/15" # Test database
),
agents=Settings.AgentsConfig(max_agents=10, default_timeout=30, health_check_interval=5),
swarm=Settings.SwarmConfig(default_topology="mesh", max_swarm_size=5, coordination_timeout=30),
api=Settings.APIConfig(
host="127.0.0.1",
port=8080, # Different port for testing
docs_enabled=False,
),
monitoring=Settings.MonitoringConfig(metrics_enabled=False, log_level="DEBUG", log_format="json"),
)
@pytest_asyncio.fixture
async def async_engine(test_settings: Settings):
"""Create async SQLAlchemy engine for testing."""
engine = create_async_engine(
test_settings.database.url,
echo=test_settings.database.echo,
connect_args={"check_same_thread": False},
poolclass=StaticPool,
)
# Create all tables
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
yield engine
# Clean up
await engine.dispose()
@pytest_asyncio.fixture
async def async_session(async_engine) -> AsyncGenerator[AsyncSession]:
"""Create async database session for testing."""
async with AsyncSession(async_engine, expire_on_commit=False) as session:
yield session
@pytest.fixture
def mock_redis():
"""Create a mock Redis client."""
mock = MagicMock()
mock.get = AsyncMock()
mock.set = AsyncMock()
mock.delete = AsyncMock()
mock.exists = AsyncMock()
mock.keys = AsyncMock()
mock.expire = AsyncMock()
mock.ping = AsyncMock(return_value=True)
return mock
@pytest.fixture
def mock_agent():
"""Create a mock agent for testing."""
mock = AsyncMock()
mock.agent_id = "test_agent_123"
mock.name = "Test Agent"
mock.agent_type = "researcher"
mock.status = "active"
mock.capabilities = {"research", "analysis"}
mock.created_at = "2024-01-01T12:00:00Z"
mock.health_status = {"cpu_usage": 25.5, "memory_usage": 150.2, "task_count": 3, "status": "healthy"}
return mock
@pytest.fixture
def mock_swarm():
"""Create a mock swarm for testing."""
mock = AsyncMock()
mock.swarm_id = "test_swarm_456"
mock.name = "Test Swarm"
mock.topology = "mesh"
mock.state = "active"
mock.agents = []
mock.tasks = []
mock.created_at = "2024-01-01T12:00:00Z"
mock.metrics = {"total_agents": 3, "active_agents": 2, "completed_tasks": 15, "efficiency_score": 85.5}
return mock
@pytest.fixture
def mock_mcp_client():
"""Create a mock MCP client for testing."""
mock = AsyncMock()
mock.is_connected = True
mock.available_tools = [
"swarm_init",
"agent_spawn",
"task_orchestrate",
"memory_usage",
"neural_train",
"performance_report",
]
mock.execute_tool = AsyncMock()
mock.get_tool_info = AsyncMock()
mock.connect = AsyncMock()
mock.disconnect = AsyncMock()
return mock
@pytest.fixture
def mock_task():
"""Create a mock task for testing."""
return {
"task_id": "test_task_789",
"type": "research_query",
"status": "pending",
"priority": "medium",
"data": {"query": "Test research query", "scope": "general", "depth": "standard"},
"created_at": "2024-01-01T12:00:00Z",
"assigned_agent": None,
"result": None,
}
@pytest.fixture(autouse=True)
def setup_test_environment(test_settings: Settings, monkeypatch):
"""Set up test environment variables."""
monkeypatch.setenv("CLEVERCLAUDE_ENVIRONMENT", "testing")
monkeypatch.setenv("CLEVERCLAUDE_DEBUG", "true")
monkeypatch.setenv("CLEVERCLAUDE_CONFIG_DIR", str(test_settings.database.url.split("///")[1].rsplit("/", 1)[0]))
# Override settings
monkeypatch.setattr("cleverclaude.config.settings.get_settings", lambda: test_settings)
@pytest.fixture
def cleanup_tasks():
"""Cleanup any remaining asyncio tasks after tests."""
yield
# Cancel any remaining tasks
tasks = [task for task in asyncio.all_tasks() if not task.done()]
for task in tasks:
task.cancel()
if tasks:
asyncio.gather(*tasks, return_exceptions=True)
# Marker definitions
pytest.mark.unit = pytest.mark.unit
pytest.mark.integration = pytest.mark.integration
pytest.mark.async_test = pytest.mark.asyncio
pytest.mark.slow = pytest.mark.slow