# -*- coding: utf-8 -*- """交接班摘要生成器测试(issue #75)。 覆盖: 1. 配置资产加载(章节/异常处置要求/默认班次); 2. 事件归类(production/equipment/alarm/safety/todo + 未知 → 待办); 3. 异常处置校验:缺失处置 → needs_followup + followup_items; 4. 无异常事件 → 「本班无异常事项」占位; 5. to_text Markdown 输出(标题/章节/待跟进标注)。 """ import os import sys import unittest sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import _bootstrap # noqa: F401 from ti_scenarios.handover import ( # noqa: E402 DEFAULT_SECTIONS, HandoverGenerator, ) CONFIG = os.path.join( os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "config", "handover.template.yaml", ) class TestConfigLoad(unittest.TestCase): """配置资产加载。""" def setUp(self): self.g = HandoverGenerator.from_template_config(CONFIG) def test_sections_and_defaults(self): self.assertEqual([s["key"] for s in self.g.sections], [s["key"] for s in DEFAULT_SECTIONS]) self.assertTrue(self.g.alarm_requires_disposal) self.assertEqual(self.g.default_shift, "甲班") class TestGenerate(unittest.TestCase): """事件归类与摘要生成。""" def setUp(self): self.g = HandoverGenerator.from_template_config(CONFIG) def test_event_classification(self): events = [ {"type": "production", "text": "生产平稳,产出 12 批", "time": "08:00"}, {"type": "equipment", "text": "洗涤泵 A 运行正常"}, {"type": "safety", "text": "巡检未发现隐患"}, {"type": "todo", "text": "明日更换滤芯"}, {"type": "未知类型", "text": "临时事项"}, ] report = self.g.generate(events, shift="甲班", date="2026-09-01") self.assertEqual(len(report.sections["production"]), 1) self.assertEqual(len(report.sections["equipment"]), 1) self.assertEqual(len(report.sections["safety"]), 1) self.assertEqual(len(report.sections["todo"]), 2) # 已知 + 未知类型 self.assertFalse(report.needs_followup) def test_alarm_with_disposal_ok(self): events = [{"type": "alarm", "text": "炉温超上限", "time": "09:12", "operator": "李工", "disposal": "已降低氯气流量,10 分钟内回落"}] report = self.g.generate(events, shift="乙班") self.assertEqual(len(report.sections["alarm"]), 1) self.assertFalse(report.needs_followup) def test_alarm_missing_disposal_marks_followup(self): events = [{"type": "alarm", "text": "炉温超上限", "time": "09:12"}] report = self.g.generate(events) self.assertTrue(report.needs_followup) self.assertTrue(any("炉温超上限" in it for it in report.followup_items)) def test_no_alarm_placeholder(self): report = self.g.generate([{"type": "production", "text": "正常"}]) self.assertEqual(report.sections["alarm"], ["本班无异常事项"]) self.assertFalse(report.needs_followup) def test_default_shift(self): report = self.g.generate([]) self.assertEqual(report.shift, "甲班") class TestOutput(unittest.TestCase): """Markdown 输出。""" def test_to_text_sections(self): g = HandoverGenerator.from_template_config(CONFIG) report = g.generate([{"type": "alarm", "text": "炉温报警"}], shift="甲班", date="2026-09-01") text = report.to_text() self.assertIn("# 交接班摘要(2026-09-01 甲班)", text) self.assertIn("## 生产概况", text) self.assertIn("## 异常与处置", text) self.assertIn("待跟进", text) # 缺处置记录 → 待跟进标注 self.assertIn("- 炉温报警", text) def test_to_dict(self): report = HandoverGenerator().generate([]) d = report.to_dict() self.assertEqual(set(d), {"shift", "date", "sections", "needs_followup", "followup_items"}) if __name__ == "__main__": unittest.main()