(test) add python script to compare goldens
This commit is contained in:
6
.github/workflows/dart.yml
vendored
6
.github/workflows/dart.yml
vendored
@@ -37,12 +37,14 @@ jobs:
|
|||||||
- name: Download golden images
|
- name: Download golden images
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: golden-images-f0cf20d904f67e03c7ae247d18287b7f8a053cd2
|
name: golden-images-${{ github.sha }}
|
||||||
path: ./golden-downloads
|
path: ./thermion_dart/test/golden-downloads
|
||||||
- name: Install Python dependencies
|
- name: Install Python dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install Pillow numpy
|
pip install Pillow numpy
|
||||||
|
- name: Compare golden images
|
||||||
|
run: cd thermion_dart/test && python compare_goldens.py
|
||||||
- name: Upload logs
|
- name: Upload logs
|
||||||
if: failure() || steps.build.outcome == 'failure'
|
if: failure() || steps.build.outcome == 'failure'
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
|
|||||||
129
thermion_dart/test/compare_goldens.py
Normal file
129
thermion_dart/test/compare_goldens.py
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Compare PNG files between golden reference images and test output images.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
from PIL import Image, ImageChops
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
def calculate_image_difference(img1_path, img2_path):
|
||||||
|
"""
|
||||||
|
Calculate the difference between two images.
|
||||||
|
Returns a tuple of (mean_squared_error, max_difference, are_identical)
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
with Image.open(img1_path) as img1, Image.open(img2_path) as img2:
|
||||||
|
# Convert to same mode if different
|
||||||
|
if img1.mode != img2.mode:
|
||||||
|
img1 = img1.convert('RGBA')
|
||||||
|
img2 = img2.convert('RGBA')
|
||||||
|
|
||||||
|
# Check if dimensions match
|
||||||
|
if img1.size != img2.size:
|
||||||
|
print(f"Size mismatch: {img1_path} {img1.size} vs {img2_path} {img2.size}")
|
||||||
|
return None, None, False
|
||||||
|
|
||||||
|
# Calculate difference
|
||||||
|
diff = ImageChops.difference(img1, img2)
|
||||||
|
|
||||||
|
# Convert to numpy for calculations
|
||||||
|
diff_array = np.array(diff)
|
||||||
|
|
||||||
|
# Calculate metrics
|
||||||
|
mse = np.mean(diff_array ** 2)
|
||||||
|
max_diff = np.max(diff_array)
|
||||||
|
are_identical = mse == 0
|
||||||
|
|
||||||
|
return mse, max_diff, are_identical
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error comparing {img1_path} and {img2_path}: {e}")
|
||||||
|
return None, None, False
|
||||||
|
|
||||||
|
def find_png_files(directory):
|
||||||
|
"""Find all PNG files in a directory recursively."""
|
||||||
|
png_files = []
|
||||||
|
for root, dirs, files in os.walk(directory):
|
||||||
|
for file in files:
|
||||||
|
if file.lower().endswith('.png'):
|
||||||
|
png_files.append(os.path.relpath(os.path.join(root, file), directory))
|
||||||
|
return sorted(png_files)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# Define paths
|
||||||
|
golden_dir = Path("golden-downloads/thermion_dart/test/output")
|
||||||
|
output_dir = Path("output")
|
||||||
|
|
||||||
|
# Check if directories exist
|
||||||
|
if not golden_dir.exists():
|
||||||
|
print(f"Error: Golden directory not found: {golden_dir}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if not output_dir.exists():
|
||||||
|
print(f"Error: Output directory not found: {output_dir}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Find PNG files in both directories
|
||||||
|
golden_files = find_png_files(golden_dir)
|
||||||
|
output_files = find_png_files(output_dir)
|
||||||
|
|
||||||
|
print(f"Found {len(golden_files)} golden files and {len(output_files)} output files")
|
||||||
|
|
||||||
|
# Track comparison results
|
||||||
|
identical_count = 0
|
||||||
|
different_count = 0
|
||||||
|
missing_count = 0
|
||||||
|
error_count = 0
|
||||||
|
|
||||||
|
# Compare each golden file with its corresponding output file
|
||||||
|
for golden_file in golden_files:
|
||||||
|
golden_path = golden_dir / golden_file
|
||||||
|
output_path = output_dir / golden_file
|
||||||
|
|
||||||
|
if not output_path.exists():
|
||||||
|
print(f"❌ MISSING: {golden_file} (exists in golden but not in output)")
|
||||||
|
missing_count += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
mse, max_diff, are_identical = calculate_image_difference(golden_path, output_path)
|
||||||
|
|
||||||
|
if mse is None:
|
||||||
|
print(f"❌ ERROR: {golden_file} (failed to compare)")
|
||||||
|
error_count += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
if are_identical:
|
||||||
|
print(f"✅ IDENTICAL: {golden_file}")
|
||||||
|
identical_count += 1
|
||||||
|
else:
|
||||||
|
print(f"⚠️ DIFFERENT: {golden_file} (MSE: {mse:.2f}, Max diff: {max_diff})")
|
||||||
|
different_count += 1
|
||||||
|
|
||||||
|
# Check for files that exist in output but not in golden
|
||||||
|
extra_files = set(output_files) - set(golden_files)
|
||||||
|
for extra_file in extra_files:
|
||||||
|
print(f"ℹ️ EXTRA: {extra_file} (exists in output but not in golden)")
|
||||||
|
|
||||||
|
# Print summary
|
||||||
|
print("\n" + "="*50)
|
||||||
|
print("COMPARISON SUMMARY:")
|
||||||
|
print(f"✅ Identical files: {identical_count}")
|
||||||
|
print(f"⚠️ Different files: {different_count}")
|
||||||
|
print(f"❌ Missing files: {missing_count}")
|
||||||
|
print(f"❌ Error files: {error_count}")
|
||||||
|
print(f"ℹ️ Extra files: {len(extra_files)}")
|
||||||
|
print(f"📊 Total golden files: {len(golden_files)}")
|
||||||
|
|
||||||
|
# Exit with appropriate code
|
||||||
|
if different_count > 0 or missing_count > 0 or error_count > 0:
|
||||||
|
print("\n❌ COMPARISON FAILED")
|
||||||
|
sys.exit(1)
|
||||||
|
else:
|
||||||
|
print("\n✅ ALL COMPARISONS PASSED")
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user