aps-agent/tests/golden/test_routing_templates.py

85 lines
3.4 KiB
Python
Raw Permalink Normal View History

# ============================================================
# M-E 黄金测试:行业工艺路线模板库(结构化 + 知识互链 + 实例化)
# ============================================================
from __future__ import annotations
import pytest
from server.state.seed import seed_world
@pytest.fixture(autouse=True)
def db_env(tmp_path, monkeypatch):
monkeypatch.setenv("APS_DB_PATH", str(tmp_path / "master.db"))
monkeypatch.delenv("APS_DB_DISABLED", raising=False)
from server.db.database import reset_engine
reset_engine()
yield
reset_engine()
def test_builtin_templates_cover_machining_categories():
from server.knowledge.routing_templates import list_templates
tpls = list_templates()
categories = {t["category"] for t in tpls}
assert {"车削", "铣削", "钻镗", "磨削", "钣金", "焊接", "装配"} <= categories
for t in tpls:
assert t["steps"], t["code"]
for s in t["steps"]:
assert s["stdMinLow"] <= s["stdMinDefault"] <= s["stdMinHigh"]
assert s["equipmentType"]
def test_templates_linked_to_knowledge_assets():
from server.knowledge.routing_templates import list_templates
tpls = list_templates()
linked = [t for t in tpls if t.get("assetId")]
assert linked, "模板应与知识资产互链(assetId)"
from server.knowledge.assets import get_knowledge
asset_ids = {a["assetId"] for a in get_knowledge().assets}
assert all(t["assetId"] in asset_ids for t in linked)
def test_recommend_by_product_keywords():
from server.knowledge.routing_templates import recommend_templates
hits = recommend_templates("传动轴 车削 外圆 螺纹")
assert hits and hits[0]["code"] == "TPL-TURNING"
hits = recommend_templates("城轨门机构部装总成")
assert any(t["code"] == "TPL-RAIL-ASSY" for t in hits)
def test_apply_template_generates_schedulable_routing():
from server.engines import PoolEngine
from server.knowledge.routing_templates import apply_template_to_product
world = seed_world()
world["flexOrders"].append({
"id": 88, "orderNo": "FO-8801", "productCode": "SHAFT-X", "quantity": 10,
"dueDate": "2099-12-31", "priority": 1, "wbs": "", "productionController": "测试",
"status": "RELEASED"})
applied = apply_template_to_product(world, "TPL-TURNING", "SHAFT-X", "传动轴")
assert applied["steps"] > 0
steps = [r for r in world["flexRoutings"] if r["productCode"] == "SHAFT-X"]
assert all(r["stdTimeSource"] == "模板" for r in steps)
# 能力已补齐 → PoolEngine 可排该单
counters: dict[str, int] = {}
def nid(kind: str) -> int:
counters[kind] = counters.get(kind, 0) + 1
return counters[kind]
result = PoolEngine().solve(world, nid, sort_mode="BOTTLENECK", order_ids=[88])
assert result["orderCount"] == 1
assert result["woCount"] == len(steps)
def test_knowledge_refs_injected_into_problem_dto():
from server.aps_domain.scheduling_dto import world_to_flex_problem
world = seed_world()
problem = world_to_flex_problem(world, include_knowledge=True)
refs = problem.meta.get("knowledgeRefs")
assert isinstance(refs, list)
if refs: # 命中时必须带出处 + 版本(RAG 硬规则)
assert all(r.get("assetId") and r.get("version") for r in refs)
assert problem.schemaVersion == "1.1"