stall-watcher/tests/test_detector.py
2026-09-07 16:23:36 +02:00

67 lines
2.3 KiB
Python

import numpy as np
from src.detector import MotionDetector
from src.models import DetectionConfig, DetectionState
def detector() -> MotionDetector:
return MotionDetector(DetectionConfig(movement_threshold=2.0, alert_after=3.0, capture_interval=1.0), downscale_step=1)
def test_identical_images_score_near_zero() -> None:
image = np.zeros((10, 10, 3), dtype=np.uint8)
assert detector().calculate_motion_score(image, image) == 0.0
def test_different_images_score_is_higher() -> None:
first = np.zeros((10, 10, 3), dtype=np.uint8)
second = np.full((10, 10, 3), 255, dtype=np.uint8)
assert detector().calculate_motion_score(first, second) > 90.0
def test_still_time_accumulates_below_threshold() -> None:
det = detector()
image = np.zeros((10, 10, 3), dtype=np.uint8)
det.update(image, 1.0)
status = det.update(image, 1.0)
assert status.state == DetectionState.STILL_WAITING
assert status.still_time == 1.0
status = det.update(image, 1.0)
assert status.still_time == 2.0
def test_still_time_resets_when_movement_returns() -> None:
det = detector()
still = np.zeros((10, 10, 3), dtype=np.uint8)
moved = np.full((10, 10, 3), 255, dtype=np.uint8)
det.update(still, 1.0)
det.update(still, 1.0)
status = det.update(moved, 1.0)
assert status.state == DetectionState.MOVING
assert status.still_time == 0.0
def test_only_one_alert_during_one_still_period() -> None:
det = detector()
image = np.zeros((10, 10, 3), dtype=np.uint8)
det.update(image, 1.0)
assert not det.update(image, 1.0).should_alert
assert not det.update(image, 1.0).should_alert
assert det.update(image, 1.0).should_alert
assert not det.update(image, 1.0).should_alert
assert not det.update(image, 1.0).should_alert
assert det.state == DetectionState.ALERTED
def test_alert_rearms_after_movement_resumes() -> None:
det = detector()
still = np.zeros((10, 10, 3), dtype=np.uint8)
moved = np.full((10, 10, 3), 255, dtype=np.uint8)
det.update(still, 1.0)
det.update(still, 1.0)
det.update(still, 1.0)
assert det.update(still, 1.0).should_alert
assert det.update(moved, 1.0).state == DetectionState.MOVING
det.update(moved, 1.0)
det.update(moved, 1.0)
assert det.update(moved, 1.0).should_alert