Files
2026Technology-Competition/tests/test_phase5_writer_state.py
T
lhl d9aa3a3325 fix(writer): 修复概要设计书输出塌缩与章间引用缺失,并补 parser 防灾
- Writer: 表格表头行/Table Grid 边框、列表 List Bullet/Number 样式、行内字符格式不再塌缩(外视 #6 反转)
- Writer: 打通章间引用(WriterState 摘要 → 后章 prompt prior_summaries)
- Writer: 删除 _chunk_source 死代码,章节数据经 DataGate 控 token 预算
- Writer: 章节结果落盘快照,命中即跳过 LLM(录制重拍可续跑,损坏快照自动忽略)
- Parser: 按 body 顺序遍历正文+单元格(含嵌套表、合并单元格去重),修复表格内锚点漏检导致的静默丢章
- Parser/服务层: .xls 显式拒绝(可操作提示),上传即校验扩展名,rules 对齐 docx-only
- 测试: 全量 680 通过,覆盖率 99.37%(红线 99%)
2026-09-15 21:30:55 +08:00

70 lines
2.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""WriterState 测试(P5-T5)。"""
from genesis.writer.writer_state import WriterState
from genesis.writer.models import ChapterContent, ContentBlock
from genesis.eval.scorer import EvalReport
def _content(cid, version=1):
return ChapterContent(chapter_id=cid, version=version, title="x", blocks=[])
def _report(failed):
return EvalReport(
dimensions=[], total_score=0.0, passed=False, failed_chapters=failed,
)
def test_initial_state_empty():
st = WriterState(["a", "b"])
assert st.needs_regeneration() == ["a", "b"]
def test_record_success_clears_need():
st = WriterState(["a"])
st.record_success(_content("a"))
assert st.needs_regeneration() == []
def test_failed_eval_marks_regeneration():
st = WriterState(["a"])
st.record_success(_content("a"))
st.record_eval("a", _report(["a"]))
assert st.needs_regeneration() == ["a"]
# ---------- 章间引用摘要(design.md §6.9 ----------
def _content_with_table(cid, title, headers, nrows):
rows = [[str(i) for _ in headers] for i in range(nrows)]
return ChapterContent(chapter_id=cid, version=1, title=title, blocks=[
ContentBlock(block_id="b1", type="table", headers=headers, rows=rows),
])
def test_summary_of_includes_title_and_table_structure():
st = WriterState(["a"])
st.record_success(_content_with_table("a", "機能一覧", ["機能ID", "機能名"], 3))
s = st.summary_of("a")
assert "a" in s and "機能一覧" in s
assert "機能ID" in s and "機能名" in s
assert "3" in s
def test_summary_of_none_when_not_generated():
st = WriterState(["a"])
assert st.summary_of("a") is None
def test_summaries_before_respects_order():
st = WriterState(["a", "b", "c"])
st.record_success(_content_with_table("a", "第一章", ["ID"], 1))
st.record_success(_content_with_table("b", "第二章", ["ID"], 2))
before_c = st.summaries_before("c")
assert "第一章" in before_c and "第二章" in before_c
assert st.summaries_before("a") == ""
def test_summaries_before_unknown_chapter_empty():
st = WriterState(["a"])
assert st.summaries_before("zzz") == ""