Files
orisys-app/docs/test-repair-plan.zh.md
ykcheungab fbf8c76bb5 为测试修复加入第 3 轮返工任务
验收 433b76e 时发现门禁不 lint 已提交改动、叠加底图失败范围过大且回退无测试,故定义返工项。文档门禁 clean。
2026-10-18 20:04:26 +08:00

11 KiB
Raw Permalink Blame History

Studio / shared 测试修复与门禁计划

状态:阶段 0–6 已交付(433b76e),返工见 第 3 轮返工。日期:2026-10-18。基线:orisys-app main 的 85d0b39。执行者:一个代理(DeepSeek),按顺序完成, 每个阶段结束时向用户汇报。本计划补充 分层测试执行计划,不替代它。

1. 为什么要做

在 85d0b39 上,studio 测试在 Windows 上有 23 项失败或错误(Linux 上 24 项),shared 有 2 项,没有人察觉。原因不是单个缺陷,而是流程本身:

问题 证据 后果
没有强制执行的门禁 仓库没有 CI 或 pre-commit;规则只写在 AGENTS 里 10-05 至 10-08 至少 6 个提交改了行为但没改测试(第 3 节逐项列出)
只跑定向测试,从不定期全量 分层计划写明"定向测试通过后结束验证" 其他分组里的测试悄悄变红,没有人发现
文档里的门禁命令无效 -m "not timing" 是文档写的门禁命令,但 timing 标记从未注册,也没有测试使用 已知不稳定的计时测试每次都失败,大家习惯无视红色
测试依赖未跟踪的数据 回放和裸视频测试读取 dist/OrisysStudio/outputs/recordings/…;10-14 重新打包后这份录像消失 换机器或重新打包,11 项测试报错,4 项失败
从仓库根目录无法运行 studio 测试 from tests.conftest import … 在根目录找不到 tests;studio 与 autocal 的 test_binding_purity.py 同名冲突 文档写的"根目录 pytest"跑不起来,每个人自己找运行方式
ui_check.py 不在任何门禁里 它的模拟 worker 从 10-08 起与 start() 签名不符,脚本中途崩溃,并连带约 15 项冒烟测试失败(已在 85d0b39 修复) 3700 行的检查静默失效
跳过的测试无人计数 studio 有 35 项跳过,原因没有汇总 环境坏了也可能显示为通过

结论:分层选择测试的思路是对的,但缺少两样东西——一个任何人都绕不过去的全量门禁,以及一份必须为空的已知失败清单。

2. 规则(执行者必须遵守)

  • 遵守 D:\orisys_ws\AGENTS.md:scratch 放在 orisys-app/.scratch/test-repair/,带 .active 标记;pytest 使用 --basetemp=<scratch>/pytest-<run> 和 -p no:cacheprovider;改动不暂存、不提交;向用户汇报用中文。
  • 解释器固定为 D:\orisys_ws\orisys-app\.venv-build\Scripts\python.exe,用 Windows PowerShell 5.1 语法。
  • 不得通过删除断言、放宽断言、加 skip 或 xfail 让测试变绿。改测试只有一个理由:测试与已确认的产品行为不一致,并且要写明是哪个提交确认了该行为。
  • 每修一项,记录它在修复前失败、修复后通过的证据(命令和输出摘要)。
  • apps/autocal/ 目前有另一个任务在改。不要编辑 autocal 的源码或测试;如果第 4 节的收集问题必须改 autocal 文件,停下来问用户。
  • 遇到第 3 节标为"需决定"的项,先准备好证据和建议,再停下来问用户,不要自己决定。

3. 逐项诊断(执行者先复核,再动手)

以下诊断来自 2026-10-18 在 Linux 离屏环境与 Windows 上的两次运行;"引入提交"由 git log -S 查得。执行者须用 git show <提交> 确认诊断后再修。

