feat: added reference utils to compare renderings of widgets
@ -145,7 +145,7 @@ tests:
|
||||
coverage_format: cobertura
|
||||
path: coverage.xml
|
||||
paths:
|
||||
- tests/unit_tests/reference_failures/
|
||||
- tests/reference_failures/
|
||||
when: always
|
||||
|
||||
test-matrix:
|
||||
|
92
bec_widgets/utils/reference_utils.py
Normal file
@ -0,0 +1,92 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
from PIL import Image, ImageChops
|
||||
from qtpy.QtGui import QPixmap
|
||||
|
||||
import bec_widgets
|
||||
|
||||
REFERENCE_DIR = os.path.join(
|
||||
os.path.dirname(os.path.dirname(bec_widgets.__file__)), "tests/references"
|
||||
)
|
||||
REFERENCE_DIR_FAILURES = os.path.join(
|
||||
os.path.dirname(os.path.dirname(bec_widgets.__file__)), "tests/reference_failures"
|
||||
)
|
||||
|
||||
|
||||
def compare_images(image1_path: str, reference_image_path: str):
|
||||
"""
|
||||
Load two images and compare them pixel by pixel
|
||||
|
||||
Args:
|
||||
image1_path(str): The path to the first image
|
||||
reference_image_path(str): The path to the reference image
|
||||
|
||||
Raises:
|
||||
ValueError: If the images are different
|
||||
"""
|
||||
image1 = Image.open(image1_path)
|
||||
image2 = Image.open(reference_image_path)
|
||||
if image1.size != image2.size:
|
||||
raise ValueError("Image size has changed")
|
||||
diff = ImageChops.difference(image1, image2)
|
||||
if diff.getbbox():
|
||||
# copy image1 to the reference directory to upload as artifact
|
||||
os.makedirs(REFERENCE_DIR_FAILURES, exist_ok=True)
|
||||
image_name = os.path.join(REFERENCE_DIR_FAILURES, os.path.basename(image1_path))
|
||||
image1.save(image_name)
|
||||
print(f"Image saved to {image_name}")
|
||||
|
||||
raise ValueError("Images are different")
|
||||
|
||||
|
||||
def snap_and_compare(widget: any, output_directory: str, suffix: str = ""):
|
||||
"""
|
||||
Save a rendering of a widget and compare it to a reference image
|
||||
|
||||
Args:
|
||||
widget(any): The widget to render
|
||||
output_directory(str): The directory to save the image to
|
||||
suffix(str): A suffix to append to the image name
|
||||
|
||||
Raises:
|
||||
ValueError: If the images are different
|
||||
|
||||
Examples:
|
||||
snap_and_compare(widget, tmpdir, suffix="started")
|
||||
|
||||
"""
|
||||
|
||||
if not isinstance(output_directory, str):
|
||||
output_directory = str(output_directory)
|
||||
|
||||
os_suffix = sys.platform
|
||||
|
||||
name = (
|
||||
f"{widget.__class__.__name__}_{suffix}_{os_suffix}.png"
|
||||
if suffix
|
||||
else f"{widget.__class__.__name__}_{os_suffix}.png"
|
||||
)
|
||||
|
||||
# Save the widget to a pixmap
|
||||
test_image_path = os.path.join(output_directory, name)
|
||||
pixmap = QPixmap(widget.size())
|
||||
widget.render(pixmap)
|
||||
pixmap.save(test_image_path)
|
||||
|
||||
try:
|
||||
reference_path = os.path.join(REFERENCE_DIR, f"{widget.__class__.__name__}")
|
||||
reference_image_path = os.path.join(reference_path, name)
|
||||
|
||||
if not os.path.exists(reference_image_path):
|
||||
raise ValueError(f"Reference image not found: {reference_image_path}")
|
||||
|
||||
compare_images(test_image_path, reference_image_path)
|
||||
|
||||
except ValueError:
|
||||
image = Image.open(test_image_path)
|
||||
os.makedirs(REFERENCE_DIR_FAILURES, exist_ok=True)
|
||||
image_name = os.path.join(REFERENCE_DIR_FAILURES, name)
|
||||
image.save(image_name)
|
||||
print(f"Image saved to {image_name}")
|
||||
raise
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@ -1,11 +1,7 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
import qdarktheme
|
||||
from PIL import Image, ImageChops
|
||||
from qtpy.QtGui import QPixmap
|
||||
|
||||
from bec_widgets.utils.reference_utils import snap_and_compare
|
||||
from bec_widgets.widgets.spinner.spinner import SpinnerWidget
|
||||
|
||||
|
||||
@ -18,75 +14,17 @@ def spinner_widget(qtbot):
|
||||
yield spinner
|
||||
|
||||
|
||||
def save_pixmap(widget, filename):
|
||||
pixmap = QPixmap(widget.size())
|
||||
widget.render(pixmap)
|
||||
pixmap.save(str(filename))
|
||||
return pixmap
|
||||
|
||||
|
||||
def compare_images(image1_path: str, reference_image_path: str):
|
||||
image1 = Image.open(image1_path)
|
||||
image2 = Image.open(reference_image_path)
|
||||
if image1.size != image2.size:
|
||||
raise ValueError("Image size has changed")
|
||||
diff = ImageChops.difference(image1, image2)
|
||||
if diff.getbbox():
|
||||
# copy image1 to the reference directory to upload as artifact
|
||||
output_dir = os.path.join(os.path.dirname(__file__), "reference_failures")
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
image_name = os.path.join(output_dir, os.path.basename(image1_path))
|
||||
image1.save(image_name)
|
||||
print(f"Image saved to {image_name}")
|
||||
|
||||
raise ValueError("Images are different")
|
||||
|
||||
|
||||
def test_spinner_widget_paint_event(spinner_widget, qtbot):
|
||||
spinner_widget.paintEvent(None)
|
||||
|
||||
|
||||
def snap_and_compare(widget, tmpdir, suffix=""):
|
||||
os_suffix = sys.platform
|
||||
|
||||
name = (
|
||||
f"{widget.__class__.__name__}_{suffix}_{os_suffix}.png"
|
||||
if suffix
|
||||
else f"{widget.__class__.__name__}_{os_suffix}.png"
|
||||
)
|
||||
|
||||
# Save the widget to a pixmap
|
||||
test_image_path = str(tmpdir / name)
|
||||
pixmap = QPixmap(widget.size())
|
||||
widget.render(pixmap)
|
||||
pixmap.save(test_image_path)
|
||||
|
||||
try:
|
||||
references_path = os.path.join(os.path.dirname(__file__), "references")
|
||||
reference_image_path = os.path.join(references_path, name)
|
||||
|
||||
if not os.path.exists(reference_image_path):
|
||||
raise ValueError(f"Reference image not found: {reference_image_path}")
|
||||
|
||||
compare_images(test_image_path, reference_image_path)
|
||||
|
||||
except ValueError:
|
||||
image = Image.open(test_image_path)
|
||||
output_dir = os.path.join(os.path.dirname(__file__), "reference_failures")
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
image_name = os.path.join(output_dir, name)
|
||||
image.save(image_name)
|
||||
print(f"Image saved to {image_name}")
|
||||
raise
|
||||
|
||||
|
||||
def test_spinner_widget_rendered(spinner_widget, qtbot, tmpdir):
|
||||
spinner_widget.update()
|
||||
qtbot.wait(200)
|
||||
snap_and_compare(spinner_widget, tmpdir, suffix="")
|
||||
snap_and_compare(spinner_widget, str(tmpdir), suffix="")
|
||||
|
||||
spinner_widget._started = True
|
||||
spinner_widget.update()
|
||||
qtbot.wait(200)
|
||||
|
||||
snap_and_compare(spinner_widget, tmpdir, suffix="started")
|
||||
snap_and_compare(spinner_widget, str(tmpdir), suffix="started")
|
||||
|