simvx.graphics.testing¶
Visual testing utilities — pixel assertions for headless Vulkan rendering.
All functions operate on numpy arrays (H, W, 4) uint8 in RGBA order, as returned by Engine.capture_frame(). No external dependencies beyond numpy.
Usage::
from simvx.graphics.testing import assert_pixel, assert_not_blank
pixels = app.run_headless(scene, frames=5, capture_frames=[4])[0]
assert_not_blank(pixels)
assert_pixel(pixels, 160, 120, (255, 0, 0, 255), tolerance=10)
Module Contents¶
Classes¶
Collects screenshots during a test run and produces CI-friendly output. |
|
Manages baseline screenshots and compares rendered frames against them. |
Functions¶
Assert the pixel at (x, y) matches expected_rgba within tolerance per channel. |
|
Return the fraction of pixels matching color within tolerance. |
|
Assert approximately expected_ratio of pixels match color. |
|
Assert all pixels in rect (x, y, w, h) match expected_color. |
|
Assert no pixel matches color. |
|
Assert the image is not a single solid color. |
|
Save RGBA uint8 pixels (H, W, 4) as a PNG file. Pure Python, no Pillow. |
|
Save RGBA pixels to file. Auto-detects format from extension (.png or .ppm). |
|
Save a visual diff image highlighting differences (5x amplified). |
Data¶
API¶
- simvx.graphics.testing.__all__¶
[‘assert_pixel’, ‘assert_color_ratio’, ‘assert_region_color’, ‘assert_no_color’, ‘assert_not_blank’,…
- simvx.graphics.testing.assert_pixel(pixels: numpy.ndarray, x: int, y: int, expected_rgba: tuple[int, ...], tolerance: int = 2) None¶
Assert the pixel at (x, y) matches expected_rgba within tolerance per channel.
- simvx.graphics.testing.color_ratio(pixels: numpy.ndarray, color: tuple[int, ...], tolerance: int = 10) float¶
Return the fraction of pixels matching color within tolerance.
- simvx.graphics.testing.assert_color_ratio(pixels: numpy.ndarray, color: tuple[int, ...], expected_ratio: float, tolerance: float = 0.02, color_tolerance: int = 10) None¶
Assert approximately expected_ratio of pixels match color.
- simvx.graphics.testing.assert_region_color(pixels: numpy.ndarray, rect: tuple[int, int, int, int], expected_color: tuple[int, ...], tolerance: int = 5) None¶
Assert all pixels in rect (x, y, w, h) match expected_color.
- simvx.graphics.testing.assert_no_color(pixels: numpy.ndarray, color: tuple[int, ...], tolerance: int = 5) None¶
Assert no pixel matches color.
- simvx.graphics.testing.assert_not_blank(pixels: numpy.ndarray) None¶
Assert the image is not a single solid color.
- simvx.graphics.testing.save_png(path: str | pathlib.Path, pixels: numpy.ndarray) None¶
Save RGBA uint8 pixels (H, W, 4) as a PNG file. Pure Python, no Pillow.
- simvx.graphics.testing.save_image(path: str | pathlib.Path, pixels: numpy.ndarray) None¶
Save RGBA pixels to file. Auto-detects format from extension (.png or .ppm).
- simvx.graphics.testing.save_diff_image(path: str | pathlib.Path, actual: numpy.ndarray, expected: numpy.ndarray) None¶
Save a visual diff image highlighting differences (5x amplified).
- class simvx.graphics.testing.ScreenshotReport(output_dir: pathlib.Path)¶
Collects screenshots during a test run and produces CI-friendly output.
Initialization
- capture(pixels: numpy.ndarray, label: str) pathlib.Path¶
Save frame as PNG, return path.
- capture_with_diff(actual: numpy.ndarray, expected: numpy.ndarray, label: str) pathlib.Path¶
Save actual + expected + diff as side-by-side composite PNG.
- add_description(text: str) None¶
Attach a text description (e.g., from scene_describe()).
- finalize(test_name: str = '', status: str = 'passed') pathlib.Path¶
Write report.json and report.html to output_dir. Return path to JSON.
- class simvx.graphics.testing.VisualRegression(baseline_dir: pathlib.Path)¶
Manages baseline screenshots and compares rendered frames against them.
On first run (no baseline exists), saves the current frame as the baseline and passes. On subsequent runs, compares against baseline and fails if pixels differ beyond threshold. On failure, saves actual frame and diff image alongside baseline for inspection.
Usage::
def test_red_cube(capture, regression): frames = capture(RedCubeScene(), frames=3, capture_frames=[2]) regression.assert_matches(frames[0], "red_cube")Initialization
- assert_matches(pixels: numpy.ndarray, name: str, threshold: float = 0.001) None¶
Compare pixels against stored baseline.
- update_baseline(pixels: numpy.ndarray, name: str) None¶
Force-overwrite baseline (for intentional visual changes).
- static pixel_diff_ratio(a: numpy.ndarray, b: numpy.ndarray, tolerance: int = 2) float¶
Fraction of pixels that differ beyond tolerance per channel.