gitlink-cli/skills/gitlink-kb/tests/test_kb.py

131 lines
3.4 KiB
Python

"""gitlink-kb 单元测试。"""
from __future__ import annotations
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "scripts"))
import pytest
from kb import (
split_sections, build_index, search, extract_faq, build_map,
collect_docs, _tokenize_query,
)
DOC = """# 项目标题
简介段落。
## 安装
使用 pip 安装这个工具。
## 如何配置?
先创建配置文件,然后运行 init。
### 子配置
细节内容。
"""
class TestSplitSections:
def test_splits_by_heading(self):
secs = split_sections(DOC)
titles = [s["title"] for s in secs]
assert "安装" in titles
assert "如何配置?" in titles
def test_level_recorded(self):
secs = split_sections(DOC)
sub = next(s for s in secs if s["title"] == "子配置")
assert sub["level"] == 3
def test_body_captured(self):
secs = split_sections(DOC)
install = next(s for s in secs if s["title"] == "安装")
assert "pip" in install["body"]
class TestTokenize:
def test_english(self):
assert "install" in _tokenize_query("how to install")
def test_chinese_bigram(self):
tokens = _tokenize_query("如何安装")
assert "如何" in tokens or "安装" in tokens
class TestSearch:
def setup_method(self):
self.index = build_index([{"path": "README", "content": DOC}])
def test_finds_install(self):
results = search(self.index, "安装")
assert results
assert any("安装" in r["title"] for r in results)
def test_english_query(self):
results = search(self.index, "pip")
assert results
assert "pip" in results[0]["snippet"]
def test_no_match(self):
assert search(self.index, "zzzznotexist") == []
def test_empty_query(self):
assert search(self.index, "") == []
def test_title_weighted(self):
# 标题命中应排在前面
results = search(self.index, "配置")
assert results
assert "配置" in results[0]["title"]
class TestFaq:
def test_extracts_question(self):
index = build_index([{"path": "README", "content": DOC}])
faq = extract_faq(index)
assert any("配置" in f["question"] for f in faq)
def test_no_question(self):
index = build_index([{"path": "x", "content": "# Title\n\nbody"}])
assert extract_faq(index) == []
class TestMap:
def test_builds_map(self):
index = build_index([{"path": "README", "content": DOC}])
doc_map = build_map(index)
assert "README" in doc_map
titles = [s["title"] for s in doc_map["README"]]
assert "安装" in titles
class TestCollectDocs:
class FakeClient:
def readme(self, owner, repo, ref):
return "# README\n\n内容"
def list_dir(self, owner, repo, path, ref):
if path == "docs":
return [{"name": "guide.md", "type": "file", "content": "# 指南\n\n步骤"}]
return []
def file_content(self, owner, repo, filepath, ref):
return None
def test_collects_readme_and_docs(self):
docs = collect_docs("o", "r", "master", self.FakeClient())
paths = {d["path"] for d in docs}
assert "README" in paths
assert any("guide" in p for p in paths)
if __name__ == "__main__":
sys.exit(pytest.main([__file__, "-v"]))