M1.1 收尾: - 24项 P0/P1/P2 bug 修复 (Rust 107 tests + Flutter 15 tests) - Flutter App v0.3: cupertino_icons 修复, 单元测试, 调试面板, APK 52.6MB - 示例插件完善: manifest.json + 请求/响应示范 + 7个测试 - API 文档重写 (以 routes.rs 为唯一权威) - MILESTONES.md 更新至 100% M1.2 启动: - P0: 插件管理 API 闭环 (handle_manager_message Custom 分支 + broadcast_plugin_states) - ServiceManager 集成测试 8/8 (tests/m1_2_service_manager.rs) - M1.2 测试计划 (docs/M1.2_TEST_PLAN.md, 18个E2E场景) - 动态插件系统: auto_rollback + version_manager GC + 路径穿越防护 总计: Rust 115/115 测试, Flutter 15/15 测试, 零 warning Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
348 lines
20 KiB
Markdown
348 lines
20 KiB
Markdown
# M1.2 集成测试计划
|
||
|
||
## 1. 目标与范围
|
||
|
||
- 目标:完成 ShowenV2 在 M1.2 阶段的端到端集成测试、旧功能对齐验证、边界条件验证、错误处理验证与回归基线建立。
|
||
- 范围覆盖:`device`、`screen`、`wifi`、`video`、`ble`、`http` 六个内置插件,动态插件系统,Flutter App 通过 HTTP/WebSocket/BLE 的交互链路。
|
||
- 重点链路:插件注册与启动、消息路由、配置热重载、视频控制、WiFi 配网、BLE 配网、文件管理、动态插件生命周期。
|
||
- 验收对齐:覆盖 `docs/MILESTONES.md` 中 M1.2 的全部任务项,并为 M1.3 性能优化提供可重复的基准输入。
|
||
|
||
## 2. 当前实现观察与 M1.2 风险
|
||
|
||
- `src/main.rs` 按 `device -> screen -> wifi -> video -> ble -> http` 注册静态插件,再扫描 `plugin_store/` 挂载动态插件。
|
||
- `src/core/service_manager.rs` 负责依赖排序、`init -> self_test -> start` 生命周期、消息路由、动态插件错误阈值、自动回退、启停与热替换。
|
||
- `src/plugins/http/routes.rs` 已暴露播放、配置、视频、文件、WiFi、BLE、插件管理、App 下载等 API。
|
||
- 风险 1:HTTP 插件管理 API 通过 `Message::Custom` 向 Manager 发命令,但 `ServiceManager::handle_manager_message()` 当前未处理 `plugin_enable`、`plugin_disable`、`plugin_rollback`、`plugin_switch`、`plugin_install`、`plugin_check_updates`。
|
||
- 风险 2:`/api/plugins` 依赖 `plugin_states` 自定义消息更新状态,但当前源码中未看到 Manager 侧生产该消息,插件列表接口可能返回空状态。
|
||
- 风险 3:`WifiProvisioned`、`DeviceEvent`、部分 `Custom` 消息在当前主链路中无明确生产者/消费者,测试时应区分“未实现”与“回归缺陷”。
|
||
- 风险 4:BLE、WiFi、显示、OpenCV、动态插件 `.so` 装载均依赖 ARM64 实机环境,CI 只能承担部分替身测试。
|
||
|
||
## 3. 测试策略
|
||
|
||
### 3.1 分层策略
|
||
|
||
- 单元测试:验证纯逻辑、解析、状态转换、命令拼装、路径校验、manifest 校验、消息序列化。
|
||
- 集成测试:验证 `ServiceManager` 与插件间消息流、配置重载、插件生命周期、HTTP 路由到消息总线的桥接。
|
||
- 端到端测试:以真实进程启动 `showen_v2`,通过 HTTP/WebSocket/BLE/文件系统操作驱动系统,校验插件协同与用户可见结果。
|
||
|
||
### 3.2 层级分工
|
||
|
||
- 单元:优先放在 `src/core/*`、`src/plugins/*` 内部测试,补齐未覆盖的解析和错误分支。
|
||
- 集成:新增 `tests/m1_2_*.rs`,使用临时目录、测试配置、fake backend、fake dynamic plugin store 驱动系统。
|
||
- E2E:以 ARM64 实机为主,CI 仅跑“无硬件替身版”流程;WebSocket/HTTP 使用 `curl`、`websocat`、Flutter 测试桩执行。
|
||
|
||
### 3.3 覆盖原则
|
||
|
||
- 所有非 `-` 消息交互单元至少有 1 条自动化验证。
|
||
- 所有用户入口 API 至少有 1 条成功场景和 1 条失败场景。
|
||
- 所有动态插件生命周期动作至少覆盖:加载、必需能力自测失败、错误阈值禁用、自动回退、热替换恢复。
|
||
- Flutter 侧至少覆盖:首次连接、实时状态、WiFi 配网、配置读取/保存、APK 下载入口。
|
||
|
||
## 4. src 模块视图
|
||
|
||
- `src/main.rs`:程序入口、配置加载、静态/动态插件注册、主循环。
|
||
- `src/core/`:消息模型、插件 trait、ServiceManager、PluginLoader、VersionManager。
|
||
- `src/plugins/device/`:统一设备能力入口,响应 `DeviceCommand` 并广播 `DeviceResponse`。
|
||
- `src/plugins/screen/`:DevicePlugin thin wrapper,负责防息屏与光标隐藏。
|
||
- `src/plugins/wifi/`:nmcli 驱动的 WiFi 扫描/连接/AP 管理。
|
||
- `src/plugins/video/`:OpenCV 播放器、状态机、状态广播。
|
||
- `src/plugins/ble/`:BlueZ GATT 配网服务,接收 WiFi 结果并向核心转发 WiFi 指令。
|
||
- `src/plugins/http/`:REST/WebSocket/Web UI/App 下载与文件管理桥接层。
|
||
|
||
## 5. 插件 × Message 覆盖矩阵
|
||
|
||
说明:`Rx`=直接处理,`Tx`=直接发送/广播,`Bridge`=对外桥接或间接映射,`Gap`=已有入口但当前实现未闭环,`-`=无直接关系。
|
||
|
||
| 插件/系统 | PlayerCommand | PlayerStatus | Trigger | StateChanged | ScreenLockRequest | CursorVisibility | WifiCommand | WifiResult | WifiProvisioned | ConfigReloaded | ConfigReloadRequest | Shutdown | PluginReady | DeviceCommand | DeviceResponse | DeviceEvent | Custom |
|
||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||
| DevicePlugin | - | - | - | - | - | - | - | - | - | - | - | Rx | Rx | Rx | Tx | - | - |
|
||
| ScreenPlugin | - | - | - | - | Rx/Tx | Rx/Tx | - | - | - | - | - | Rx | - | Tx | - | - | - |
|
||
| WifiPlugin | - | - | - | - | - | - | Rx | Tx | - | - | - | - | - | - | - | - | - |
|
||
| VideoPlugin | Rx | Tx | Rx | Tx | Tx | - | - | - | - | Rx | - | Rx | Tx | - | - | - | - |
|
||
| BlePlugin | - | - | - | - | - | - | Tx(经 GATT) | Rx | - | - | - | Rx | Tx | - | - | - | - |
|
||
| HttpPlugin | Bridge | Rx/Bridge | Bridge | Rx/Bridge | - | - | Bridge | Rx/Bridge | - | Rx/Bridge | Tx/Bridge | Rx | Rx(ble) | - | - | - | Rx(`plugin_states`) |
|
||
| 动态插件系统 | 视插件而定 | 视插件而定 | 视插件而定 | 视插件而定 | 视插件而定 | 视插件而定 | 视插件而定 | 视插件而定 | 视插件而定 | 视插件而定 | - | Rx | 视插件而定 | 视插件而定 | 视插件而定 | 视插件而定 | Rx/Tx |
|
||
| Flutter App | Bridge | Bridge | Bridge | Bridge | - | - | Bridge | Bridge | Bridge(BLE 配网结果) | Bridge | Bridge | - | Bridge(状态映射) | - | - | - | Bridge(插件管理入口) |
|
||
|
||
### 5.1 重点补测项
|
||
|
||
- `DeviceResponse`:补足 DevicePlugin 与 ScreenPlugin/业务插件的联动验证,确认 thin wrapper 没有只发不收的问题。
|
||
- `PluginReady`:验证 `video`、`http`、`ble` 的 ready 事件被 Manager 广播后,HTTP/Flutter 状态同步是否准确。
|
||
- `Custom`:动态插件自定义消息已有基础;HTTP 插件管理类 `Custom` 当前缺少 Manager 闭环,应作为 M1.2 对齐缺陷优先验证。
|
||
|
||
## 6. HTTP API 覆盖范围
|
||
|
||
### 6.1 播放与状态
|
||
|
||
- `GET /api/status`
|
||
- `POST /api/play`
|
||
- `POST /api/pause`
|
||
- `POST /api/next`
|
||
- `POST /api/previous`
|
||
- `POST /api/goto/:index`
|
||
- `GET /api/playlist`
|
||
- `POST /api/scene/:name`
|
||
- `POST /api/trigger/:name`
|
||
- `POST /api/trigger/:name/:value`
|
||
|
||
### 6.2 配置管理
|
||
|
||
- `GET /api/config`
|
||
- `GET /api/config/display`
|
||
- `POST /api/config`
|
||
- `GET /api/config/available`
|
||
- `POST /api/config/switch`
|
||
|
||
### 6.3 视频/文件/App
|
||
|
||
- `GET /api/videos`
|
||
- `POST /api/videos/upload`
|
||
- `DELETE /api/videos/:filename`
|
||
- `GET /api/app/info`
|
||
- `GET /download/:filename`
|
||
- `GET /api/files/:dir`
|
||
- `POST /api/files/:dir/upload`
|
||
- `GET /api/files/:dir/download`
|
||
- `POST /api/files/:dir/delete`
|
||
- `POST /api/files/move`
|
||
- `POST /api/files/:dir/mkdir`
|
||
|
||
### 6.4 WiFi / BLE / WebSocket / 插件管理
|
||
|
||
- `GET|POST /api/wifi/scan`
|
||
- `GET /api/wifi/status`
|
||
- `POST /api/wifi/connect`
|
||
- `POST /api/wifi/ap/start`
|
||
- `POST /api/wifi/ap/stop`
|
||
- `POST /api/wifi/hotspot/start`
|
||
- `POST /api/wifi/hotspot/stop`
|
||
- `POST /api/ble/start`
|
||
- `POST /api/ble/stop`
|
||
- `GET /api/ble/status`
|
||
- `GET /ws`
|
||
- `GET /api/plugins`
|
||
- `GET /api/plugins/:id`
|
||
- `POST /api/plugins/:id/enable`
|
||
- `POST /api/plugins/:id/disable`
|
||
- `POST /api/plugins/:id/rollback`
|
||
- `POST /api/plugins/:id/switch`
|
||
- `POST /api/plugins/install`
|
||
- `POST /api/plugins/check-updates`
|
||
|
||
## 7. 端到端场景清单
|
||
|
||
每个场景均要求记录:日志、HTTP 响应、WebSocket 事件、关键文件变化、插件状态快照。
|
||
|
||
### 场景 1:系统冷启动与插件注册
|
||
|
||
- 前置条件:ARM64 实机;有效配置文件;`plugin_store/` 为空或仅含稳定动态插件。
|
||
- 操作步骤:启动主程序;观察启动日志;调用 `GET /api/status`;建立 `/ws` 连接。
|
||
- 预期结果:6 个内置插件按依赖顺序启动;若动态插件存在则完成自测;`/api/status` 可返回;WebSocket 首包包含 `status_update`、`config_update`、`ble_update`。
|
||
|
||
### 场景 2:播放控制主链路
|
||
|
||
- 前置条件:播放列表至少 2 个有效视频;HTTP 服务启用。
|
||
- 操作步骤:依次调用 `/api/play`、`/api/pause`、`/api/play`、`/api/next`、`/api/previous`。
|
||
- 预期结果:VideoPlugin 正确切换状态;WebSocket 推送 `status_update`;暂停时触发 ScreenPlugin 释放防息屏,恢复播放时重新加锁。
|
||
|
||
### 场景 3:按索引跳转视频
|
||
|
||
- 前置条件:播放列表长度 >= 3。
|
||
- 操作步骤:调用 `POST /api/goto/2`,随后调用 `GET /api/status`。
|
||
- 预期结果:当前索引变为 2;当前视频与目标条目一致;无越界异常。
|
||
|
||
### 场景 4:状态机触发器切换场景
|
||
|
||
- 前置条件:配置内存在多个 state/trigger 规则。
|
||
- 操作步骤:调用 `POST /api/trigger/voice/name` 或 WebSocket `{"cmd":"trigger","name":"voice","value":"name"}`。
|
||
- 预期结果:VideoPlugin 接收 `Trigger`;若状态变化则广播 `StateChanged`;HTTP/WebSocket 观察到 `state_update`。
|
||
|
||
### 场景 5:配置热重载
|
||
|
||
- 前置条件:当前配置文件合法,可修改显示或播放参数。
|
||
- 操作步骤:`POST /api/config` 提交合法 JSON;观察日志与 `/ws`;再次调用 `/api/config`。
|
||
- 预期结果:配置文件落盘;Manager 处理 `ConfigReloadRequest` 并广播 `ConfigReloaded`;VideoPlugin 与 HttpPlugin 更新内部状态;新配置立即可见。
|
||
|
||
### 场景 6:切换配置文件
|
||
|
||
- 前置条件:`configs/` 下至少 2 个合法配置文件。
|
||
- 操作步骤:调用 `GET /api/config/available`,选择另一个配置后调用 `POST /api/config/switch`。
|
||
- 预期结果:目标配置通过校验后覆盖当前活动配置;系统广播配置重载;`active` 配置更新。
|
||
|
||
### 场景 7:视频文件上传与删除
|
||
|
||
- 前置条件:视频目录可写;准备 1 个小视频文件。
|
||
- 操作步骤:调用 `/api/videos/upload` 上传;调用 `/api/videos` 检查列表;随后调用 `DELETE /api/videos/:filename`。
|
||
- 预期结果:上传成功且文件可见;删除后列表消失;不会因文件名注入逃逸目录。
|
||
|
||
### 场景 8:文件管理器跨目录操作
|
||
|
||
- 前置条件:`videos/`、`configs/`、`plugin_store/` 可访问;创建测试子目录。
|
||
- 操作步骤:调用 `/api/files/:dir` 浏览、`mkdir` 新建目录、`upload` 上传、`move` 移动、`download` 下载、`delete` 删除。
|
||
- 预期结果:仅允许受管目录;子路径校验生效;跨文件系统移动可回退到 copy+delete;非法路径返回拒绝。
|
||
|
||
### 场景 9:WiFi 扫描与状态查询
|
||
|
||
- 前置条件:实机具备 WiFi 网卡与 `nmcli`;附近存在可扫描网络。
|
||
- 操作步骤:调用 `GET /api/wifi/scan`;随后调用 `GET /api/wifi/status`。
|
||
- 预期结果:WiFiPlugin 返回去重后的网络列表;状态接口返回连接状态、SSID、IP;WebSocket 有 `wifi_update`。
|
||
|
||
### 场景 10:WiFi 连接成功
|
||
|
||
- 前置条件:准备可连接的测试 WiFi;账号密码正确。
|
||
- 操作步骤:调用 `POST /api/wifi/connect`;等待 1~10 秒后查询 `/api/wifi/status`。
|
||
- 预期结果:连接命令进入 WifiPlugin;返回成功消息;状态转为 connected;IP 地址可读。
|
||
|
||
### 场景 11:AP 热点启停
|
||
|
||
- 前置条件:设备支持热点模式。
|
||
- 操作步骤:调用 `POST /api/wifi/ap/start`;确认热点启动;随后调用 `POST /api/wifi/ap/stop`。
|
||
- 预期结果:热点名称和密码按请求生效;停止成功;兼容别名 `/api/wifi/hotspot/*`。
|
||
|
||
### 场景 12:BLE 配网成功链路
|
||
|
||
- 前置条件:BLE 在配置中启用;手机或测试脚本可写 GATT 特征;目标 WiFi 可用。
|
||
- 操作步骤:启动程序;通过 BLE 写入 SSID、密码、`connect` 命令;观察 BLE 状态特征、日志、WiFi 状态。
|
||
- 预期结果:BLE 将凭据转发为 `WifiCommand::Connect`;WifiPlugin 返回结果后 BLE 状态特征更新;HttpPlugin 反映 `ble_update` 与 `wifi_update`。
|
||
|
||
### 场景 13:WebSocket 实时控制链路
|
||
|
||
- 前置条件:WebSocket 已连接。
|
||
- 操作步骤:发送 `play`、`pause`、`goto`、`trigger`、`connect`、`ap_start` 命令 JSON。
|
||
- 预期结果:合法命令被解析为内部消息并入队;响应 `{"ok":true}`;状态更新推送到客户端。
|
||
|
||
### 场景 14:动态插件挂载与自测通过
|
||
|
||
- 前置条件:`plugin_store/registry.json` 指向一个合法动态插件版本;manifest 声明 capability 且自测通过。
|
||
- 操作步骤:启动程序;查看日志与插件状态接口。
|
||
- 预期结果:动态插件被加载、`init`、`self_test`、`start`;必需能力通过;插件状态显示 enabled。
|
||
|
||
### 场景 15:动态插件必需能力失败并自动回退
|
||
|
||
- 前置条件:准备 active 版本失败、stable 版本可回退的动态插件仓库;错误策略为 `auto_rollback`。
|
||
- 操作步骤:启动程序或发送触发失败的消息直至达到错误阈值。
|
||
- 预期结果:当前版本被禁用并触发回退;若稳定版本可重载则恢复运行;否则 `needs_rollback=true` 并记录日志。
|
||
|
||
### 场景 16:动态插件热替换恢复旧版本
|
||
|
||
- 前置条件:已加载动态插件;准备一个启动失败的新版本。
|
||
- 操作步骤:通过测试钩子或后续管理命令触发热替换。
|
||
- 预期结果:旧插件先 stop;新插件 init/start 失败后恢复旧插件;资源无双开窗口。
|
||
|
||
### 场景 17:Flutter App 首次连接与实时状态
|
||
|
||
- 前置条件:Flutter App 安装完成;手机与设备网络可达。
|
||
- 操作步骤:Flutter App 输入设备地址并连接;进入主控页;触发播放/暂停;保持 WebSocket 连接。
|
||
- 预期结果:App 能读取 `/api/status`、`/api/playlist`、`/api/ble/status`;能接收 `status_update`、`state_update`、`wifi_update`;UI 与设备状态一致。
|
||
|
||
### 场景 18:Flutter App 配网与 APK 下载入口
|
||
|
||
- 前置条件:HTTP 服务与下载目录启用;存在 `downloads/showen-app.apk`。
|
||
- 操作步骤:Flutter 通过 BLE 或 HTTP 执行配网;访问 App 下载信息接口;点击下载 APK。
|
||
- 预期结果:`/api/app/info` 返回正确版本、大小、下载地址;APK 下载成功;Flutter 侧配网链路完成且错误可回显。
|
||
|
||
## 8. 边界条件清单
|
||
|
||
- 1. 空 `playlist` 启动:`/api/status`、`/api/videos`、WebSocket 快照均不崩溃。
|
||
- 2. `goto` 越界:返回 `400`,不改变当前播放状态。
|
||
- 3. 上传 100MB 边界:恰好上限通过,超过上限返回 `413`。
|
||
- 4. 文件名包含 `..`、`/`、`\\`:上传、下载、删除、配置切换均拒绝。
|
||
- 5. WiFi SSID/密码包含空格、引号、反斜杠、冒号:命令参数保真。
|
||
- 6. BLE 写入空 SSID 或空命令:状态特征返回错误,不向核心发送无效命令。
|
||
- 7. 动态插件 manifest `id/version` 与目录不匹配:加载应失败且不污染注册表。
|
||
- 8. 动态插件 required capability 缺失于自测结果:视为失败并按策略处理。
|
||
- 9. `ConfigReloadRequest` 指向损坏 JSON:Manager 记录失败,保留旧配置。
|
||
- 10. WebSocket 收到非法 JSON 或缺少 `cmd`:返回结构化错误字符串,不影响连接。
|
||
- 11. `remote_control.enabled=false`:HTTP 插件不启动监听,但系统其他插件正常工作。
|
||
- 12. 关闭中的广播消息:`Shutdown` 广播后所有启用插件按逆序停止。
|
||
|
||
## 9. 错误处理场景清单
|
||
|
||
- 1. HTTP 发送到关闭的消息通道:播放/WiFi/插件管理 API 返回 `500`。
|
||
- 2. WiFi 10 秒无响应:`/api/wifi/*` 返回 `504`。
|
||
- 3. WiFi 返回非 JSON:HTTP 层返回 `502`。
|
||
- 4. WiFi 返回 `{ok:false}`:HTTP 层透传为 `500` 业务错误。
|
||
- 5. 配置更新请求体非 UTF-8:返回 `400`。
|
||
- 6. 配置切换目标文件不存在:返回 `404`。
|
||
- 7. 文件下载缺少 `path` 参数:返回 `400`。
|
||
- 8. 文件移动目标已存在:返回 `409`。
|
||
- 9. 静态插件 init/start 失败:启动整体失败并退出。
|
||
- 10. 动态插件 init/start 失败:仅该插件禁用,其他插件继续运行。
|
||
- 11. 动态插件错误阈值达到上限:`disable_and_log` 时禁用;`auto_rollback` 时回退。
|
||
- 12. 热替换新插件启动失败:恢复旧插件;若恢复失败则明确标记 disabled。
|
||
- 13. BLE worker 崩溃:3 秒重试;停止信号下应及时退出。
|
||
- 14. `/api/plugins*` 命令当前无 Manager 闭环:应在 M1.2 先作为已知功能对齐缺陷立项验证并修复。
|
||
|
||
## 10. 性能基准定义
|
||
|
||
M1.2 不做深度优化,但必须建立可重复基准,供 M1.3 追踪。
|
||
|
||
- 启动时间:从进程启动到 `http` 与 `video` 均发出 `PluginReady`,目标 `<= 3s`(无动态插件时)。
|
||
- HTTP 控制延迟:`POST /api/play` 到首个 `status_update`,P95 `<= 200ms`。
|
||
- WebSocket 状态推送延迟:内部消息到客户端收到事件,P95 `<= 150ms`。
|
||
- 配置热重载耗时:`POST /api/config` 到 `config_update` 推送完成,P95 `<= 500ms`。
|
||
- WiFi 状态查询:单次 `/api/wifi/status` 完成时间 P95 `<= 3s`,超时阈值 10s。
|
||
- 视频上传:100MB 文件上传不出现进程 OOM,峰值 RSS 不超过基线版本 120%。
|
||
- 长稳冒烟:连续 4 小时播放 + WebSocket 连接 + 周期性 WiFi 状态查询,无崩溃、无句柄泄漏迹象。
|
||
- 动态插件回退:达到错误阈值到完成禁用/回退标记,P95 `<= 1s`(不含磁盘 I/O 抖动)。
|
||
|
||
## 11. 测试环境要求
|
||
|
||
### 11.1 ARM64 实机
|
||
|
||
- Linux ARM64。
|
||
- 安装 `nmcli`、BlueZ、OpenCV 运行时、`websocat`、`curl`。
|
||
- 具备显示输出、WiFi 网卡、BLE 适配器。
|
||
- 可访问测试路由器,并可创建 AP 热点。
|
||
- 支持动态插件 `.so` 装载与回退仓库读写。
|
||
|
||
### 11.2 CI 环境
|
||
|
||
- 运行 Rust 单元/集成测试。
|
||
- 使用 fake backend/fake plugin store 替代硬件。
|
||
- 执行 HTTP 路由级测试、消息序列化测试、ServiceManager 生命周期测试。
|
||
- 不承担真实 OpenCV 显示、真实 WiFi/BLE、真实动态 `.so` 装载回归。
|
||
|
||
### 11.3 Flutter 联调环境
|
||
|
||
- Android 真机优先,至少 1 台;若支持则补 1 台 iOS 设备做网络连通冒烟。
|
||
- Flutter App 使用与服务端同版本 API 模型。
|
||
- 同时验证 HTTP 轮询回退与 WebSocket 实时模式。
|
||
|
||
## 12. 自动化落地建议
|
||
|
||
- 新增 `tests/m1_2_service_manager.rs`:启动顺序、关闭顺序、广播、配置重载、动态插件错误策略。
|
||
- 新增 `tests/m1_2_http.rs`:播放/配置/文件/WiFi/BLE/插件管理 API 路由级验证。
|
||
- 新增 `tests/m1_2_dynamic_plugin.rs`:registry、manifest、热替换、回退、必需能力失败。
|
||
- 新增 `scripts/e2e/`:实机冒烟脚本,串联 `curl + websocat + 日志断言`。
|
||
- 新增 `clients/flutter/integration_test/`:设备发现、状态同步、WiFi 配网、配置保存。
|
||
|
||
## 13. 预估工作量与排期建议
|
||
|
||
### 13.1 工作量
|
||
|
||
- 测试基建与 fake fixture:2 人日。
|
||
- HTTP/ServiceManager 集成测试补齐:3 人日。
|
||
- 动态插件系统回退/热替换测试:2 人日。
|
||
- ARM64 实机 WiFi/BLE/视频链路验证:3 人日。
|
||
- Flutter 联调与回归:2 人日。
|
||
- 缺陷修复回归缓冲:2~4 人日。
|
||
- 合计:12~16 人日。
|
||
|
||
### 13.2 两周建议排期
|
||
|
||
- 第 1-2 天:补齐测试基建,冻结 M1.2 测试配置与样本数据。
|
||
- 第 3-5 天:完成 ServiceManager、HTTP、文件管理、配置热重载自动化测试。
|
||
- 第 6-7 天:完成动态插件系统自动化测试,并确认插件管理 API 闭环缺陷。
|
||
- 第 8-10 天:ARM64 实机执行视频/WiFi/BLE/Flutter E2E,集中提单。
|
||
- 第 11-12 天:修复缺陷并回归,补齐性能基线数据。
|
||
- 第 13-14 天:做旧版本功能对齐复盘、输出测试报告与遗留风险清单。
|
||
|
||
## 14. M1.2 完成判定
|
||
|
||
- 六个内置插件均有成功链路与失败链路验证证据。
|
||
- 动态插件系统完成加载、自测、禁用、回退、热替换验证。
|
||
- Flutter App 完成 HTTP/WebSocket/BLE 三条交互链路联调。
|
||
- 所有关键用户场景、边界条件、错误处理场景均有执行记录。
|
||
- 已知阻断性问题清零,或被明确降级并获负责人确认。
|