# 测试 现象 判断 处理
1 test_bare_video_analysis.py 全部 11 项 找不到 dist/…/20260930T015028Z_session0002_…/raw_0001.mp4 测试数据缺失 见第 4 节阶段 2
2 test_replay_wiring.py 4 项(_open 报 the recording did not open;declined prompt 报 FileNotFoundError) 同一份录像缺失;_copy_recording 静默跳过缺失文件,而模块级的 skip 只在部分路径生效 测试数据缺失,加上 fixture 行为不一致 阶段 2;同时让缺数据时一律明确失败
3 test_replay_analysis.py::test_a_stitch_grid_is_not_painted_onto_the_camera_frame 测试桩 _Reader 没有 provenance 属性 测试过时(replay_analysis.py:245,401 读取 reader.provenance,引入于 829d2c1,10-06) 给测试桩补上 provenance,取值仿照真实 reader,不得改产品代码
4 test_ui_smoke.py::test_old_result_depth_is_not_sent_to_the_new_sensor_scene 调用已删除的 _show_analysis_frame 测试过时(cf49b08、28e955a 改为 show_analysis_packet) 改用公共入口,保留原断言意图:旧结果的深度不得送进新传感器的场景
5 test_scene3d_view.py::test_the_replay_view_shows_the_pane_and_says_where_the_field_comes_from 断言文案含"重算",现在是"分析结果:非录制时的测量值" 测试过时(c0a10e6 改了文案) 改为对比 locale 键 source_recompute,不再硬编码字面词
6 test_ui_elements.py::test_every_declared_condition_is_used_and_reaches_a_window liveCalibrationCombo、sensorProfileScroll 未登记 登记表过时(3d2fb0c 新增控件) 用 apps/studio/tools/ui_elements_dump.py 生成条目,补进 apps/studio/docs/ui-elements.json,逐条写明用途
7 test_ui_smoke.py::test_run_tooltip_explains_disabled_reason 期望选了视频文件后「运行」可用 测试过时:实时视图不再用视频运行(test_live_run_refuses_a_video_source 断言的正是相反行为) 改为断言:视频源时按钮禁用、提示文字和顶栏 run_hint 都是 toolbar.run_video_in_replay
8 test_ui_smoke.py::test_the_sensor_summary_opens_the_dialog 没有导出系数时「应用到设备」仍可用 很可能是测试过时(3d2fb0c 让该按钮应用对话框里选中的实时标定) 读 sensor_dialog.py:324 一带确认行为后改断言;若该按钮在什么都没选时也可用并会出错,按产品缺陷处理
9 test_pause_controls.py::test_the_transport_says_which_way_it_goes 暂停提示不再提到录制会留空档 需决定:f2bbab7(10-08)为缩短文案删掉了这句,但修复计划 A 要求提示写明空档 建议恢复一句短的"录制会留空档",测试保持不变;须用户确认
10 test_ui_smoke.py::test_the_replay_view_is_the_live_view_with_a_video_source,以及 ui_check 的同名检查 回放与实时的分栏宽度不同(589/825 对 643/771) 需决定:可能是 321e52f(10-06,改善回放布局)有意改变,也可能是回归 用 git bisect 在测试上定位引入提交,向用户说明那次改动的意图,再决定改测试还是改代码
11 test_ui_smoke.py::test_the_rail_puts_result_identity_before_a_long_video_name 仅 Linux 失败(字体宽度不同),Windows 通过 环境差异 不改;在门禁说明里写明门禁平台是 Windows
12 shared/tests/test_worker_frame_rate.py 2 项 "30 fps 设备只消费到 21 fps",取决于机器负载 计时测试,本身不稳定 注册并标记为 timing,移出合入门禁;另开任务把它改成确定性测试
13 shared/tests/test_scene3d_protect.py::test_the_release_gate_fails_an_unsigned_package 仅 Linux 失败 环境差异 不改;记录在案

4. 实施阶段

