52
52
Actual shape: {actual_shape}
53
53
{actual_path}"""
54
54
55
+ # The following are the subsets of formats supported by the Matplotlib image
56
+ # comparison machinery
57
+ RASTER_IMAGE_FORMATS = ['png' ]
58
+ VECTOR_IMAGE_FORMATS = ['eps' , 'pdf' , 'svg' ]
59
+ ALL_IMAGE_FORMATS = RASTER_IMAGE_FORMATS + VECTOR_IMAGE_FORMATS
60
+
55
61
56
62
def _hash_file (in_stream ):
57
63
"""
@@ -70,8 +76,8 @@ def pathify(path):
70
76
"""
71
77
path = Path (path )
72
78
ext = ''
73
- if path .suffixes [- 1 ] == '.png' :
74
- ext = '.png'
79
+ if path .suffixes [- 1 ][ 1 :] in ALL_IMAGE_FORMATS :
80
+ ext = path . suffixes [ - 1 ]
75
81
path = str (path ).split (ext )[0 ]
76
82
path = str (path )
77
83
path = path .replace ('[' , '_' ).replace (']' , '_' )
@@ -315,18 +321,24 @@ def __init__(self,
315
321
self .logger .setLevel (level )
316
322
self .logger .addHandler (handler )
317
323
324
+ def _file_extension (self , item ):
325
+ compare = get_compare (item )
326
+ savefig_kwargs = compare .kwargs .get ('savefig_kwargs' , {})
327
+ return savefig_kwargs .get ('format' , 'png' )
328
+
318
329
def generate_filename (self , item ):
319
330
"""
320
331
Given a pytest item, generate the figure filename.
321
332
"""
333
+ ext = self ._file_extension (item )
322
334
if self .config .getini ('mpl-use-full-test-name' ):
323
- filename = generate_test_name (item ) + '.png '
335
+ filename = generate_test_name (item ) + f'. { ext } '
324
336
else :
325
337
compare = get_compare (item )
326
338
# Find test name to use as plot name
327
339
filename = compare .kwargs .get ('filename' , None )
328
340
if filename is None :
329
- filename = item .name + '.png '
341
+ filename = item .name + f'. { ext } '
330
342
331
343
filename = str (pathify (filename ))
332
344
return filename
@@ -441,10 +453,10 @@ def generate_image_hash(self, item, fig):
441
453
compare = get_compare (item )
442
454
savefig_kwargs = compare .kwargs .get ('savefig_kwargs' , {})
443
455
444
- imgdata = io . BytesIO ( )
456
+ ext = self . _file_extension ( item )
445
457
458
+ imgdata = io .BytesIO ()
446
459
fig .savefig (imgdata , ** savefig_kwargs )
447
-
448
460
out = _hash_file (imgdata )
449
461
imgdata .close ()
450
462
@@ -465,11 +477,17 @@ def compare_image_to_baseline(self, item, fig, result_dir, summary=None):
465
477
tolerance = compare .kwargs .get ('tolerance' , 2 )
466
478
savefig_kwargs = compare .kwargs .get ('savefig_kwargs' , {})
467
479
480
+ ext = self ._file_extension (item )
481
+
468
482
baseline_image_ref = self .obtain_baseline_image (item , result_dir )
469
483
470
- test_image = (result_dir / "result.png " ).absolute ()
484
+ test_image = (result_dir / f "result.{ ext } " ).absolute ()
471
485
fig .savefig (str (test_image ), ** savefig_kwargs )
472
- summary ['result_image' ] = test_image .relative_to (self .results_dir ).as_posix ()
486
+
487
+ if ext in ['png' , 'svg' ]: # Use original file
488
+ summary ['result_image' ] = test_image .relative_to (self .results_dir ).as_posix ()
489
+ else :
490
+ summary ['result_image' ] = (result_dir / f"result_{ ext } .png" ).relative_to (self .results_dir ).as_posix ()
473
491
474
492
if not os .path .exists (baseline_image_ref ):
475
493
summary ['status' ] = 'failed'
@@ -484,26 +502,33 @@ def compare_image_to_baseline(self, item, fig, result_dir, summary=None):
484
502
485
503
# setuptools may put the baseline images in non-accessible places,
486
504
# copy to our tmpdir to be sure to keep them in case of failure
487
- baseline_image = (result_dir / "baseline.png " ).absolute ()
505
+ baseline_image = (result_dir / f "baseline.{ ext } " ).absolute ()
488
506
shutil .copyfile (baseline_image_ref , baseline_image )
489
- summary ['baseline_image' ] = baseline_image .relative_to (self .results_dir ).as_posix ()
507
+
508
+ if ext in ['png' , 'svg' ]: # Use original file
509
+ summary ['baseline_image' ] = baseline_image .relative_to (self .results_dir ).as_posix ()
510
+ else :
511
+ summary ['baseline_image' ] = (result_dir / f"baseline_{ ext } .png" ).relative_to (self .results_dir ).as_posix ()
490
512
491
513
# Compare image size ourselves since the Matplotlib
492
514
# exception is a bit cryptic in this case and doesn't show
493
- # the filenames
494
- expected_shape = imread (str (baseline_image )).shape [:2 ]
495
- actual_shape = imread (str (test_image )).shape [:2 ]
496
- if expected_shape != actual_shape :
497
- summary ['status' ] = 'failed'
498
- summary ['image_status' ] = 'diff'
499
- error_message = SHAPE_MISMATCH_ERROR .format (expected_path = baseline_image ,
500
- expected_shape = expected_shape ,
501
- actual_path = test_image ,
502
- actual_shape = actual_shape )
503
- summary ['status_msg' ] = error_message
504
- return error_message
515
+ # the filenames. However imread won't work for vector graphics so we
516
+ # only do this for raster files.
517
+ if ext in RASTER_IMAGE_FORMATS :
518
+ expected_shape = imread (str (baseline_image )).shape [:2 ]
519
+ actual_shape = imread (str (test_image )).shape [:2 ]
520
+ if expected_shape != actual_shape :
521
+ summary ['status' ] = 'failed'
522
+ summary ['image_status' ] = 'diff'
523
+ error_message = SHAPE_MISMATCH_ERROR .format (expected_path = baseline_image ,
524
+ expected_shape = expected_shape ,
525
+ actual_path = test_image ,
526
+ actual_shape = actual_shape )
527
+ summary ['status_msg' ] = error_message
528
+ return error_message
505
529
506
530
results = compare_images (str (baseline_image ), str (test_image ), tol = tolerance , in_decorator = True )
531
+
507
532
summary ['tolerance' ] = tolerance
508
533
if results is None :
509
534
summary ['status' ] = 'passed'
@@ -514,8 +539,7 @@ def compare_image_to_baseline(self, item, fig, result_dir, summary=None):
514
539
summary ['status' ] = 'failed'
515
540
summary ['image_status' ] = 'diff'
516
541
summary ['rms' ] = results ['rms' ]
517
- diff_image = (result_dir / 'result-failed-diff.png' ).absolute ()
518
- summary ['diff_image' ] = diff_image .relative_to (self .results_dir ).as_posix ()
542
+ summary ['diff_image' ] = Path (results ['diff' ]).relative_to (self .results_dir ).as_posix ()
519
543
template = ['Error: Image files did not match.' ,
520
544
'RMS Value: {rms}' ,
521
545
'Expected: \n {expected}' ,
@@ -538,6 +562,8 @@ def compare_image_to_hash_library(self, item, fig, result_dir, summary=None):
538
562
compare = get_compare (item )
539
563
savefig_kwargs = compare .kwargs .get ('savefig_kwargs' , {})
540
564
565
+ ext = self ._file_extension (item )
566
+
541
567
if not self .results_hash_library_name :
542
568
# Use hash library name of current test as results hash library name
543
569
self .results_hash_library_name = Path (compare .kwargs .get ("hash_library" , "" )).name
@@ -574,7 +600,7 @@ def compare_image_to_hash_library(self, item, fig, result_dir, summary=None):
574
600
f"{ hash_library_filename } for test { hash_name } ." )
575
601
576
602
# Save the figure for later summary (will be removed later if not needed)
577
- test_image = (result_dir / "result.png " ).absolute ()
603
+ test_image = (result_dir / f "result.{ ext } " ).absolute ()
578
604
fig .savefig (str (test_image ), ** savefig_kwargs )
579
605
summary ['result_image' ] = test_image .relative_to (self .results_dir ).as_posix ()
580
606
@@ -627,6 +653,8 @@ def pytest_runtest_call(self, item): # noqa
627
653
remove_text = compare .kwargs .get ('remove_text' , False )
628
654
backend = compare .kwargs .get ('backend' , 'agg' )
629
655
656
+ ext = self ._file_extension (item )
657
+
630
658
with plt .style .context (style , after_reset = True ), switch_backend (backend ):
631
659
632
660
# Run test and get figure object
@@ -665,7 +693,7 @@ def pytest_runtest_call(self, item): # noqa
665
693
summary ['status_msg' ] = 'Skipped test, since generating image.'
666
694
generate_image = self .generate_baseline_image (item , fig )
667
695
if self .results_always : # Make baseline image available in HTML
668
- result_image = (result_dir / "baseline.png " ).absolute ()
696
+ result_image = (result_dir / f "baseline.{ ext } " ).absolute ()
669
697
shutil .copy (generate_image , result_image )
670
698
summary ['baseline_image' ] = \
671
699
result_image .relative_to (self .results_dir ).as_posix ()
0 commit comments