From 1f2bf24a669327982eaac8185ae9f9055efa6d6d Mon Sep 17 00:00:00 2001 From: Juan Date: Mon, 11 May 2026 08:28:26 +0200 Subject: [PATCH] test(integration): happy path end-to-end con escenario MOS sin HITL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Invoca el agente real incident_analyzer (assets del repo, LLM mock) vía TestClient y comprueba status=completed, final_output y que el decision_path recorre los seis nodos del grafo. Añade conftest con la fixture integration_client (env apuntando a agents/ y policies/ del repo, caches DI limpiadas). Co-Authored-By: Claude Opus 4.7 --- tests/integration/conftest.py | 31 +++++++++++++++++++++ tests/integration/test_invoke_happy_path.py | 29 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 tests/integration/conftest.py create mode 100644 tests/integration/test_invoke_happy_path.py diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py new file mode 100644 index 0000000..244873e --- /dev/null +++ b/tests/integration/conftest.py @@ -0,0 +1,31 @@ +"""Fixtures compartidas para tests de integración.""" + +from pathlib import Path + +import pytest + +from agentforge_core.api import deps + + +@pytest.fixture +def integration_client(tmp_path: Path, monkeypatch: pytest.MonkeyPatch): # type: ignore[no-untyped-def] + """Cliente FastAPI con env apuntando a los assets reales del repo.""" + from fastapi.testclient import TestClient + + from agentforge_core.main import create_app + + repo_root = Path(__file__).parent.parent.parent + monkeypatch.setenv("DATA_DIR", str(tmp_path)) + monkeypatch.setenv("AGENTS_DIR", str(repo_root / "agents")) + monkeypatch.setenv("POLICIES_DIR", str(repo_root / "policies")) + monkeypatch.setenv("LLM_PROVIDER", "mock") + for fn in ( + deps.get_settings, + deps.get_registry, + deps.get_policy_store, + deps.get_orchestrator, + deps.get_llm_provider, + deps.get_guardrail_engine, + ): + fn.cache_clear() + return TestClient(create_app()) diff --git a/tests/integration/test_invoke_happy_path.py b/tests/integration/test_invoke_happy_path.py new file mode 100644 index 0000000..7f5f8ca --- /dev/null +++ b/tests/integration/test_invoke_happy_path.py @@ -0,0 +1,29 @@ +"""Integration: invoca incident_analyzer real con escenario MOS (sin HITL).""" + +from pathlib import Path + +import pytest + +EXAMPLES = ( + Path(__file__).parent.parent.parent / "agents" / "incident_analyzer" / "examples" +) + + +@pytest.mark.integration +def test_happy_path_completa_sin_hitl(integration_client) -> None: # type: ignore[no-untyped-def] + payload = (EXAMPLES / "02_mos_degradation_pool_sbc.txt").read_text(encoding="utf-8") + r = integration_client.post("/agents/incident_analyzer/invoke", json={"input": payload}) + assert r.status_code == 200 + body = r.json() + assert body["status"] == "completed" + assert body["agent_name"] == "incident_analyzer" + assert body["agent_version"] in {"v1", "v2"} + assert body["final_output"]["severity"] in {"low", "medium", "high", "critical"} + # Decision_path debe contener todos los nodos. + steps = {s["step"] for s in body["decision_path"]} + assert "validate_input" in steps + assert "llm_reason" in steps + assert "validate_output" in steps + assert "propose_actions" in steps + assert "approve_gate" in steps + assert "finalize" in steps