From ee224e7c56b84e6644d96cf0f5111a0622c3e114 Mon Sep 17 00:00:00 2001 From: lhl Date: Sun, 30 Aug 2026 00:44:49 +0800 Subject: [PATCH] =?UTF-8?q?test(rag):=20=E8=A1=A5=E5=85=85=E5=BC=95?= =?UTF-8?q?=E6=93=8E=E6=87=92=E6=9E=84=E5=BB=BA=E4=B8=8E=20HTTP=20?= =?UTF-8?q?=E7=BA=A7=20RAG=20e2e=20=E8=A6=86=E7=9B=96=EF=BC=8C=E6=81=A2?= =?UTF-8?q?=E5=A4=8D=2099%=20=E9=97=A8=E7=A6=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_impact_rag_e2e.py | 78 ++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/tests/test_impact_rag_e2e.py b/tests/test_impact_rag_e2e.py index 8866b3f..12cbb17 100644 --- a/tests/test_impact_rag_e2e.py +++ b/tests/test_impact_rag_e2e.py @@ -8,10 +8,14 @@ from __future__ import annotations import asyncio import glob import io +import json import zipfile from pathlib import Path import pytest +from fastapi.testclient import TestClient + +from genesis.server.app import create_app from genesis.impact.impact_agent import _RAG_CONTEXT_TITLE from genesis.rag.embeddings import FakeEmbedder @@ -144,3 +148,77 @@ def test_rag_e2e_use_rag_false_backward_compat(tmp_path): assert _RAG_CONTEXT_TITLE not in (engine.captured or "") # 确定性报告存在 assert rec.impact_report_path and Path(rec.impact_report_path).exists() + + +def test_service_rag_lazy_engine_build(tmp_path, monkeypatch): + """覆盖 service.py:233-236:构造未传 engine 且 run_impact(use_rag=True) 时懒构建引擎。""" + store = SessionStore(db_path=str(tmp_path / "s.db")) + rag = ImpactRAG(RagStore(str(tmp_path / "rag.db")), FakeEmbedder()) + # 注入的懒构建产物:一个会捕获 prompt 的 FakeEngine + injected_engine = FakeEngine() + monkeypatch.setattr( + "genesis.inference.factory.build_inference_engine", lambda: injected_engine + ) + svc = GenesisService( + store=store, + data_root=str(tmp_path / "data"), + rag=rag, + use_rag=False, # 构造时不传 engine、RAG 默认关闭 + ) + assert svc.engine is None # 尚未构建 + + sid = svc.create_session("u1").session_id + svc.upload_file(sid, "requirements", "requirements_newdev.xlsx", _sample_req()) + svc.upload_file(sid, "template", "template_design_ja.docx", _sample_tpl()) + # 上传即索引(D1),existing_system 含 KnownOrder 源码 + svc.upload_file(sid, "existing_system", "existing.zip", _make_existing_zip()) + svc.run_parse(sid) + svc.confirm_parse(sid) + assert svc.get_session(sid).status == "impact_running" + + # 显参开启 RAG → 触发 engine 为 None 的懒构建分支 + rec = asyncio.run(svc.run_impact(sid, use_rag=True)) + assert rec.status == "awaiting_impact_confirm" + # 懒构建的引擎被注入并实际使用 + assert svc.engine is injected_engine + summary = json.loads(rec.impact_summary) + assert summary.get("rag_enabled") is True + # 引擎捕获的 prompt 含 RAG 检索注入的 KnownOrder 片段 + assert injected_engine.captured is not None + assert "KnownOrder" in injected_engine.captured + + +def test_http_start_impact_use_rag_e2e(tmp_path): + """覆盖 app.py start_impact 异步端点 + _FakeEngine.chat_structured(RAG 路径,HTTP 级)。""" + store = SessionStore(db_path=str(tmp_path / "s.db")) + rag = ImpactRAG(RagStore(str(tmp_path / "rag.db")), FakeEmbedder()) + app = create_app( + store=store, + data_root=str(tmp_path / "data"), + engine="fake", # 触发内部 _FakeEngine(异步 chat_structured) + rag=rag, + ) + client = TestClient(app) + + sid = client.post("/api/sessions", json={"user_id": "u1"}).json()["session_id"] + # multipart 上传:要件/模板/既有系统 + client.post(f"/api/sessions/{sid}/files", + data={"file_type": "requirements"}, + files={"file": ("requirements_newdev.xlsx", _sample_req())}) + client.post(f"/api/sessions/{sid}/files", + data={"file_type": "template"}, + files={"file": ("template_design_ja.docx", _sample_tpl())}) + client.post(f"/api/sessions/{sid}/files", + data={"file_type": "existing_system"}, + files={"file": ("existing.zip", _make_existing_zip())}) + + assert client.post(f"/api/sessions/{sid}/start-parse").status_code == 200 + # 有既有系统 → impact_running + assert client.post(f"/api/sessions/{sid}/confirm-parse").json()["status"] == "impact_running" + + # 异步端点:start-impact?use_rag=True(显参开启 RAG) + r = client.post(f"/api/sessions/{sid}/start-impact?use_rag=True") + assert r.status_code == 200 + ir = client.get(f"/api/sessions/{sid}/impact-result").json() + # 经 HTTP 真实走到 RAG 路径,摘要标记 rag_enabled + assert ir.get("rag_enabled") is True