streamsearch / tests /test_app.py
sharmaaryan's picture
Phase 1: demo tier — FastAPI + Streamlit over a baked index, Docker-deployable
a22b195
Raw
History Blame Contribute Delete
2.63 kB
"""Phase 1: drive the FastAPI /search and /ingest endpoints over a tiny index.
Builds a 3-doc embedded index into a temp dir, then exercises the app the same
way the live demo does.
"""
import importlib
import json
import sys
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "src"))
sys.path.insert(0, str(ROOT / "app"))
sys.path.insert(0, str(ROOT / "scripts"))
MINI = [
{"id": "a1", "title": "Graph neural networks", "text": "Message passing over graph structured data."},
{"id": "a2", "title": "Streaming systems", "text": "Kafka and Spark process unbounded event streams."},
{"id": "a3", "title": "Vector search", "text": "HNSW indexes power approximate nearest neighbor retrieval."},
]
@pytest.fixture()
def client(tmp_path, monkeypatch):
corpus = tmp_path / "corpus.jsonl"
corpus.write_text("\n".join(json.dumps(d) for d in MINI), encoding="utf-8")
monkeypatch.setenv("PREBUILT_DIR", str(tmp_path / "prebuilt"))
monkeypatch.setenv("CORPUS_PATH", str(corpus))
monkeypatch.delenv("QDRANT_URL", raising=False)
# Reload config so it picks up the temp paths, then build the index.
import streamsearch.config as config
importlib.reload(config)
build = importlib.import_module("build_index") if "build_index" not in sys.modules \
else importlib.reload(sys.modules["build_index"])
build.main()
# Import the app fresh against the same reloaded config.
import service
importlib.reload(service)
service.get_searcher.cache_clear()
main = importlib.import_module("main") if "main" not in sys.modules \
else importlib.reload(sys.modules["main"])
from fastapi.testclient import TestClient
with TestClient(main.app) as c:
yield c
def test_health_reports_doc_count(client):
r = client.get("/health")
assert r.status_code == 200
assert r.json()["documents"] == 3
def test_search_returns_relevant_result(client):
r = client.get("/search", params={"q": "kafka spark streaming", "top_k": 3})
assert r.status_code == 200
assert r.json()["results"][0]["id"] == "a2"
def test_ingest_then_searchable(client):
r = client.post("/ingest", json={"title": "Zephyr protocol",
"text": "The zephyrium snark lattice teleports widgets."})
assert r.status_code == 200
new_id = r.json()["id"]
r2 = client.get("/search", params={"q": "zephyrium snark lattice widgets", "top_k": 3})
assert new_id in [h["id"] for h in r2.json()["results"]]
assert client.get("/health").json()["documents"] == 4