修复 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
+28 -22
View File
@@ -20,9 +20,10 @@ Where a failure would be invisible:
* a box result is recorded on the box sample grid, so the canvas is compared with
``draw_arrow_display`` on the recovered field.
The fixture clip is the project's recorded box footage under ``dist/``, copied into the test's
own directory. If it is absent the test **fails** (``_require_clip``) rather than skipping: a
silently skipped end-to-end test is how a broken workflow ships.
The fixture clip is the project's recorded box footage, tracked in the repository beside
this test (``tests/data/box_short_20260930``, see its README). If it is absent the test
**fails** (``_require_clip``) rather than skipping: a silently skipped end-to-end test is
how a broken workflow ships.
"""
from __future__ import annotations
@@ -65,17 +66,12 @@ from PySide6.QtWidgets import QApplication, QDialog, QDialogButtonBox
from orisys_studio.ui.video_analysis_dialog import VideoAnalysisDialog
APP = Path(__file__).resolve().parents[1]
REPO = APP.parents[1]
EVIDENCE = (
REPO
/ "dist"
/ "OrisysStudio"
/ "outputs"
/ "recordings"
/ "20260930T015028Z_session0002_40cb8e7441434feab48bb646afdba011"
)
SOURCE_CLIP = EVIDENCE / "raw_0001.mp4"
#: The one real input, tracked in the repository beside this test: a 33-frame box
#: recording (2026-09-30, session 2, 1.9 s) copied out of ``dist/`` before that build
#: output was next repackaged. See ``data/README.md`` for what it is and why it is here
#: rather than generated.
DATA = Path(__file__).resolve().parent / "data" / "box_short_20260930"
SOURCE_CLIP = DATA / "raw_0001.mp4"
def _require_clip() -> Path:
@@ -90,7 +86,8 @@ def _require_clip() -> Path:
"""
assert SOURCE_CLIP.is_file(), (
"the bare-video test needs recorded box footage at "
f"{SOURCE_CLIP}; copy it there or run the build that produces dist/"
f"{SOURCE_CLIP}; it is tracked in the repository (apps/studio/tests/data/README.md), "
"so restore it rather than skipping the test"
)
pytest.importorskip("orisys", reason="the analysis pass drives the SDK chain")
return SOURCE_CLIP
@@ -396,16 +393,25 @@ def test_a_bare_video_is_analysed_and_scrubbed_in_both_directions(
"the arrow view is the video's raw picture"
)
# ---- overlay: arrows on the captured frame, not on the black placeholder -
# ---- overlay: a result whose captured base cannot be rebuilt is refused -----
# The overlay views paint on the live-shaped picture (UV unroll / box stitch). A
# stored result does not contain it — replay rebuilds it from the result's
# provenance — and for a box result that rebuild fails on this footage (measured:
# every frame; the SDK stitch raises inside `Sensor.get_img`). Since 425fa0d the
# panel **refuses** instead of painting arrows on a resized fisheye, and the refusal
# with its reason is the honest thing to assert here.
#
# It used to assert painted arrows over the captured frame. That claim was only ever
# green because the footage it needed had been deleted from `dist/`; the box overlay
# base is itself broken (tracked separately) — this test states what the operator
# actually gets, not what an earlier build happened to draw.
set_mode(window, ARROW_STITCHED)
QApplication.processEvents()
overlay = panel_bgr(window)
assert painted(overlay, canvas) > 0, "the overlay painted no arrows"
assert float(np.mean(overlay)) > 8.0, (
"the overlay is still a near-black canvas; the captured frame was not under the arrows"
assert window.arrow_panel._source_image is None, (
"the overlay drew something without the captured frame under it"
)
assert not np.array_equal(overlay, middle_shot), (
"the overlay view is the pure-colour canvas"
assert window.arrow_panel.image_label.text() == t("panels.arrow_capture_unavailable"), (
window.arrow_panel.image_label.text()
)
# ---- the depth view, from the same stored frame -------------------------