阶段 内容 验收 估时
0 基线 记录 HEAD、解释器、PySide6 与 pyqtgraph 版本;分别在 apps/studio、shared 下跑全量(-m "not timing"),并运行 ui_check.py,产出 JUnit XML scratch 下有失败清单,与第 3 节逐项对上;对不上的项先报告用户 0.5 h
1 让门禁能跑 在根 pyproject.toml 注册 timing 标记,并加 --strict-markers;标记第 3 节 12 号的两项;解决根目录收集问题(建议:把 studio 测试从 tests.conftest 导入的辅助函数移到 apps/studio/tests/_studio_helpers.py,并在 studio 的 conftest 里把该目录加入 sys.path;同名测试文件用 --import-mode=importlib 或改名解决,不改 autocal 文件) 在仓库根目录执行 python -m pytest --collect-only -q 时收集错误为 0;-m "not timing" 确实排除了 2 项 2–3 h
2 测试数据 第 3 节 1、2 号:新建 apps/studio/tests/data/,放一段真实的 box 短录像(raw_0001.mp4、frames.csv、forces.csv、events.csv、session.json),约 30 帧;所有测试改为从这里读取;只需要回放接线的测试,优先用 ExperimentRecorder(shared/.../record/experiment.py)在 fixture 里生成合成录像,写法参考 ui_snapshot.py --scene replay;数据缺失时一律明确失败,不跳过 两个文件的全部用例在干净的检出上可运行;dist/ 不再出现在任何测试路径中(grep -r "dist" apps/studio/tests 只剩注释) 2–3 h,另需用户录一段
3 逐项修复 第 3 节 3–8 号直接修;9、10 号先问用户再修 每项记录修前失败、修后通过;断言数量不减少(列出每个改动测试的断言前后对比) 3–4 h
4 门禁脚本 新增 tools/gate.ps1:依次运行 tools/lint_gate.py(改动文件)、studio 全量、shared 全量、ui_check.py;全部输出写进 scratch 并汇总为一页;读取 tools/known_failures.txt,该文件必须为空,有内容就让门禁失败;记录跳过数,超过 tools/skip_budget.txt 中的上限就失败;收集数低于下限也失败(防止整个模块被静默跳过) 在当前状态运行 gate.ps1 退出码为 0;故意改坏一个断言后退出码非 0;故意删掉测试数据后退出码非 0 3–4 h
5 接入流程 在 orisys-app 提供可选的 pre-push 钩子(调用 gate.ps1,安装方式写进 README,不自动安装);修订 test-execution-plan.zh.md:定向测试用于开发中,提交前跑一次 gate.ps1;第 4 节表格里加"门禁平台:Windows" 文档门禁通过;README 写有安装钩子的一条命令 1 h
6 收尾 以最终状态跑一次 gate.ps1;写 commit-message.txt;用中文汇报 汇报区分:已修、需用户决定、移出门禁的(含理由)、仍未解决的 0.5 h

阶段 1 必须先于其他阶段完成;阶段 2 和 3 可以交错进行;阶段 4 依赖前三个阶段全部变绿。总计约 12–16 小时,外加用户录制测试数据的时间。

5. 需要用户先决定的事

  1. 测试录像放在哪里。 建议放进 git(apps/studio/tests/data/,控制在 5 MB 以内);如果不想让仓库变大,就改用环境变量 ORISYS_TEST_DATA 指向 NAS 上的目录,但缺失时测试必须失败,不能跳过。还需要用户用 box 传感器录一段约 1 秒的短录像。
  2. 第 3 节 9 号:暂停提示是否恢复"录制会留空档"。
  3. 第 3 节 10 号:回放与实时布局不一致,属于有意改动还是回归(执行者 bisect 之后再问)。
  4. 以后是否搭 Gitea runner(Windows 自托管)自动跑 gate.ps1。本计划只做到本地钩子;runner 另开任务。

6. 不在本计划内

计时测试改为确定性测试;GL 真机冒烟测试;autocal 测试树的问题;测试目录重排。这些都在门禁稳定之后另行安排。

交接记录

自第 3 轮起移至 第 3 轮返工,本文件不再维护任务状态。第 2 轮的完整记录见 433b76e 中的本文件。