7.4 KiB
7.4 KiB
定时任务 — 模板填充「源数据抽取」手工测试清单
覆盖功能:定时任务「模板数据转换器」内置 agent —— 把用户传入的源数据转换成 HTML 模板的
DATA结构并填充生成可预览页面。重点测「源数据抽取」:源可能是 ① 纯 JSON、② 含 JSON 的文本、③ 纯文本,三种形态都要正确处理。测试环境:后端
http://localhost:8001(make dev),前端http://localhost:5174(pnpm dev)。 相关代码:deerflow/runtime/scheduler/template_fill.py(extract_embedded_json)、service.py(_run_template_fill_attempt/_build_conversion_prompt)、pages/ScheduledTasksPage.tsx。
前置 — 进入表单
| # | 步骤 | 预期结果 |
|---|---|---|
| 0.1 | 任务管理 → 新建定时任务 | 弹出「新建定时任务」对话框 |
| 0.2 | 「执行智能体」下拉选择 模板数据转换器 | 表单出现「HTML 模板」下拉;「必须生成 HTML/Markdown」两个开关隐藏 |
| 0.3 | 「HTML 模板」下拉选择 no.1 | 下方出现「上传 .json」按钮 + 源数据文本框;说明含「未提供源 JSON 时,将直接展示该模板的默认数据」 |
T1 — 源形态①:纯 JSON
| # | 步骤 / 输入 | 预期结果 |
|---|---|---|
| 1.1 | 在源数据框粘贴纯 JSON(示例见下「样例 A」) | 文本框正常接收,无报错 |
| 1.2 | 保存任务 → 「立即执行」 | 执行记录新增一条,状态最终 succeeded |
| 1.3 | 打开执行记录 → HTML 预览 | 渲染出 no.1 大屏,总览指标/各列表数据来自粘贴的 JSON(而非模板默认值) |
| 1.4 | 执行记录正文 | 文案为「已根据源数据填充模板「no.1」生成页面」 |
T2 — 源形态②:含 JSON 的文本(抽取重点)
| # | 步骤 / 输入 | 预期结果 |
|---|---|---|
| 2.1 | 粘贴「样例 B」(前后是中文说明,中间夹一段 JSON) | 文本框正常接收 |
| 2.2 | 保存 → 立即执行 → 查看 HTML | 页面数据以夹带的 JSON 为准填充;正文里的补充说明(如「重点突出 X」)被一并参考 |
| 2.3 | 验证抽取正确性:JSON 字符串值里含 }(如 "备注": "进度 80%}尚未完成") |
不会被误判为 JSON 块提前结束,整段 JSON 被完整抽取 |
T3 — 源形态③:纯文本(无 JSON)
| # | 步骤 / 输入 | 预期结果 |
|---|---|---|
| 3.1 | 粘贴「样例 C」(一段纯中文描述,无任何 JSON) | 文本框正常接收 |
| 3.2 | 保存 → 立即执行 → 查看 HTML | 智能体理解文本语义后据实填充模板,产出完整可预览页面(数据可能较稀疏但结构完整) |
| 3.3 | 不应报「未返回 JSON」类硬失败(除非模型彻底失败重试耗尽) | 状态 succeeded |
T4 — 空源 → 模板默认数据
| # | 步骤 | 预期结果 |
|---|---|---|
| 4.1 | 源数据框留空,保存 → 立即执行 | 不调用模型,直接用 no.1 模板自带的默认数据生成 |
| 4.2 | 执行记录正文 | 「未提供源数据,已用模板「no.1」的默认数据生成页面」 |
| 4.3 | HTML 预览 | 展示模板内置的默认大屏 |
T5 — 上传 .json 文件
| # | 步骤 | 预期结果 |
|---|---|---|
| 5.1 | 点击「上传 .json 文件」,选一个合法 .json |
文件内容被读入源数据文本框 |
| 5.2 | 上传一个非法 JSON 内容的文件 | toast 提示「文件不是合法 JSON,已填入文本框请检查」,内容仍填入(可手改) |
| 5.3 | 连续上传同一个文件两次 | 第二次仍能触发读取(input 已被重置 value) |
T6 — no.2(只展示模板)
| # | 步骤 | 预期结果 |
|---|---|---|
| 6.1 | 「HTML 模板」下拉选 no.2 | 隐藏上传按钮与源数据文本框;显示「该模板暂为直接展示已有数据,无需填写」 |
| 6.2 | 即使之前填过源数据,保存 → 立即执行 | 忽略源数据,原样输出 no.2 现有页面 |
| 6.3 | 执行记录正文 | 「已展示模板「no.2」的现有数据」 |
T7 — 编辑回显
| # | 步骤 | 预期结果 |
|---|---|---|
| 7.1 | 对已保存的模板任务点「编辑」 | 「执行智能体」「HTML 模板」「源数据」均正确回显 |
| 7.2 | 把模板从 no.1 改成 no.2 再保存 | 切到 no.2 时源数据区即时隐藏;保存后执行走只展示分支 |
样例数据(可直接复制粘贴到源数据框)
样例 A — 纯 JSON
{
"overview": {
"核心指标": [
{ "名称": "综合区域", "数值": 7, "单位": "区", "说明": "测试数据" },
{ "名称": "组织与单位", "数值": 188, "单位": "个", "说明": "测试数据" }
]
},
"regions": [
{ "name": "测试区域甲", "scope": "本岛西岸" }
],
"equipment": [
{ "name_zh": "测试装备X", "category": "无人系统", "status": "列装" }
]
}
预期:总览第一项「综合区域」显示 7,「组织与单位」显示 188,区域/装备出现「测试区域甲」「测试装备X」。
样例 B — 含 JSON 的文本
这是本月台海态势数据,请据此填充大屏,重点突出离岛防卫:
{"overview": {"核心指标": [{"名称": "综合区域", "数值": 9, "单位": "区", "说明": "含离岛"}]}, "regions": [{"name": "离岛防区", "scope": "外岛", "备注": "进度 80%}尚未完成"}]}
以上数据来自 6 月例会,务必准确,不要臆造未提供的字段。
预期:① 数据以中间 JSON 为准(综合区域=9、出现「离岛防区」);② 字符串里的
}(进度 80%})不破坏抽取;③ 前后的「重点突出离岛防卫」「务必准确」作为补充说明被模型参考。
样例 C — 纯文本
请整理一份台湾滨海防卫概览:覆盖本岛沿岸 9 个综合区域,组织与单位约 280 个,
装备条目近百项(含无人系统、防空、海军平台等类别),并列出若干关键节点与近期演习。
数据以离线知识为准,没有的字段留空即可。
预期:智能体理解语义后据实填充,产出结构完整的页面(具体数值取决于模型,可较稀疏),不报硬失败。
后端单元测试(自动化补充)
# 在 offline-backend-20260512/backend/ 下运行
PYTHONPATH=. uv run --no-sync pytest tests/test_template_fill.py -v # 引擎:抽取/校验/填充/注册表
PYTHONPATH=. uv run --no-sync pytest tests/test_template_fill_attempt.py -v # 调度器执行分支:三形态/默认/只展示/重试
PYTHONPATH=. uv run --no-sync pytest tests/test_template_builder_seed.py -v # 内置 agent 种子
抽取相关关键用例:
test_extract_embedded_json_pure_object/_pure_array—— 纯 JSON。test_extract_embedded_json_text_with_json/_fenced—— 含 JSON 的文本 / ```json 围栏。test_extract_embedded_json_plain_text_returns_none—— 纯文本返回 None。test_extract_embedded_json_ignores_braces_in_strings—— 引号内}不误判。test_text_with_embedded_json_surfaced_in_prompt—— 转换 prompt 单独标注「识别到的结构化数据」。test_plain_text_source_converts—— 纯文本仍照常转换。test_empty_source_uses_template_default—— 空源用模板默认数据。test_display_only_template_renders_as_is—— no.2 原样输出。
三个文件应全部通过(0 failed)。