8a3bea6b31
검색 엔드포인트 wrapper decoration(run_search 코어 무접촉·ranking 무관): - version_status: 법령 결과(material_type=law)에 legal_meta.version_status 부착 (decorate_version_status, law 무결과 시 query skip). SearchResult.version_status 신설. - facets=true: top-K 결과 분류 축(material_type/jurisdiction/version_status) 분포 라벨 (compute_facets). 미요청=None(byte 불변). SearchResponse.facets 신설. - result_decorate.py 신설. 단위 4건. freshness incident 변경(law_365d 제거+흡수)=ranking 변경이라 별 슬라이스 defer. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
58 lines
2.0 KiB
Python
58 lines
2.0 KiB
Python
"""C-1 후속 — facets 집계 + version_status decorate 순수 로직 테스트.
|
|
|
|
version_status 의 실제 legal_meta 조회는 GPU 라이브(법령 검색)로 검증 — 여기선 facets 분포
|
|
계약 + decorate 의 law 무결과 skip 경로(DB 미접촉)만.
|
|
"""
|
|
|
|
import asyncio
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(0, str(Path(__file__).parent.parent / "app"))
|
|
|
|
from services.search.result_decorate import ( # noqa: E402
|
|
compute_facets,
|
|
decorate_version_status,
|
|
)
|
|
|
|
|
|
class _R:
|
|
"""SearchResult 흉내 — 분류 축 속성만."""
|
|
|
|
def __init__(self, material_type=None, jurisdiction=None, version_status=None, id=1):
|
|
self.material_type = material_type
|
|
self.jurisdiction = jurisdiction
|
|
self.version_status = version_status
|
|
self.id = id
|
|
|
|
|
|
def test_compute_facets_distribution():
|
|
results = [
|
|
_R("law", "KR", "current"),
|
|
_R("law", "KR", "superseded"),
|
|
_R("incident", "KR", None),
|
|
_R("paper", None, None),
|
|
]
|
|
f = compute_facets(results)
|
|
assert f["material_type"] == {"law": 2, "incident": 1, "paper": 1}
|
|
assert f["jurisdiction"] == {"KR": 3} # paper jurisdiction None 제외
|
|
assert f["version_status"] == {"current": 1, "superseded": 1} # None 제외
|
|
|
|
|
|
def test_compute_facets_empty_and_all_none():
|
|
assert compute_facets([]) == {}
|
|
assert compute_facets([_R(), _R()]) == {} # 모든 축 None → 빈 축 미포함
|
|
|
|
|
|
def test_compute_facets_excludes_empty_axes():
|
|
f = compute_facets([_R(jurisdiction="US"), _R(jurisdiction="EU")])
|
|
assert f == {"jurisdiction": {"US": 1, "EU": 1}}
|
|
assert "material_type" not in f
|
|
|
|
|
|
def test_decorate_version_status_skips_without_law():
|
|
# law 결과 없으면 legal_meta 조회 skip → session 미사용(None 으로도 무오류)
|
|
results = [_R("incident", "KR"), _R("paper")]
|
|
asyncio.run(decorate_version_status(None, results))
|
|
assert all(r.version_status is None for r in results)
|