import runpy import sys import types import unittest from pathlib import Path from unittest.mock import Mock, patch import cv2 import numpy as np class ShowcaseDrawingTests(unittest.TestCase): def test_webcam_resolution_changes_preserve_drawing_without_add_error(self): # The runner's waiting frame is 640x480; browser webcam frames are 480x360. shapes = [(480, 640, 3), (480, 640, 3), (360, 480, 3), (480, 640, 3), (640, 480, 3)] camera = Mock() camera.read.side_effect = [(True, np.zeros(shape, dtype=np.uint8)) for shape in shapes] + [(False, None)] landmarks = [types.SimpleNamespace(x=0.25, y=0.7) for _ in range(21)] landmarks[8].y = 0.3 landmarks[12].y = 0.8 detector = Mock() detector.detect.side_effect = [ types.SimpleNamespace(hand_landmarks=[landmarks]), *[types.SimpleNamespace(hand_landmarks=[]) for _ in shapes[1:]], ] mp = types.ModuleType("mediapipe") tasks = types.ModuleType("mediapipe.tasks") python = types.ModuleType("mediapipe.tasks.python") vision = types.ModuleType("mediapipe.tasks.python.vision") mp.Image = Mock() mp.ImageFormat = types.SimpleNamespace(SRGB=1) python.BaseOptions = Mock() vision.HandLandmarkerOptions = Mock() vision.HandLandmarker = types.SimpleNamespace(create_from_options=Mock(return_value=detector)) mp.tasks, tasks.python, python.vision = tasks, python, vision modules = {module.__name__: module for module in (mp, tasks, python, vision)} displayed = [] script = Path(__file__).resolve().parents[1] / "projects/DEMO/展示用學生/03_手指空中畫畫/draw_game_student.py" with patch.dict(sys.modules, modules), \ patch.object(cv2, "VideoCapture", return_value=camera), \ patch.object(cv2, "imshow", side_effect=lambda title, frame: displayed.append(frame.copy())), \ patch.object(cv2, "waitKey", return_value=-1), \ patch.object(cv2, "destroyAllWindows"): runpy.run_path(str(script), run_name="__main__") self.assertEqual([frame.shape for frame in displayed], shapes) self.assertTrue(all(frame.dtype == np.uint8 for frame in displayed)) self.assertTrue(all(np.any(frame) for frame in displayed), "Existing drawing must survive size changes") camera.release.assert_called_once() if __name__ == "__main__": unittest.main()