| """ |
| Test end-to-end integration flows. |
| |
| Tests cover: |
| - EpisodeService → EventBus → LearningEngine flow |
| - MementoEngine full lifecycle |
| - AlphaEvolverEngine full lifecycle |
| - EvolutionEngine monitoring and optimization |
| - FitnessService + AdvisorService integration |
| """ |
|
|
| import pytest |
| from unittest.mock import AsyncMock, MagicMock |
|
|
| from core.auto_dev.event_hooks import EventBus, TaskEvent, SkillExecutionEvent |
|
|
|
|
| class TestIntegrationEventFlow: |
| """Test EpisodeService → EventBus → LearningEngine flow.""" |
|
|
| @pytest.mark.asyncio |
| async def test_full_event_chain(self, sample_task_event): |
| """Test full event chain from emit to handler.""" |
| bus = EventBus() |
| handler_called = [] |
|
|
| async def handler(event): |
| handler_called.append(event.episode_id) |
|
|
| bus.on_task_fail(handler) |
|
|
| await bus.emit_task_fail(sample_task_event) |
|
|
| assert len(handler_called) == 1 |
| assert handler_called[0] == sample_task_event.episode_id |
|
|
|
|
| class TestIntegrationMementoEngineLifecycle: |
| """Test MementoEngine full lifecycle (episode → skill).""" |
|
|
| @pytest.mark.asyncio |
| async def test_analyzes_failed_episode(self, mock_auto_dev_llm, auto_dev_db_session, sample_episode): |
| """Test analyzes failed episode.""" |
| from core.auto_dev.memento_engine import MementoEngine |
|
|
| engine = MementoEngine(db=auto_dev_db_session, llm_service=mock_auto_dev_llm) |
|
|
| result = await engine.analyze_episode(sample_episode.id) |
|
|
| assert "episode_id" in result |
|
|
| @pytest.mark.asyncio |
| async def test_proposes_skill_code(self, mock_auto_dev_llm, auto_dev_db_session): |
| """Test proposes skill code.""" |
| from core.auto_dev.memento_engine import MementoEngine |
|
|
| engine = MementoEngine(db=auto_dev_db_session, llm_service=mock_auto_dev_llm) |
|
|
| code = await engine.propose_code_change( |
| context={"task_description": "Test task", "error_trace": "Error"} |
| ) |
|
|
| assert isinstance(code, str) |
| assert len(code) > 0 |
|
|
| @pytest.mark.asyncio |
| async def test_validates_in_sandbox(self, mock_sandbox, auto_dev_db_session): |
| """Test validates in sandbox.""" |
| from core.auto_dev.memento_engine import MementoEngine |
|
|
| engine = MementoEngine(db=auto_dev_db_session, sandbox=mock_sandbox) |
|
|
| result = await engine.validate_change( |
| code="print('test')", |
| test_inputs=[{}], |
| tenant_id="tenant-001", |
| ) |
|
|
| assert "passed" in result |
|
|
| @pytest.mark.asyncio |
| async def test_promotes_to_community_skill(self, mock_auto_dev_llm, mock_sandbox, auto_dev_db_session, sample_tenant_id, sample_agent_id): |
| """Test promotes to CommunitySkill.""" |
| from core.auto_dev.memento_engine import MementoEngine |
| from core.auto_dev.models import SkillCandidate |
|
|
| engine = MementoEngine(db=auto_dev_db_session, llm_service=mock_auto_dev_llm, sandbox=mock_sandbox) |
|
|
| |
| candidate = SkillCandidate( |
| tenant_id=sample_tenant_id, |
| agent_id=sample_agent_id, |
| skill_name="test_skill", |
| generated_code="def test(): pass", |
| validation_status="validated", |
| ) |
| auto_dev_db_session.add(candidate) |
| auto_dev_db_session.commit() |
|
|
| |
| |
| assert hasattr(engine, "promote_skill") |
|
|
|
|
| class TestIntegrationAlphaEvolverEngineLifecycle: |
| """Test AlphaEvolverEngine full lifecycle (episode → variant).""" |
|
|
| @pytest.mark.asyncio |
| async def test_analyzes_successful_episode(self, mock_auto_dev_llm, auto_dev_db_session, sample_episode): |
| """Test analyzes successful episode.""" |
| from core.auto_dev.alpha_evolver_engine import AlphaEvolverEngine |
|
|
| engine = AlphaEvolverEngine(db=auto_dev_db_session, llm_service=mock_auto_dev_llm) |
|
|
| result = await engine.analyze_episode(sample_episode.id) |
|
|
| assert "episode_id" in result |
|
|
| @pytest.mark.asyncio |
| async def test_generates_mutations(self, mock_auto_dev_llm, auto_dev_db_session, sample_tenant_id): |
| """Test generates mutations.""" |
| from core.auto_dev.alpha_evolver_engine import AlphaEvolverEngine |
|
|
| engine = AlphaEvolverEngine(db=auto_dev_db_session, llm_service=mock_auto_dev_llm) |
|
|
| mutation = await engine.generate_tool_mutation( |
| tenant_id=sample_tenant_id, |
| tool_name="test_tool", |
| parent_tool_id=None, |
| base_code="def test(): pass", |
| mutation_prompt="Optimize", |
| ) |
|
|
| assert mutation.id is not None |
|
|
| @pytest.mark.asyncio |
| async def test_validates_variants(self, mock_sandbox, auto_dev_db_session, sample_tenant_id): |
| """Test validates variants.""" |
| from core.auto_dev.alpha_evolver_engine import AlphaEvolverEngine |
| from core.auto_dev.models import ToolMutation |
|
|
| engine = AlphaEvolverEngine(db=auto_dev_db_session, sandbox=mock_sandbox) |
|
|
| mutation = ToolMutation( |
| tenant_id=sample_tenant_id, |
| tool_name="test", |
| mutated_code="x = 1", |
| sandbox_status="pending", |
| ) |
| auto_dev_db_session.add(mutation) |
| auto_dev_db_session.commit() |
|
|
| result = await engine.sandbox_execute_mutation( |
| mutation_id=mutation.id, |
| tenant_id=sample_tenant_id, |
| inputs={}, |
| ) |
|
|
| assert "success" in result |
|
|
| @pytest.mark.asyncio |
| async def test_spawns_workflow_variant(self, auto_dev_db_session, sample_tenant_id, sample_agent_id): |
| """Test spawns WorkflowVariant.""" |
| from core.auto_dev.alpha_evolver_engine import AlphaEvolverEngine |
|
|
| engine = AlphaEvolverEngine(db=auto_dev_db_session) |
|
|
| variant = engine.spawn_workflow_variant( |
| tenant_id=sample_tenant_id, |
| agent_id=sample_agent_id, |
| workflow_def={"steps": []}, |
| parent_variant_id=None, |
| ) |
|
|
| assert variant.id is not None |
|
|
|
|
| class TestIntegrationEvolutionEngineMonitoring: |
| """Test EvolutionEngine monitoring and optimization.""" |
|
|
| def test_monitors_variant_performance(self, auto_dev_db_session, sample_workflow_variant): |
| """Test monitors WorkflowVariant performance.""" |
| from core.auto_dev.evolution_engine import EvolutionEngine |
|
|
| engine = EvolutionEngine(db=auto_dev_db_session) |
|
|
| |
| assert engine.db == auto_dev_db_session |
|
|
| @pytest.mark.asyncio |
| async def test_detects_trigger_conditions(self, auto_dev_db_session, monkeypatch): |
| """Test detects trigger conditions.""" |
| from core.auto_dev.evolution_engine import EvolutionEngine |
|
|
| engine = EvolutionEngine(db=auto_dev_db_session) |
|
|
| |
| monkeypatch.setattr(engine, "_should_optimize", lambda agent_id, tenant_id: True) |
|
|
| |
| monkeypatch.setattr(engine, "_get_skill_code", lambda skill_id, tenant_id: "def test_skill():\n pass") |
|
|
| |
| mock_evolver = MagicMock() |
| mock_mutation = MagicMock() |
| mock_mutation.id = "mutation-001" |
| mock_evolver.generate_tool_mutation = AsyncMock(return_value=mock_mutation) |
| mock_evolver.sandbox_execute_mutation = AsyncMock(return_value={"success": True}) |
|
|
| import sys |
| original_module = sys.modules.get("core.auto_dev.alpha_evolver_engine") |
|
|
| class MockAlphaEvolverEngine: |
| def __init__(self, db): |
| pass |
|
|
| sys.modules["core.auto_dev.alpha_evolver_engine"] = MockAlphaEvolverEngine |
| sys.modules["core.auto_dev.alpha_evolver_engine"].AlphaEvolverEngine = lambda db: mock_evolver |
|
|
| try: |
| event = SkillExecutionEvent( |
| execution_id="exec-001", |
| agent_id="agent-001", |
| tenant_id="tenant-001", |
| skill_id="skill-001", |
| skill_name="test_skill", |
| execution_seconds=10.0, |
| token_usage=1000, |
| success=True, |
| ) |
|
|
| await engine.process_execution(event) |
|
|
| |
| assert mock_evolver.generate_tool_mutation.called |
| finally: |
| if original_module: |
| sys.modules["core.auto_dev.alpha_evolver_engine"] = original_module |
| else: |
| sys.modules.pop("core.auto_dev.alpha_evolver_engine", None) |
|
|
|
|
| class TestIntegrationServiceIntegration: |
| """Test FitnessService + AdvisorService integration.""" |
|
|
| def test_fitness_evaluates_variants(self, auto_dev_db_session, sample_workflow_variant): |
| """Test FitnessService evaluates variants.""" |
| from core.auto_dev.fitness_service import FitnessService |
|
|
| service = FitnessService(auto_dev_db_session) |
|
|
| proxy_signals = { |
| "syntax_error": False, |
| "execution_success": True, |
| } |
|
|
| score = service.evaluate_initial_proxy( |
| sample_workflow_variant.id, |
| sample_workflow_variant.tenant_id, |
| proxy_signals, |
| ) |
|
|
| assert 0.0 <= score <= 1.0 |
|
|
| @pytest.mark.asyncio |
| async def test_advisor_generates_guidance(self, mock_auto_dev_llm, auto_dev_db_session, sample_tenant_id): |
| """Test AdvisorService generates guidance.""" |
| from core.auto_dev.advisor_service import AdvisorService |
|
|
| service = AdvisorService(db=auto_dev_db_session, llm_service=mock_auto_dev_llm) |
|
|
| result = await service.generate_guidance(tenant_id=sample_tenant_id) |
|
|
| assert "status" in result |
| assert result["status"] == "success" |
|
|
| @pytest.mark.asyncio |
| async def test_end_to_end_optimization_flow(self, mock_auto_dev_llm, mock_sandbox, auto_dev_db_session, sample_tenant_id, sample_agent_id): |
| """Test end-to-end optimization flow.""" |
| from core.auto_dev.alpha_evolver_engine import AlphaEvolverEngine |
| from core.auto_dev.fitness_service import FitnessService |
| from core.auto_dev.advisor_service import AdvisorService |
|
|
| |
| evolver = AlphaEvolverEngine( |
| db=auto_dev_db_session, |
| llm_service=mock_auto_dev_llm, |
| sandbox=mock_sandbox, |
| ) |
|
|
| mutation = await evolver.generate_tool_mutation( |
| tenant_id=sample_tenant_id, |
| tool_name="test_tool", |
| parent_tool_id=None, |
| base_code="def test(): pass", |
| mutation_prompt="Optimize", |
| ) |
|
|
| |
| variant = evolver.spawn_workflow_variant( |
| tenant_id=sample_tenant_id, |
| agent_id=sample_agent_id, |
| workflow_def={"optimized": True}, |
| parent_variant_id=None, |
| ) |
|
|
| |
| fitness_service = FitnessService(auto_dev_db_session) |
|
|
| proxy_signals = { |
| "syntax_error": False, |
| "execution_success": True, |
| } |
|
|
| score = fitness_service.evaluate_initial_proxy( |
| variant.id, |
| variant.tenant_id, |
| proxy_signals, |
| ) |
|
|
| |
| advisor = AdvisorService(db=auto_dev_db_session, llm_service=mock_auto_dev_llm) |
|
|
| guidance = await advisor.generate_guidance(tenant_id=sample_tenant_id) |
|
|
| |
| assert mutation.id is not None |
| assert variant.id is not None |
| assert 0.0 <= score <= 1.0 |
| assert guidance["status"] == "success" |
|
|