This commit is contained in:
LASTA_DEV01\lasta
2026-05-13 19:57:34 +09:00
parent 2e9204243d
commit 9e88f4c7ad
4310 changed files with 48538 additions and 905279 deletions

View File

View File

@@ -0,0 +1,45 @@
"""E2E test configuration.
These tests are SKIPPED by default. To run them set ``LLM_API_KEY`` and
``LLM_PROVIDER`` (and any model overrides) in the environment, then run:
pytest tests/e2e -m e2e
They exercise the full OntoCast workflow end-to-end — LLM calls included —
and so they cost real money. Keep them out of CI default runs.
"""
from __future__ import annotations
import os
import sys
from pathlib import Path
import pytest
REPO_ROOT = Path(__file__).resolve().parents[2]
for p in (REPO_ROOT, REPO_ROOT / "vendored" / "ontocast"):
if str(p) not in sys.path:
sys.path.insert(0, str(p))
def pytest_collection_modifyitems(
config: pytest.Config, items: list[pytest.Item]
) -> None:
"""Skip all e2e tests when LLM_API_KEY is not configured."""
if os.environ.get("LLM_API_KEY"):
return
skip_marker = pytest.mark.skip(
reason="E2E tests require LLM_API_KEY in environment."
)
for item in items:
# Only apply to tests in this directory tree.
if "tests/e2e" in str(item.fspath).replace("\\", "/"):
item.add_marker(skip_marker)
def pytest_configure(config: pytest.Config) -> None:
config.addinivalue_line(
"markers",
"e2e: end-to-end test that requires a real LLM and may cost money",
)

View File

@@ -0,0 +1,93 @@
"""Phase 0 end-to-end pipeline test.
Runs the actual OntoCast workflow through the FastAPI ``/process`` endpoint
with a tiny JSON input. Verifies Acceptance Gate 0 evidence:
- /health, /info, /process respond OK
- ontology + facts Turtle are produced
- BudgetTracker reports non-zero LLM call/triple counts
- Filesystem TripleStoreManager writes artifacts under working_directory
Skipped unless ``LLM_API_KEY`` is set (see ``conftest.py``).
"""
from __future__ import annotations
import importlib
import json
import os
import sys
from pathlib import Path
import pytest
from fastapi.testclient import TestClient
REPO_ROOT = Path(__file__).resolve().parents[2]
if str(REPO_ROOT) not in sys.path:
sys.path.insert(0, str(REPO_ROOT))
main_module = importlib.import_module("platform.api.main")
deps_module = importlib.import_module("platform.api.deps")
platform_config = importlib.import_module("platform.config")
@pytest.mark.e2e
@pytest.mark.asyncio
async def test_full_pipeline_writes_ontology_and_facts(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
# Point the working directory at the test's tmp_path so artifacts don't
# leak between runs.
monkeypatch.setenv("ONTOCAST_WORKING_DIRECTORY", str(tmp_path / "work"))
# Honor whatever LLM provider the operator configured.
assert os.environ.get("LLM_API_KEY"), "LLM_API_KEY must be set for e2e"
# Force a fresh AppContext so the new working_directory wins.
deps_module.reset_app_context_for_testing()
settings = platform_config.load_settings()
await deps_module.initialize_app_context(settings, head_chunks=1)
app = main_module.create_app()
# Tiny but ontology-rich payload.
payload = {
"text": (
"Alice works at Acme Corporation in Berlin. "
"Acme Corporation manufactures bicycles."
),
"ontology_user_instruction": "Focus on person-organization-location relations.",
"facts_user_instruction": "Extract employment and manufacturing facts.",
}
with TestClient(app) as client:
# /health & /info first as smoke
assert client.get("/health").status_code == 200
assert client.get("/info").status_code == 200
response = client.post(
"/process",
content=json.dumps(payload),
headers={"Content-Type": "application/json"},
)
assert response.status_code == 200, response.text
body = response.json()
assert body["status"] == "success"
assert body["data"]["ontology"], "ontology TTL must not be empty"
assert body["data"]["facts"], "facts TTL must not be empty"
budget = body["metadata"]["budget"]
assert budget["calls_count"] > 0, "BudgetTracker must record at least one LLM call"
assert (
budget["ontology_triples_generated"] > 0
or budget["facts_triples_generated"] > 0
), "BudgetTracker must record triple generation"
# The filesystem manager should have created artifacts somewhere under
# working_directory. We don't assert exact filenames (those depend on
# the document hash) — just that the directory is non-empty.
work_dir = tmp_path / "work"
written = list(work_dir.rglob("*"))
assert any(p.suffix in {".ttl", ".rdf"} for p in written if p.is_file()), (
f"No RDF artifacts produced under {work_dir}"
)