test_q4a_search_highlight.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. """搜索关键词高亮与正文命中片段的单元测试。"""
  2. from __future__ import annotations
  3. import sys
  4. from pathlib import Path
  5. import pytest
  6. BACKEND_ROOT = Path(__file__).resolve().parents[2]
  7. if str(BACKEND_ROOT) not in sys.path:
  8. sys.path.insert(0, str(BACKEND_ROOT))
  9. from dms.services.document_query_service import _content_snippet
  10. class TestContentSnippet:
  11. """_content_snippet 纯函数测试。"""
  12. def test_returns_none_when_no_content(self):
  13. assert _content_snippet(None, "关键词") is None
  14. def test_returns_none_when_no_keyword(self):
  15. assert _content_snippet("一些正文内容", None) is None
  16. assert _content_snippet("一些正文内容", "") is None
  17. assert _content_snippet("一些正文内容", " ") is None
  18. def test_returns_none_when_keyword_not_in_content(self):
  19. assert _content_snippet("这是一段正文", "不存在") is None
  20. def test_keyword_at_start_no_prefix_ellipsis(self):
  21. content = "关键词在开头,后面有很多内容" * 10
  22. result = _content_snippet(content, "关键词")
  23. assert result is not None
  24. assert not result.startswith("……")
  25. assert result.endswith("……")
  26. assert "关键词" in result
  27. def test_keyword_at_end_no_suffix_ellipsis(self):
  28. content = "前面有很多内容" * 20 + "尾部关键词"
  29. result = _content_snippet(content, "尾部关键词")
  30. assert result is not None
  31. assert result.startswith("……")
  32. assert not result.endswith("……")
  33. assert "尾部关键词" in result
  34. def test_keyword_in_middle_both_ellipsis(self):
  35. content = "前面的内容。" * 20 + "目标词" + "后面的内容。" * 20
  36. result = _content_snippet(content, "目标词")
  37. assert result is not None
  38. assert result.startswith("……")
  39. assert result.endswith("……")
  40. assert "目标词" in result
  41. def test_short_content_no_ellipsis(self):
  42. content = "很短的关键词"
  43. result = _content_snippet(content, "关键词")
  44. assert result is not None
  45. assert not result.startswith("……")
  46. assert not result.endswith("……")
  47. assert result == content
  48. def test_case_insensitive_match(self):
  49. content = "Hello World Test"
  50. result = _content_snippet(content, "hello")
  51. assert result is not None
  52. assert "Hello" in result
  53. def test_chinese_case_insensitive(self):
  54. """中文无大小写,但函数不应崩溃。"""
  55. content = "这是一段包含关键词的正文内容"
  56. result = _content_snippet(content, "关键词")
  57. assert result is not None
  58. assert "关键词" in result
  59. def test_snippet_length_bounded(self):
  60. content = "A" * 500 + "目标" + "B" * 500
  61. result = _content_snippet(content, "目标")
  62. assert result is not None
  63. # 40 before + keyword + 80 after + 2 ellipsis chars
  64. assert len(result) <= 40 + 2 + 80 + 4 # 126
  65. def test_strips_keyword_whitespace(self):
  66. content = "前面的内容目标词后面的内容"
  67. result = _content_snippet(content, " 目标词 ")
  68. assert result is not None
  69. assert "目标词" in result