docs(UI自动化): 新增第七节「板端有状态导航判据」+ 过密码口径指针
票 = task-25 第二半(配套上一笔的 scripts/board_ui_nav.py)。 docs/UI设计/UI_自动化测试流程.md 新增第七节: - 7.1 为什么必须闭环:KEY 空帧 + 盲走 9 帧仅 3 帧名副其实的实测表(含每帧落点与墨量), 三张证据 PNG 落 docs/测试说明/boot_log_data/(弹框裁切现场、盲走落密码页、盲走停在级联)。 「512 bits 神秘空白态」在表里定名为**密码输入页**——走带 #P 注记的叶子时第一屏是要密码。 - 7.2 认屏三判据(表格:判据 + 为什么这样判)与两条实测纪律(l 收列、#P 注记顺序)。 - 7.3 四种用法与钩子档位:钩子只跑快检档,完整档(含闭环)合入前 / 上板前手工跑;「没跑」 与「跑过且通过」在脚本输出里是两种打印,不互相顶替。 - 7.4 四条已知限度:末两行叶子弹框被裁(真机定位留台架窗口取证,是取证题不是编码题)、 同标题多态不区分、与黄金文案的有意耦合、快检不证导航。 - 7.5 过密码口径:查看 000 / 修改 123,键序与黄金回归编辑态完全一致;只读判据不自动升格。 docs/UI设计/UI_数据供给设计说明.md 追加落地注·五(指针级):写路径(批 5)必须把「过密码」 当显式状态——快照层不提供「曾否进过某页」,可写性只由 UI 权限态与 par.locked 决定。 纯文档与取证图,无行为改动。取证 PNG 由 simulator/i1_to_png.py 从留档帧转出(4 倍放大,与 其余 UI 证据图同规格);本笔钩子按各自触发面执行,其中 doc-links 会核对本节新增的两处 相对链接与三张图的存在性。
This commit is contained in:
@@ -526,6 +526,14 @@ typedef struct {
|
||||
> 「合位/分位」这条词映射当前**没有任何自动化证据覆盖**(像素恒 IV、页面依赖 LVGL 也进不了
|
||||
> 主机单测),它已登记为开入落地后的台架判据,而不是假装测过。
|
||||
|
||||
> 【落地注·五(写路径判据的前置口径,指针级,不重述细节)】带 `#P` 注记的叶子**第一屏是密码
|
||||
> 页、不是内容页**:真机实测里三帧「深页盲走」的落点都是密码输入页(墨量 512,与黄金参考
|
||||
> 的两张密码态逐字对得上)。所以批 5 的写路径判据必须把「过密码」当**显式状态**处理——快照
|
||||
> 层不提供「曾否进过某页」这种隐式状态,可写性只由 UI 侧权限态与 `par.locked` 共同决定,
|
||||
> 「当前是否已过密码」既不真实也不该被推断。判据侧的过法只有一套(查看密码 = 出厂 000 /
|
||||
> 修改密码 = 123,键序与黄金回归的网口设置编辑态完全一致),口径与纪律见
|
||||
> `docs/UI设计/UI_自动化测试流程.md` §7.5;本节只登记这条事实,避免两份文档各说各话。
|
||||
|
||||
---
|
||||
|
||||
## 12. 验收判据
|
||||
|
||||
@@ -102,6 +102,88 @@ cmake --build simulator/build --config Debug # 0) 构建模拟器(须 0 警
|
||||
- `菜单页面设计.md` §9:内容页对象树 / 几何表 / 内存预算(本文数字的来源)
|
||||
- `simulator/README.md` §3.5/§3.6:无头模式(`--keys`/`--screenshot`)与回归脚本说明
|
||||
|
||||
## 七、板端有状态导航判据(真机侧,`scripts/board_ui_nav.py`)
|
||||
|
||||
> 前五节都在模拟器里跑;模拟器与固件同一份 UI 源码,像素判据在 PC 上就成立。本节管另外
|
||||
> 一半:**真机上把页面走到、并证明走对了**——这一步只有真机需要(模拟器侧把键序直接喂给
|
||||
> 无头进程,状态是确定的)。
|
||||
|
||||
### 7.1 为什么必须闭环(实测 2026-10-25 大窗)
|
||||
|
||||
- RemoDispBus 的 **KEY 应答是空帧、不携带任何状态**:发了 5 个键不等于到了第 5 层。
|
||||
- 靠预置键序盲走,9 个「应当到达」的态里只有 3 个真是那个态:
|
||||
|
||||
| 留档帧 | 文件名声称 | 实际是 | 墨量 | 证据 |
|
||||
|---|---|---|---|---|
|
||||
| 00 / 01 / 02 | 根菜单 / 装置信息 / 交流量 | 名副其实 | 3226 / 3476 / 3346 | 认屏一致 |
|
||||
| 03_dc | 直流量 | 菜单级联(整屏无页标题) | 4961 | [blindwalk_cascade](../测试说明/boot_log_data/20261025_uinav_blindwalk_cascade.png) |
|
||||
| 04_yx / 05_yxp2 / 06_soe | 遥信量两页 / SOE记录 | **密码输入页** | 512 / 515 / 512 | [blindwalk_pwd512](../测试说明/boot_log_data/20261025_uinav_blindwalk_pwd512.png) |
|
||||
| 07_vparam | 参数查看页 | 网口设置页 | 3774 | 标题带命中「网口设置」 |
|
||||
| 08_vset | 定值查看页 | 装置信息页 | 3474 | 标题带命中「装置信息」 |
|
||||
|
||||
那三帧的 512 墨量曾被记成「神秘空白态」;与黄金参考 `shot_pwd.bin`、`shot_pwe.bin`(墨量
|
||||
同为 512)逐字对得上之后可以定性:**走带 `#P` 注记的叶子时,第一屏是要密码,不是内容页**
|
||||
——写路径判据(批 5)因此必须把「过密码」当显式状态处理,口径见 §7.5。
|
||||
- 结论:判据脚本只能信画面。脚本因此**每按一键重新认屏**再决定下一个键,且「到达」只由
|
||||
**页面身份**裁定;中途任何假设都写进轨迹,绝不当成结论。
|
||||
|
||||
### 7.2 认屏的三条判据(精确字形匹配,复用同一份 `ui_font_cn_12`)
|
||||
|
||||
| 态 | 判据 | 为什么这样判 |
|
||||
|---|---|---|
|
||||
| 内容页 | 标题带命中 + 该页黄金行文本至少一条 + 页码行「第 N 页,共 M 页」 | 只认标题会把两屏认成一屏(「参数」既是菜单项也是页名);页码让「遥信量第 2 页 / 共 5 页」成为可比对的事实 |
|
||||
| 菜单 | 在白底横条(反白选中行)覆盖的行范围内、**整幅宽度**找反白标签;长标签优先,命中框被包住者丢 | 选中行是黑字白底,只按正常极性永远读不出选中项;「参数定值」那行必然同时落进子串「参数」「定值」,不去重就凭空多两列 |
|
||||
| 密码页 | 「用户密码」四个字里中三个 | 整串匹配实测差约 1 px 打不中;数字格随输入变,不参与判定 |
|
||||
|
||||
另两条实测纪律(理由写死在代码注释里,此处不重述):
|
||||
|
||||
- **收级联列按 `l`、不按 `s`**:菜单态按 `s` 不收列,用 `ssssssss` 回根正是深页错位的来源之一;
|
||||
- 菜单树的 `#P` 注记可能写在 `#page=` **之前**(`网口设置 #P #page=net_cfg`),解析顺序错了就
|
||||
剥不掉,那一叶的页面 id 也永远认不出来。
|
||||
### 7.3 用法与门禁档位
|
||||
|
||||
```powershell
|
||||
# 认屏快检:18 张黄金参考(+ 若有台架留档帧),秒级,不需要构建产物
|
||||
& '.venv\Scripts\python.exe' scripts/board_ui_nav.py --selftest-quick
|
||||
# 完整自检:再加全绑定页闭环导航(需模拟器可执行文件,约 30 s)
|
||||
& '.venv\Scripts\python.exe' scripts/board_ui_nav.py --selftest
|
||||
# 台架窗口:一条命令走完全部绑定页并逐页存帧(须持 bench 锁)
|
||||
& '.venv\Scripts\python.exe' scripts/board_ui_nav.py --walk
|
||||
# 只走一页并抓图;--trace 落步迹、--dump-fail 落「认错的那一屏」
|
||||
& '.venv\Scripts\python.exe' scripts/board_ui_nav.py --board --to yx --grab D:/tmp/yx
|
||||
```
|
||||
|
||||
- 提交钩子 `uinav-selftest` 跑的是**快检档**(`--selftest-quick`)。为什么不挂完整档:闭环
|
||||
那一段要模拟器可执行文件——它是构建产物,新工作树里没有,正是同一天 `mem-numbers` 缺
|
||||
`.map` 那课的形状。脚本对「缺可执行文件」报 FAIL 并给可执行提示,不「跳过当通过」;
|
||||
合入前 / 上板前请手工跑一次完整档(快检 ≠ 闭环,两者结论不同,别互相顶替)。
|
||||
- 板端后端只连 7003 取图注键,**不含串口、烧录、复位**;跑真机必须自己持 `bench` 锁。
|
||||
- 台架留档帧目录在 gitignore 内、不入库:缺就整段跳过,不算失败——但脚本把「没跑」与
|
||||
「跑过且通过」分开打印,不把前者写成后者。
|
||||
|
||||
### 7.4 已知限度(别把它当万能闸)
|
||||
|
||||
1. **根列选中落在最后两行时,子菜单弹框会被屏幕裁掉**:选带不在可扫窗口里,列数会漏计。
|
||||
脚本对策是「枚举 + 验终点」——末列先盲按 N 次下移再进(第 N 次尝试),成败仍只由页面
|
||||
身份裁定,所以它会大声报错而不是静默走错页。实测 `自检记录` / `运行记录` 两页在模拟器
|
||||
上 5 次枚举内没吃到,现场帧见
|
||||
[popup_clipped](../测试说明/boot_log_data/20261025_uinav_popup_clipped.png);
|
||||
**真机上那层弹框究竟画在哪,留台架窗口取证后再定修法**——这是取证题,不是编码题。
|
||||
2. 同一标题的多个显示态(网口设置的 只读 / 编辑 / 保存)在分类里都是同一个页面 id
|
||||
`net_cfg`;要区分得看行内文本,写路径判据需要时再加。
|
||||
3. 认屏复用黄金参考的文案:改了页面文案而没同步 `simulator/tests/` 的文本断言表,本节脚本
|
||||
会一起红。那是**有意的耦合**(两处必须同时改),不是脚本脆弱。
|
||||
4. 快检档只证「认屏认得对」,不证「导航走得对」;后者只有完整档的闭环那一段会响。
|
||||
|
||||
### 7.5 过密码的口径(与黄金回归同源,只有一套走法)
|
||||
|
||||
查看密码 = 出厂 `000`(直接 `e` 确认);修改密码 = `123`,键序 `u,r,u,r,u,r,e`,与
|
||||
`simulator/tests/check_content_pages.py` 的 `netcfg_edit` 态**完全一致**——刻意不另发明一套走法
|
||||
(两套走法迟早分叉,而分叉的那一边往往是真机)。导航器**默认只过查看密码**:判据需要写
|
||||
路径权限时必须显式传 `modify=True`,**不因「能进去」就自动升格成可写**——只读判据偷偷拿到
|
||||
修改权限,等于把判据的边界让给了实现。
|
||||
|
||||
---
|
||||
## 变更记录
|
||||
|
||||
| 日期 | 变更 |
|
||||
@@ -114,4 +196,7 @@ cmake --build simulator/build --config Debug # 0) 构建模拟器(须 0 警
|
||||
| 2026-09-13 | 管线同步:`UI_界面制作流程.md` 移除 HTML 样机阶段(五阶段 → 四阶段 P0~P4),本文定位改为"P2/P3 门禁的可执行版本";§六 关系描述更新为 P0 规格 → P1 编码 → P2 本文回归 → P3 上机目检 → P4 归档;移除 `tools/ui_mock/` 引用 |
|
||||
| 2026-10-11 | **裁剪 LVGL 死代码(F-1/F-2/F-3)时的门禁记录**:先用**未裁剪**配置 `--update` 生成 11 页黄金参考,再切到裁剪配置重编重跑 → **逐字节全部一致**(菜单 8 状态像素一致),证明裁剪零视觉影响。池水位门禁随之 5440/5520 → **5368/5448**(−72 B;一次性残留仍 80 B,故非泄漏变化,见 §三 水位历史)。顺带揪出并修掉 `Lib/lv_conf.h` 与 `simulator/lv_conf.h` 的**长期漂移**(模拟器早已 I1-only、MCU 端未裁)→ 规则见 `UI_设计架构.md` §1.4 第 10 条,量化见 `../内存管理/RAM使用分析与优化方案.md` §2.6.4 |
|
||||
| 2026-10-15 | **回归改为自洽运行(修 `netcfg_save` 假失败)**:`check_menu_rows.py` / `check_content_pages.py` 一律以**空临时目录当工作目录**跑 `lvgl_sim`(模拟器按 CWD 读写 `sim_config.ini`,残留档会改变页面内容);`simulator/main.c` 的 `--cfgtest` 加外壳,**无论成败一律删除伪造的 4000 B 配置档**——旧行为连 PASS 路径也会留雷,之后每次 UI 回归的保存行都从 `OK` 变 `ERR`(引擎拒写超长文档,属正确行为)。脚本里"删 `sim_netcfg.bin` 残留"的旧兼容清理随之作废(旧档迁移 2026-10-10 已删),改为**只提示不删除**。修后 11 页 + 往返池水位 5,448 B 全过,**未刷任何黄金参考**;排查口径见 §五 |
|
||||
| 2026-10-25 | 新增第七节「板端有状态导航判据」(`scripts/board_ui_nav.py`):真机侧闭环导航、
|
||||
盲走 9 帧仅 3 帧名副其实的实测表、认屏三判据、`uinav-selftest` 钩子档位、四条已知限度与
|
||||
过密码口径;三张证据 PNG 落 `boot_log_data/` |
|
||||
| 2026-10-22 | **`ref/*.bin` 像素黄金参考改为入库**(撤销 2026-09-10 的"整目录不入库"):`.gitignore` 由忽略整目录收窄为只忽略 `ref/*.png`。动因是这条门禁不可移植——新克隆/新工作树里基准必然缺失,`ui-golden` 报「缺黄金参考」而不是回归结论;本仓实测两次同类踩坑(并行工作树里第一次跑必失败,只能现场 `--update` 造基准,而"现场造的基准"恰好失去意义)。入库前做了可复现性验证:主树(`ref/` 生成于 2026-10-11)与新工作树各自独立构建 `lvgl_sim`,11 个 `.bin` SHA-256 全部一致。§四 与"何时不该更新"随之改写:`--update` = 改基准,会进 `git diff`,须逐页过目并在提交正文说明 |
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
Reference in New Issue
Block a user