Files
aetherbound-guild/tools/test_verify_visual_fidelity.py
T

83 lines
3.0 KiB
Python

#!/usr/bin/env python3
from __future__ import annotations
import importlib.util
import tempfile
import unittest
from pathlib import Path
from PIL import Image, ImageDraw
MODULE_PATH = Path(__file__).with_name("verify_visual_fidelity.py")
SPEC = importlib.util.spec_from_file_location("verify_visual_fidelity", MODULE_PATH)
assert SPEC is not None and SPEC.loader is not None
VERIFY = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(VERIFY)
class VisualFidelityTests(unittest.TestCase):
def _image(self, box: tuple[int, int, int, int] | None = None) -> Image.Image:
image = Image.new("RGB", (200, 100), "white")
if box is not None:
ImageDraw.Draw(image).rectangle(box, fill="black")
return image
def _contract(self) -> dict:
return {
"approved_master": {"aspect": 2.0},
"runtime_canvas": {"bounds": "auto_centered"},
"defaults": {
"analysis_width": 200,
"aspect_ratio_delta": 0.01,
"anchor_delta": 0.02,
"focal_scale_delta": 0.02,
"occupancy_delta": 0.05,
"static_region_mean_error": 0.01,
"dynamic_detection": {
"difference_threshold": 0.1,
"minimum_component_area_px": 4,
},
},
"regions": [
{
"id": "subject",
"mode": "runtime_replacement",
"search_bounds": [0.0, 0.0, 1.0, 1.0],
"runtime_bounds": [0.2, 0.2, 0.2, 0.4],
}
],
}
def _run(self, runtime_box: tuple[int, int, int, int]) -> dict:
with tempfile.TemporaryDirectory() as directory:
return VERIFY.run_verification(
self._image((40, 20, 80, 60)),
self._image(runtime_box),
self._image(),
self._contract(),
Path(directory),
Path("approved.png"),
Path("runtime.png"),
Path("static.png"),
)
def test_matching_rendered_dynamic_bounds_pass(self) -> None:
report = self._run((40, 20, 80, 60))
subject = report["checks"][1]
self.assertEqual("PASS", report["result"])
self.assertEqual([0.2, 0.2, 0.205, 0.41], subject["runtime_measurement"]["bounds"])
self.assertIn("declared_runtime_bounds_ignored", subject)
def test_copied_runtime_bounds_cannot_hide_shifted_pixels(self) -> None:
report = self._run((110, 30, 180, 80))
subject = report["checks"][1]
self.assertEqual("FAIL_VISUAL_FIDELITY", report["result"])
self.assertEqual([0.55, 0.3, 0.355, 0.51], subject["runtime_measurement"]["bounds"])
self.assertGreater(subject["anchor_delta"], subject["anchor_tolerance"])
self.assertGreater(subject["size_delta"], subject["size_tolerance"])
if __name__ == "__main__":
unittest.main()