tests/test_excerpts_resolve.py
Rama main · réplica de lectura del repositorio original.
"""索引裡的鍵要真的讀得回內容。
一個查得到、但摘要是空的命中,比查不到更糟:它佔掉一個名額,然後什麼都
沒給你。而顯示層在摘要為空時會退回顯示標題,所以它看起來一直很正常——
這種「優雅降級」把一個缺陷藏了好幾個月。
兩件真的發生過的事:
路徑疊了兩層 索引鍵是 wiki/topics/x.md#標題,呼叫端拿掉 wiki/ 之後傳
topics/x.md,而 WIKI_TOPICS_DIR 本身就以 topics 結尾。
於是每一個 wiki 命中的摘要都是空的——不是部分,是全部。
後綴沒被剝掉 索引用 @N 標示切塊、~N 標示同名標題的第幾個,都加在 # 之後。
讀取端拿「做法-Workflow~2」去找標題,找不到。實測 895 個。
這個測試對真實索引抽樣,所以它同時擋住「路徑組錯」與「又加了一種後綴卻
忘了教讀取端」。
"""
from __future__ import annotations
import json
import re
import sys
import unittest
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "scripts"))
import continuity_recall as cr
import xkb_paths
SAMPLE = 120
# 索引不完美,允許少量鍵指向已經被改掉的標題(頁面會變,索引是增量的)。
MIN_RESOLVED = 0.9
def _wiki_keys() -> list[str]:
if not xkb_paths.VECTOR_FILE.exists():
return []
data = json.loads(xkb_paths.VECTOR_FILE.read_text(encoding="utf-8"))
keys = data.get("vectors", data)
return [k for k in keys if k.startswith("wiki/")]
class ExcerptsResolveTest(unittest.TestCase):
def _rate(self, keys: list[str]) -> float:
if not keys:
self.skipTest("這台機器上沒有索引")
resolved = 0
for key in keys[:SAMPLE]:
rest, _, section = key[len("wiki/"):].partition("#")
if cr._section_text(rest, cr._base_heading(rest, section)):
resolved += 1
return resolved / min(SAMPLE, len(keys))
def test_ordinary_keys_resolve(self) -> None:
"""路徑組錯的話這裡會是 0——而且顯示層看起來仍然正常。"""
keys = [k for k in _wiki_keys() if not re.search(r"[@~]\d+$", k)]
rate = self._rate(keys)
self.assertGreaterEqual(rate, MIN_RESOLVED, f"只有 {rate:.0%} 的 wiki 鍵讀得回內容")
def test_suffixed_keys_resolve(self) -> None:
"""@N / ~N 是索引自己加的,讀取端要認得。"""
keys = [k for k in _wiki_keys() if re.search(r"[@~]\d+$", k)]
rate = self._rate(keys)
self.assertGreaterEqual(rate, MIN_RESOLVED, f"只有 {rate:.0%} 的帶後綴鍵讀得回內容")
def test_a_real_suffix_is_not_stripped_blindly(self) -> None:
"""標題本身就以 ~2 結尾時,不能被當成索引後綴砍掉。"""
self.assertEqual(cr._base_heading("does-not-exist.md", "核心概念"), "核心概念")
if __name__ == "__main__":
unittest.main()