# KSP 管理后台重构测试计划 v2 生成日期:2026-05-31 ## 1. 项目与重构摘要 本项目是一个 Flask + SQLAlchemy 的 KSP 数据管理后台,数据来源包括引擎/通信/燃料箱/载具 Excel,以及任务资产日志。早期能力集中在数据中心:引擎目录、通信部件、燃料箱规格、载具成本、燃料换算和导入脚本。 `draft_board.md` 描述的重构重点是“任务运营”: - 资产当前位置、当前任务、当前状态由 `AssetLogEntry` 按 `simulation_time` 派生,不应直接编辑位置结果。 - 资产列表、任务总览、状态板、任务列表、时间线和地点板都应围绕同一套资产日志快照计算。 - 日志支持 state interval / event point,并支持 state nodes;节点应按时间排序。 - 对接关系应是时间敏感模型,需求中规划了 `docking_events` 表,并要求已有资产对接时双向写入日志。 - 地点板应提供 Canvas 星图、天体层级导航、缩放/拖拽和 scope 面板。 - 时间线应提供只读时间轴、搜索、预设、类型/位置/状态/日期范围/资产选择等筛选。 - 数据中心保持现有结构,重构不应破坏 CRUD、筛选、排序和详情页。 当前实现与 `draft_board.md` 的明显差距: - 模型和迁移中尚未实现 `docking_events` 表;当前 `/api/v1/assets//dock` 只给当前资产新增一条 state 日志,没有真实父子对接关系、分离流程或双向日志。 - Location 仍是日志自由文本字段,尚未落成结构化层级选项。 - 地点板已接入 Canvas 和轨道数据,但当前模板使用程序绘制的渐变天体,没有使用 `demo/textures/` 的真实纹理。 - 时间线模板渲染了筛选控件,但未发现 `tlPreset`、搜索/筛选控件事件处理脚本;这些控件需要被测试明确捕获。 - 资产详情日志搜索/类型筛选控件存在 DOM,但未发现对应前端过滤脚本。 ## 2. 对现有 `docs/test_plan.md` 的评估 现有计划覆盖面大体方向正确,但不能直接作为验收依据: - 文档称“12 个测试模块”,实际只写了 10 个模块。 - 大量断言只验证元素存在,例如按钮、表格、canvas,而没有验证数据来源、交互结果、URL 参数、数据库派生逻辑或副作用。 - 多个用例与当前实现不一致:日志编辑实际是跳转到编辑页,不是打开 modal;对接功能没有 `docking_events`;时间线筛选控件缺少脚本;地点板没有真实纹理切换。 - 测试脚本 `tests/test_e2e.py` 只有 36 个轻量断言,且结果名称编码损坏;它没有执行关键 CRUD 写入、分离、双向日志、时间敏感对接、筛选功能有效性,也没有隔离数据库。 - 测试环境写“真实 PostgreSQL”,但计划包含新增/删除/对接写入,这会污染生产式数据。写入类测试必须切换到隔离测试库或事务回滚。 ## 3. 测试策略 测试分三层执行。 ### A. 非破坏性冒烟回归 目标:确认服务可达、页面主结构存在、关键数据表可渲染、API 基本可用。 适用环境:当前真实 PostgreSQL 或只读数据环境。 执行方式: - HTTP GET 页面检查。 - API GET/错误输入检查。 - 静态模板/脚本契约检查。 - 不新增、不编辑、不删除、不调用会持久写入的对接接口。 ### B. 浏览器交互回归 目标:确认 JS 交互真的工作,而不是只存在 DOM。 适用环境:可运行 Playwright/Browser 的本地环境。 执行方式: - 点击主题切换、时间 modal、侧边栏、地点板 canvas、时间线筛选控件。 - 检查 URL、DOM、canvas 像素和 console error。 - 只执行不写库的交互,除非已切到测试库。 ### C. 写入与业务验收 目标:验证重构核心的业务正确性。 适用环境:隔离 PostgreSQL/SQLite 测试库,或每个测试事务回滚。 执行方式: - 使用固定 fixture 创建资产、日志、节点、对接事件。 - 测试完成后清理或回滚。 - 严禁在真实数据环境直接执行新增/删除/对接/导入。 ## 4. v2 测试矩阵 | 模块 | 优先级 | 用例 | 类型 | 预期 | |---|---:|---|---|---| | 服务/API | P0 | `/api/v1/health` | 冒烟 | HTTP 200,`status=ok`,service 名正确 | | 服务/API | P0 | 燃料列表 API | 冒烟 | 返回 8 个燃料因子 | | 服务/API | P1 | 燃料换算 API `mode=volume/mass` | 冒烟 | 返回每种燃料的换算结果 | | 服务/API | P1 | 燃料换算非法输入 | 冒烟 | HTTP 400,错误信息明确 | | 基础框架 | P0 | 首页可达 | 冒烟 | HTTP 200,显示任务总览 | | 基础框架 | P0 | 侧边栏 | 冒烟 | 显示任务运营、数据中心、燃料换算、API 健康检查 | | 基础框架 | P1 | 主题切换 | 浏览器 | `data-theme` 在 dark/light 间切换,localStorage 持久化 | | 基础框架 | P1 | 模拟时间 modal | 浏览器 | 可打开/关闭/ESC 关闭,Apply 后 URL 写入 `sim_time` | | 任务总览 | P0 | 指标与状态板渲染 | 冒烟 | Tracked Assets / Active Missions / Upcoming / Status Board 存在 | | 任务总览 | P1 | 模拟时间影响 | 业务 | 同一 fixture 在不同 `sim_time` 下派生状态和 upcoming 变化正确 | | 资产列表 | P0 | `/assets` 可达 | 冒烟 | 表格有数据行,显示当前位置/当前事件/日志数 | | 资产列表 | P0 | 搜索路由 | 冒烟 | `q=ST-01` 返回匹配资产 | | 资产列表 | P1 | 类型/排序 | 浏览器 | 下拉改变后请求参数正确,结果排序/过滤正确 | | 资产列表 | P1 | 退役资产默认隐藏 | 业务 | 默认不显示 retired,显式开关后显示 | | 资产详情 | P0 | 从列表进入详情 | 冒烟 | 显示信息卡、Docking Target、Docked Vehicles、Log Entries | | 资产详情 | P1 | 当前状态/位置派生 | 业务 | state interval 覆盖当前时间时取 active state;无 active 时取最近日志或 home_region | | 资产详情 | P1 | 日志分页 | 浏览器 | 多页日志翻页后保留 `sim_time` | | 资产详情 | P2 | 日志搜索/类型筛选 | 浏览器 | 输入/选择后列表实际收缩;若控件无脚本应失败 | | 日志 CRUD | P0 | 新增 state interval | 写入 | 写入后列表出现,state nodes 按 `at_time` 升序 | | 日志 CRUD | P0 | 新增 event point | 写入 | event 无 end/state/nodes 字段要求,保存后可见 | | 日志 CRUD | P0 | 编辑日志页 | 写入 | GET 预填原值,POST 修改后持久化,失败时保留输入并显示 validation dialog | | 日志 CRUD | P1 | 删除日志 | 写入 | 删除后 entries 计数减少,关联 nodes 级联删除 | | 对接功能 | P0 | 需求级数据模型 | 静态/迁移 | 存在 `docking_events` 表和模型字段;当前应失败 | | 对接功能 | P0 | 已有资产对接 | 写入 | parent/child 关系可按时间查询,双方日志/节点按需求写入 | | 对接功能 | P0 | custom name 对接 | 写入 | 只影响当前 asset,保留 child_label | | 对接功能 | P0 | 分离 | 写入 | undocked_at 写入,当前时间晚于分离时不再显示 docked | | 状态板 | P0 | `/mission-preview/status-board` 可达 | 冒烟 | 显示状态分组、筛选栏、upcoming | | 状态板 | P1 | 筛选 | 浏览器 | 资产类型/地点/记录范围筛选后卡片数量和 URL 参数正确 | | 任务列表 | P1 | `/missions` 可达 | 冒烟 | 显示任务/日志聚合列表 | | 任务列表 | P1 | 筛选 | 浏览器 | 类型/地点/记录范围筛选正确 | | 地点板 | P0 | `/mission-preview/location-board` 可达 | 冒烟 | canvas、Scope、Assets in Scope、Ongoing Missions 存在 | | 地点板 | P0 | canvas 非空 | 浏览器 | 截图或像素采样证明非空,console 无错误 | | 地点板 | P1 | 层级导航 | 浏览器 | 点击 Jupiter 进入 Jupiter System,点击 Io 进入 Io,Back 返回 | | 地点板 | P1 | 缩放/拖拽 | 浏览器 | wheel 改变缩放,拖拽改变视图偏移 | | 地点板 | P1 | 资产 scope | 业务 | 不同 scope 下 Assets in Scope 与日志 location 派生一致 | | 地点板 | P2 | 真实纹理 | 视觉/静态 | 使用真实纹理资源或明确降级;当前实现应标记未达 draft 目标 | | 时间线 | P0 | `/mission-preview/timeline` 可达 | 冒烟 | 时间线行和刻度渲染 | | 时间线 | P1 | scale 切换 | 浏览器 | Year/Month/Day 改变 URL 或刻度 | | 时间线 | P1 | 搜索/类型/地点/状态筛选 | 浏览器 | 控件实际改变可见行;当前缺少脚本时应失败 | | 时间线 | P1 | 日期范围 | 浏览器/业务 | 手动范围生效,segment 裁切百分比正确 | | 数据中心 | P0 | 四个列表页 | 冒烟 | `/engines` `/communications` `/tanks` `/vehicles` 均 HTTP 200 且有数据 | | 数据中心 | P1 | 筛选/排序 | 浏览器 | 查询参数生效,表格结果正确 | | 数据中心 | P1 | CRUD | 写入 | 新增/编辑/删除后数据库一致,失败时 validation 明确 | | 导入 | P1 | workbook inspect/import dry run | 业务 | 能识别表结构、自然键冲突、导入统计 | | 可访问性/前端质量 | P1 | console error | 浏览器 | 主路径无 JS error | | 可访问性/前端质量 | P2 | 响应式 | 视觉 | 1440x900、390x844 下无严重重叠 | ## 5. 自动化建议 - 保留一个 `smoke` 套件:只读、可在真实库跑,覆盖 P0 冒烟项。 - 新增一个 `e2e` 套件:Playwright + 测试库,覆盖 P1 浏览器交互。 - 新增一个 `business` 套件:Flask test client + fixture + 事务回滚,覆盖日志派生、对接、时间敏感状态。 - 测试报告必须输出 Markdown 与机器可读 JSON;失败项保留 URL、参数、截图或最小复现步骤。 - 所有写入测试统一使用唯一前缀,例如 `TEST_E2E_20260531_`,并在 teardown 校验清理完成。 ## 6. 本轮建议的验收门槛 - P0 冒烟:100% 通过。 - P0 业务:对接模型完成前允许标记为“未实现”,但不能误报通过。 - P1 浏览器交互:主路径无 console error,地点板 canvas 非空,时间线筛选可实际生效。 - 写入测试:只允许在隔离库执行;真实库环境下报告为 skipped,而不是 pass。