修复 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
+8 -43
View File
@@ -51,6 +51,14 @@ _TOOLS_DIR = Path(__file__).resolve().parents[1] / "tools"
if _TOOLS_DIR.is_dir() and str(_TOOLS_DIR) not in sys.path:
sys.path.insert(0, str(_TOOLS_DIR))
# The tests' own directory, so ``_studio_helpers`` is importable however pytest was
# started. Relying on pytest to insert it works only under the default import mode and
# only for the directory a test file happens to sit in; naming it here is what lets the
# suite be collected from the repository root (see ``docs/test-repair-plan.zh.md`` §4).
_TESTS_DIR = Path(__file__).resolve().parent
if str(_TESTS_DIR) not in sys.path:
sys.path.insert(0, str(_TESTS_DIR))
@pytest.fixture(scope="session")
def qt_app():
@@ -117,49 +125,6 @@ def decline_video_prompt(monkeypatch):
)
def visible_descendants(widget):
"""Yield every visible descendant widget of ``widget``."""
for child in widget.findChildren(object):
if not hasattr(child, "isVisible") or not hasattr(child, "geometry"):
continue
if child.isVisible():
yield child
def show_window(window, size):
"""Show a window at ``size`` and flush pending Qt events."""
from PySide6.QtWidgets import QApplication
window.resize(*size)
window.show()
QApplication.processEvents()
return window
def running_window(make_window):
"""Return a running window backed by a controllable test worker."""
import ui_check
window = show_window(
make_window(sensor_type="box", source_mode="camera"),
(1440, 880),
)
stuck = ui_check._StuckWorker()
window._ensure_workers = lambda: None
window._box_worker = stuck
window._finger_worker = stuck
window._start_run()
window._run_timer.stop()
window._set_phase("running")
return window, stuck
def finish_run(window, stuck):
"""Stop a test run and release its controllable worker."""
window._stop_run(reason="user_stop")
stuck.release()
_RECORD_SCRATCH = (
Path(__file__).resolve().parents[1] / "outputs" / "_test_record"
)