149 lines
7.4 KiB
Markdown
149 lines
7.4 KiB
Markdown
# 定时任务 — 模板填充「源数据抽取」手工测试清单
|
||
|
||
> 覆盖功能:定时任务「模板数据转换器」内置 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
|
||
|
||
```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 个,
|
||
装备条目近百项(含无人系统、防空、海军平台等类别),并列出若干关键节点与近期演习。
|
||
数据以离线知识为准,没有的字段留空即可。
|
||
```
|
||
|
||
> 预期:智能体理解语义后据实填充,产出结构完整的页面(具体数值取决于模型,可较稀疏),不报硬失败。
|
||
|
||
---
|
||
|
||
## 后端单元测试(自动化补充)
|
||
|
||
```bash
|
||
# 在 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)。
|