import asyncio import tempfile import unittest from whoosh import index from whoosh.fields import Schema, TEXT, ID from app.services.search_service import SearchService, ChineseAnalyzer class SearchServiceTest(unittest.TestCase): def _build_service(self): tmp = tempfile.mkdtemp() schema = Schema( project_id=ID(stored=True), path=ID(unique=True, stored=True), title=TEXT(stored=True, analyzer=ChineseAnalyzer()), content=TEXT(stored=True, analyzer=ChineseAnalyzer()), ) ix = index.create_in(tmp, schema) writer = ix.writer() writer.add_document( project_id="1", path="1:标签表.md", title="标签表.md", content="本文档介绍标签表的使用方法。", ) writer.add_document( project_id="1", path="1:标签分类.md", title="标签分类.md", content="文档按标签进行分类,分类表存储记录。", ) writer.add_document( project_id="1", path="1:标签说明.md", title="标签说明.md", content="标签用于内容分类。", ) writer.add_document( project_id="1", path="1:配置表.md", title="配置表.md", content="该表用于系统配置。", ) writer.commit() service = SearchService() service.ix = ix return service def test_phrase_keyword_matches_only_exact_content(self): """搜索「标签表」只应命中原文确实包含该短语的文件, 而不是「标签」+「表」分散出现在不同位置的文件。""" service = self._build_service() result = asyncio.run(service.search("标签表", "1")) self.assertEqual([item["path"] for item in result], ["标签表.md"]) def test_single_token_search_returns_all_matches(self): service = self._build_service() result = asyncio.run(service.search("标签", "1")) paths = {item["path"] for item in result} self.assertEqual(paths, {"标签表.md", "标签分类.md", "标签说明.md"}) def test_no_match_returns_empty(self): service = self._build_service() result = asyncio.run(service.search("接口文档", "1")) self.assertEqual(result, []) if __name__ == "__main__": unittest.main()