修复 Studio 失败测试并新增合并门禁

把丢失的 box 录像放回 apps/studio/tests/data/,修掉第 3 节 3–10 号与两处过时测试桩,
注册 timing 标记并让根目录收集零错误;新增 tools/gate.ps1 与可选的 pre-push 钩子。
验证:studio 524 通过 19 跳过、shared 467 通过 18 跳过、ui_check 632 项 0 失败、gate.ps1 退出码 0。
细节见 docs/test-repair-plan.zh.md。
This commit is contained in:
ykcheungab
2026-10-18 19:24:31 +08:00
parent dcabd547fa
commit 433b76e43c
38 changed files with 1036 additions and 171 deletions
+1 -1
View File
@@ -367,7 +367,7 @@ Panel 控件:三维开关、预设视角、复位、外壳显隐、显示形
### 11.1 依赖
- 继续使用项目验证过的 Python、**PySide6**、NumPy;新增 PyOpenGL。先建立兼容版本范围,PoC 通过后分别锁定 Windows/Jetson/QCS6490 的版本与 wheel 哈希,不在文档虚构已验证版本。
Qt 绑定选 PySide6(LGPLv3)而不是 PyQt5(GPLv3-or-commercial):两个 app 都只允许 PySide6,由 `apps/studio/tests/test_binding_purity.py` 与 `apps/autocal/tests/test_binding_purity.py` 静态强制;构建环境里出现第二个 binding 会让 `pyqtgraph` 绑错(`setup.ps1` 会卸载 PyQt5/PyQt6/PySide2,`main.py` 在 import pyqtgraph 之前设 `PYQTGRAPH_QT_LIB=PySide6`)。
Qt 绑定选 PySide6(LGPLv3)而不是 PyQt5(GPLv3-or-commercial):两个 app 都只允许 PySide6,由 `apps/studio/tests/test_studio_binding_purity.py` 与 `apps/autocal/tests/test_binding_purity.py` 静态强制;构建环境里出现第二个 binding 会让 `pyqtgraph` 绑错(`setup.ps1` 会卸载 PyQt5/PyQt6/PySide2,`main.py` 在 import pyqtgraph 之前设 `PYQTGRAPH_QT_LIB=PySide6`)。
- PyOpenGL_accelerate 是可选优化,不作为首轮 ARM 安装前提;官方也将它列为可选项。[PyOpenGL 安装](https://pyopengl.sourceforge.net/documentation/installation.html)
- 加密发布模式另引入成熟密码库;Blender、GLB 转换工具只在资产构建环境,客户运行时不依赖 Blender。
- PyOpenGL 不自带 GPU 驱动。不要为了满足依赖让 pip/系统包覆盖板卡 BSP 指定的 EGL/GLES 库。
+2 -2
View File
@@ -191,7 +191,7 @@ graph TB
| 规则 | 是否成立 | 证据 |
|---|---|---|
| 模块级无循环依赖 | ✅ | 扫描 **94 个模块**(studio 37 + shared 57)的 import:**环 0 个** |
| 共享层不依赖 Qt | ✅(有一条惰性例外) | `import` 时拉进 PySide6 的模块**全部**在 `orisys_studio.*`;`shared/theme/qss.py` 用 PySide6 **画图标时**才 import(函数内 + try 保护)。两个 app 的 `tests/test_binding_purity.py` 现在静态强制"只允许 PySide6"(在此之前 `qss.py` 的 import 因为写的是 PyQt5 而静默失败,AutoCal 的箭头图标一直没有画出来) |
| 共享层不依赖 Qt | ✅(有一条惰性例外) | `import` 时拉进 PySide6 的模块**全部**在 `orisys_studio.*`;`shared/theme/qss.py` 用 PySide6 **画图标时**才 import(函数内 + try 保护)。两个 app 的 `test_studio_binding_purity.py`/`test_binding_purity.py` 现在静态强制"只允许 PySide6"(在此之前 `qss.py` 的 import 因为写的是 PyQt5 而静默失败,AutoCal 的箭头图标一直没有画出来) |
| OpenGL 从不在 import 时拉入 | ✅ | 唯一使用者 `scene3d/gl_backend.py` 是函数内惰性 import;`widget.py` 同理 |
| 三维调度与相机无 Qt,可脱离 GUI 测试 | ✅ | 新解释器里 `import orisys_studio.scene3d.coordinator` / `.camera` → 不含 PySide6/OpenGL/SDK |
| 采集侧可在无 GUI 环境导入 | ✅ | `acquisition.arrows` / `.sinks`、`record.playback`、`scene3d.contracts`、`scene3d.composer` 全部"干净" |
@@ -305,7 +305,7 @@ graph TB
|---|---|---|---|---|
| 1 | ~~**拆 `app_window`**~~ **已完成**(会话 → `session_controller`、回放 → `replay_controller`、布局 → `view_layout`、显示偏好 → `display_prefs`、标定规则 → `calibration_service`;窗口 3044 → 2309 行) | 改动热点从 1 个 3000 行文件变成 5 个 200–650 行文件 + 一个装配器;每个控制器可脱离窗口单测(新增 41 项) | ~~中~~(已付:纯搬运 + 一层转发,未改行为) | `test_ui_smoke`/`test_scene3d_view`/`ui_check` 全绿;`git diff` 只应有移动与转发 |
| 1b | **删掉过渡转发**:窗口里那约 40 个 `self._x` 转发是给 tests/`ui_check` 用的桥,下一次改动落在哪个控制器,就顺手把该控制器的转发与测试调用点改成 `self.<controller>.*` | 窗口真正退到"只有装配";转发留着会慢慢变成新的隐式耦合 | 小-中(每次改动顺带;一次性清理会大面积改测试) | 全套 + `ui_check` |
| 2 | **给共享层加"依赖规则测试"**:AST 扫描断言 `shared` 不得 eager import PySide6/OpenGL(现状成立),以及 `studio.scene3d` 不得 import `acquisition`;把 `force → orisys` 的现状登记为"已知例外"或改为惰性 —— *部分已完成*:`apps/studio/tests/test_binding_purity.py` 与 `apps/autocal/tests/test_binding_purity.py` 已经强制"只允许 PySide6"(含无作用域枚举的检查,且用真 binding 内省而不是手写枚举名单);`studio.scene3d` 与 `force → orisys` 两条仍未加 | 把"现在对"变成"以后不会错";顺手暴露第 4 条风险 | 小(一个测试文件,用现成扫描脚本改) | 新测试 + 现有套件 |
| 2 | **给共享层加"依赖规则测试"**:AST 扫描断言 `shared` 不得 eager import PySide6/OpenGL(现状成立),以及 `studio.scene3d` 不得 import `acquisition`;把 `force → orisys` 的现状登记为"已知例外"或改为惰性 —— *部分已完成*:`apps/studio/tests/test_studio_binding_purity.py` 与 `apps/autocal/tests/test_binding_purity.py` 已经强制"只允许 PySide6"(含无作用域枚举的检查,且用真 binding 内省而不是手写枚举名单);`studio.scene3d` 与 `force → orisys` 两条仍未加 | 把"现在对"变成"以后不会错";顺手暴露第 4 条风险 | 小(一个测试文件,用现成扫描脚本改) | 新测试 + 现有套件 |
| 3 | **消歧命名**:`scene3d/panel.py` → `scene3d/controls.py`;`ui/mesh3d_panel.py` → `ui/scene3d_host.py`;`scene3d/replay` 与 `record/playback` 在 docstring 里互相指路 | 新人少走 3 次错门 | 小(改名 + import 更新),但会触及 ui_check 的引用 | 全套 + `ui_check` |
| 4 | **把 `force → SDK` 改为惰性**(`calibration_io` 里改成函数内 import,或把 SDK 相关函数拆出去) | 力曲线的纯计算(history/filters/scale)可在无 SDK 环境测试 | 中(要区分哪些函数真的需要 SDK) | 现有力测试 + 无 SDK 的 import 检查 |
| 5 | **`ui_check` 拆模块**(按场景拆 `tools/ui_checks/*.py`,保留单一入口与退出码) | 最脆的资产变成可分工、可 diff 的几块 | 中(3401 行搬运,语义不变) | 检查项计数不变(587 项 0 失败) |
+4
View File
@@ -24,6 +24,8 @@
代理开始验证前说明“改动 → 所选测试 → 扩大理由”。定向测试通过后结束验证;没有新增改动、失败或未解决风险时,不追加全量。全量只在最终候选状态运行一次;之后仅复验新改动涉及的测试,除非新改动再次触及公共基础。
**提交前跑一次 `tools/gate.ps1`。** 定向测试用于开发中,门禁用于“这一版可以交给别人”的那一刻:它依次跑改动文件的 lint、studio 全量、shared 全量、`ui_check.py`,并要求 `tools/known_failures.txt` 为空、跳过数与收集数在 `tools/skip_budget.txt` 之内。可选 `pre-push` 钩子会调用它(安装方式见 [README](../README.md),不自动安装)。门禁平台是 **Windows**:测试渲染真实 Qt 控件,而 [测试修复与门禁计划](test-repair-plan.zh.md) 第 3 节的 11、13 号只在 Linux 上失败,Linux 的通过不等于同一结论。
不能通过跳过失败、删除断言或把必需测试标成可选来提速。测试缺依赖、收集为空或意外跳过必须报告。间歇性错误先保留证据,查明影响后只重跑受影响范围;不循环重跑全量碰运气。
## 拟提供的入口
@@ -64,6 +66,8 @@
| 3 | 接入代理执行规范,约 1 小时 | 仓库 AGENTS 链接执行指南,说明默认范围及停止条件;登记文档并运行文档门禁。不改工作区通用测试标准。 |
| 4 | 验证实际选择,1–2 小时 | 分别选择 Autocal 记录修复、Studio 局部界面、shared 录制契约三个场景;核对收集清单包含必要消费者,至少实际执行一个受影响组。 |
门禁平台:**Windows**。上表的定向验证可以在任何平台开发,但“提交前通过 `tools/gate.ps1`”这一条以 Windows 结果为准。
任务 2 依赖任务 1,任务 3 依赖入口可用,任务 4 最后验收。建议一名工程师顺序完成,总计约 5–8 小时;无需多个代理并行修改公共入口。
任务 1 后核对依赖覆盖,任务 2–3 后核对入口与规则一致。验收只运行调度工具测试、必要功能组和文档检查;不为证明调度工具可用而运行三个产品的全部测试。
+24 -19
View File
@@ -77,36 +77,41 @@
按 [代理交接约定](../../docs/platform/agent-handoff.zh.md) 维护;只保留当前状态和每轮一行摘要。
- task_id:test-repair;round:1;updated_at:2026-10-18 17:45 +08:00
- status:ready;owner:Claude(定义);next_agent:DeepSeek(执行)
- 目标与完成条件:本轮只做第 4 节阶段 0 和 1,验收以该两行为准;阶段 2 起留待下一轮
- 范围:`pyproject.toml`、`apps/studio/tests/**`、`shared/tests/**` 的标记与收集修复,新增
`apps/studio/tests/_studio_helpers.py`;排除 `apps/autocal/**`、产品源码、locale 与 `docs/` 以外的文档
- 停止条件:交接约定的默认条件;收集问题必须改 autocal 文件时停止
- 时间预算:按阶段分别计算,取第 4 节估时区间的上限(阶段 0 为 0.5 h,阶段 1 为 3 h),
不含等待用户或数据的时间;超出 50% 即触发停止条件
- 影响面:根 `pyproject.toml` 同时影响 autocal 测试树;记录受影响的 autocal 测试并在汇报中提醒用户,
不直接联系 autocal 任务(`.scratch/autocal-*` 中带 `.active` 的目录)
- 授权:用户 2026-10-18 17:17 要求制定计划交 DeepSeek 执行、17:40 确认启动;仅授权本地修改与测试,提交、推送、安装依赖仍需用户另行授权
- task_id:test-repair;round:2;updated_at:2026-10-18 18:45 +08:00
- status:ready(待验收);owner:Claude(定义);executed_by:DeepSeek
- 目标与完成条件:用户 18:36 把范围扩到全计划,阶段 0–6 全部执行,验收以第 4 节各行与本记录为准
- 范围:`pyproject.toml`、`apps/studio/**`(tests、tools、locales、docs)、`shared/tests/**`、新增
`tools/gate.ps1` 等门禁文件;`apps/autocal/**` 一律未改
- 停止条件:交接约定的默认条件;收集问题必须改 autocal 文件时停止(未触发)
- 时间预算:按第 4 节估时逐阶段累计;等待用户决定与数据的时间不计
- 影响面:根 `pyproject.toml` 的 `--strict-markers` 同时作用于 autocal 测试树;收集已核对(0 未知标记、
0 错误)
- 授权:用户 18:36 授权执行全计划并按阶段汇报;本轮未提交、未推送、未安装依赖
### 基准与输入
| 仓库/checkout | 分支、HEAD | 起始暂存/未暂存/未跟踪变化 | 本轮修改 |
|---|---|---|---|
| `D:\orisys_ws\orisys-app` | `main`、`e268a9d`(studio/shared 与 `85d0b39` 相同) | autocal 有其他任务的改动,不属本任务 | 待填 |
| `D:\orisys_ws\orisys-app` | `main`、`e268a9d`(执行期间他人提交到 `9a3886b`,均属 autocal 任务) | autocal 有其他任务的改动(已由其自行提交),不属本任务 | 23 项修好、门禁落地、录像入库;见下 |
- 环境:`D:\orisys_ws\orisys-app\.venv-build\Scripts\python.exe`
- 输入:不适用(阶段 2 的测试录像尚待用户提供)
- 环境:`D:\orisys_ws\orisys-app\.venv-build\Scripts\python.exe`(版本见 phase0 汇总)
- 输入:录像从 `.scratch/result-visible/` 找回(帧号 20…52,与测试期望一致),复制进
`apps/studio/tests/data/box_short_20260930/`(3.79 MB,不含 preroll);用户无需补录
### 执行结果
| 验收项与预期 | 实际命令及 run_id | 实际结果 | 证据路径 |
|---|---|---|---|
| 阶段 0:失败清单与第 3 节对上 | 待填 | 待填 | 待填 |
| 阶段 1:根目录收集错误为 0;`timing` 排除 2 项 | 待填 | 待填 | 待填 |
| 阶段 0:失败清单与第 3 节对上 | 两次全量 pytest + `ui_check.py` | 23 项逐项对上;另有 ui_check 重试竞态 | `.scratch/test-repair/phase0/` |
| 阶段 1:根目录收集 0 错误;`timing` 排除 | `python -m pytest --collect-only` | 112 文件 1754 项、0 错误;排除 3 项 | `phase1/` |
| 阶段 2:数据用例可运行 | 三个数据用例文件 | 12 / 11 / 30 项全绿 | `phase2/` |
| 阶段 3:3–10 号 | 定向用例 | 全绿;9、10 号按用户决定 | `phase3/items*.xml` |
| 阶段 4:门禁 | `tools/gate.ps1` | 当前状态退出码 0;改坏断言、删数据均非 0 | `.scratch/gate/gate-*` |
| 阶段 5:钩子与文档 | `git config core.hooksPath .githooks`(未安装) | README 与两份计划已改;文档门禁 clean | `scripts/doc_lint.py` |
### 验收与下一步
- 轮次摘要:(执行后填写)
- 验收者:Claude 或 GPT;决定:待验收
- 下一步:DeepSeek 执行阶段 0–1,交付 review
- 轮次摘要:阶段 0–6 完成;偏差(`timing` 三项、box 叠加画布、四处计划外过时断言)见
`.scratch/test-repair/final-report.md`
- 验收者:用户(或评审代理);决定:待验收
- 下一步:box 画布重建与计时确定性各开任务;等用户授权后再提交