supervision/tests/cv2/test_cv2.py

112 lines
2.6 KiB
Python

"""Tests for the private OpenCV facade."""
from __future__ import annotations
import importlib
import subprocess
import sys
import numpy as np
import pytest
from supervision import _cv2
try:
cv2 = importlib.import_module("cv2")
except (ImportError, OSError):
pytest.skip(
"OpenCV is required as the reference implementation for this test module",
allow_module_level=True,
)
REQUIRED_SYMBOLS = {
"VideoCapture",
"VideoWriter",
"VideoWriter_fourcc",
"addWeighted",
"approxPolyDP",
"blur",
"circle",
"connectedComponents",
"connectedComponentsWithStats",
"contourArea",
"convertScaleAbs",
"copyMakeBorder",
"cvtColor",
"drawContours",
"ellipse",
"fillPoly",
"find_contours",
"flip",
"getTextSize",
"imread",
"imwrite",
"intersectConvexConvex",
"line",
"mean",
"merge",
"polylines",
"putText",
"rectangle",
"resize",
"split",
}
@pytest.mark.parametrize(
"symbol",
[
pytest.param(symbol, id=symbol.lower().replace("_", "-"))
for symbol in sorted(REQUIRED_SYMBOLS)
],
)
def test_facade_exports_required_opencv_symbol(symbol: str) -> None:
"""Expose each OpenCV symbol used by production call sites."""
assert symbol in _cv2.__all__
assert hasattr(_cv2, symbol)
def test_facade_reports_opencv_backend() -> None:
"""Report OpenCV when the native backend is available."""
assert _cv2.BACKEND_NAME == "opencv"
def test_facade_routes_color_calls_to_opencv() -> None:
"""Route color conversion calls through the Supervision facade."""
image = np.array([[[10, 20, 30], [40, 50, 60]]], dtype=np.uint8)
np.testing.assert_array_equal(
_cv2.cvtColor(image, _cv2.COLOR_BGR2RGB),
cv2.cvtColor(image, cv2.COLOR_BGR2RGB),
)
def test_facade_routes_resize_calls_to_opencv() -> None:
"""Route resize calls through the Supervision facade."""
image = np.array([[[10, 20, 30], [40, 50, 60]]], dtype=np.uint8)
np.testing.assert_array_equal(
_cv2.resize(image, (4, 2), interpolation=_cv2.INTER_NEAREST),
cv2.resize(image, (4, 2), interpolation=cv2.INTER_NEAREST),
)
def test_facade_does_not_hide_a_breaking_opencv_import() -> None:
"""Raise when cv2 imports but no longer exposes a required symbol."""
code = """
import sys
import types
sys.modules["cv2"] = types.ModuleType("cv2")
from supervision import _cv2
"""
result = subprocess.run(
[sys.executable, "-c", code],
capture_output=True,
text=True,
)
assert result.returncode != 0
assert "cannot import name" in result.stderr