"""test_humanizer.py —— Humanizer 单测(S4)。 覆盖:规则命中 / 块级保护(引用/表格/代码/图片逐字符一致)/ 幂等 / 空串不抛。 """ from __future__ import annotations import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) from app.services.humanizer import humanize_answer # noqa: E402 class TestRules: def test_strikes_ai_phrases(self): text = "值得注意的是,水稻SPL基因家族在产量调控中发挥作用。此外,它影响穗发育。" out, stats = humanize_answer(text) assert "值得注意的是" not in out assert stats["rules_applied"] >= 1 def test_idempotent(self): text = "此外,该基因影响发育。" out1, _ = humanize_answer(text) out2, _ = humanize_answer(out1) assert out1 == out2 def test_empty_ok(self): assert humanize_answer("") == ("", {"rules_applied": 0}) assert humanize_answer(None)[0] is None class TestBlockProtection: def test_citation_spans_preserved(self): text = "该基因调控分蘖 [PMID: 12345678]。此外,另一研究 [DOI: 10.1000/x] 表明……" out, _ = humanize_answer(text) assert "[PMID: 12345678]" in out assert "[DOI: 10.1000/x]" in out def test_code_fence_preserved(self): code = "```python\nprint('值得注意的是')\n```" text = f"正文。{code}" out, _ = humanize_answer(text) assert code in out assert "值得注意的是" in out # 代码块内的不被替换 def test_table_preserved(self): table = "| 基因 | 功能 |\n|---|---|\n| OsSPL14 | 分蘖 |" text = f"值得注意的是,见下表。\n{table}" out, _ = humanize_answer(text) assert table in out def test_fig_marker_preserved(self): marker = "[[FIG:PMC12345]]" text = f"正文。\n{marker}" out, _ = humanize_answer(text) assert marker in out def test_image_md_preserved(self): img = "![](/api/figures/proxy?pmcid=PMC7820984&url=https%3A%2F%2Fexample)" text = f"正文 {img}" out, _ = humanize_answer(text) assert img in out