@@ -155,6 +155,12 @@ def pytest_addoption(parser):
155
155
results_path_help = "directory for test results, relative to location where py.test is run"
156
156
group .addoption ('--mpl-results-path' , help = results_path_help , action = 'store' )
157
157
parser .addini ('mpl-results-path' , help = results_path_help )
158
+
159
+ results_always_help = "Always generate result images, not just for failed tests."
160
+ group .addoption ('--mpl-results-always' , action = 'store_true' ,
161
+ help = results_always_help )
162
+ parser .addini ('mpl-results-always' , help = results_always_help )
163
+
158
164
parser .addini ('mpl-use-full-test-name' , help = "use fully qualified test name as the filename." ,
159
165
type = 'bool' )
160
166
@@ -175,6 +181,8 @@ def pytest_configure(config):
175
181
results_dir = config .getoption ("--mpl-results-path" ) or config .getini ("mpl-results-path" )
176
182
hash_library = config .getoption ("--mpl-hash-library" )
177
183
generate_summary = config .getoption ("--mpl-generate-summary" )
184
+ results_always = config .getoption ("--mpl-results-always" ) or config .getini ("mpl-results-always" )
185
+
178
186
179
187
if config .getoption ("--mpl-baseline-relative" ):
180
188
baseline_relative_dir = config .getoption ("--mpl-baseline-path" )
@@ -205,7 +213,8 @@ def pytest_configure(config):
205
213
results_dir = results_dir ,
206
214
hash_library = hash_library ,
207
215
generate_hash_library = generate_hash_lib ,
208
- generate_summary = generate_summary ))
216
+ generate_summary = generate_summary ,
217
+ results_always = results_always ))
209
218
210
219
else :
211
220
@@ -262,7 +271,8 @@ def __init__(self,
262
271
results_dir = None ,
263
272
hash_library = None ,
264
273
generate_hash_library = None ,
265
- generate_summary = None
274
+ generate_summary = None ,
275
+ results_always = False
266
276
):
267
277
self .config = config
268
278
self .baseline_dir = baseline_dir
@@ -274,6 +284,7 @@ def __init__(self,
274
284
if generate_summary and generate_summary .lower () not in ("html" ,):
275
285
raise ValueError (f"The mpl summary type '{ generate_summary } ' is not supported." )
276
286
self .generate_summary = generate_summary
287
+ self .results_always = results_always
277
288
278
289
# Generate the containing dir for all test results
279
290
if not self .results_dir :
@@ -389,7 +400,6 @@ def generate_baseline_image(self, item, fig):
389
400
** savefig_kwargs )
390
401
391
402
close_mpl_figure (fig )
392
- pytest .skip ("Skipping test, since generating image" )
393
403
394
404
def generate_image_hash (self , item , fig ):
395
405
"""
@@ -455,6 +465,10 @@ def load_hash_library(self, library_path):
455
465
return json .load (fp )
456
466
457
467
def compare_image_to_hash_library (self , item , fig , result_dir ):
468
+ new_test = False
469
+ hash_comparison_pass = False
470
+ baseline_image_path = None
471
+
458
472
compare = self .get_compare (item )
459
473
savefig_kwargs = compare .kwargs .get ('savefig_kwargs' , {})
460
474
@@ -468,42 +482,60 @@ def compare_image_to_hash_library(self, item, fig, result_dir):
468
482
hash_name = self .generate_test_name (item )
469
483
470
484
if hash_name not in hash_library :
471
- return f"Hash for test '{ hash_name } ' not found in { hash_library_filename } ."
485
+ new_test = True
486
+ error_message = f"Hash for test '{ hash_name } ' not found in { hash_library_filename } ."
472
487
473
488
test_hash = self .generate_image_hash (item , fig )
474
489
475
- if test_hash == hash_library [hash_name ]:
476
- return
490
+ # Save the figure for later summary (will be removed later if not needed)
491
+ test_image = (result_dir / "result.png" ).absolute ()
492
+ fig .savefig (str (test_image ), ** savefig_kwargs )
477
493
478
- error_message = (f"Hash { test_hash } doesn't match hash "
479
- f"{ hash_library [hash_name ]} in library "
480
- f"{ hash_library_filename } for test { hash_name } ." )
494
+ if not new_test :
495
+ if test_hash == hash_library [hash_name ]:
496
+ hash_comparison_pass = True
497
+ else :
498
+ error_message = (f"Hash { test_hash } doesn't match hash "
499
+ f"{ hash_library [hash_name ]} in library "
500
+ f"{ hash_library_filename } for test { hash_name } ." )
481
501
482
502
# If the compare has only been specified with hash and not baseline
483
503
# dir, don't attempt to find a baseline image at the default path.
484
- if not self .baseline_directory_specified (item ):
485
- # Save the figure for later summary
486
- test_image = (result_dir / "result.png" ).absolute ()
487
- fig .savefig (str (test_image ), ** savefig_kwargs )
504
+ if not hash_comparison_pass and not self .baseline_directory_specified (item ) or new_test :
488
505
return error_message
489
506
490
- baseline_image_path = self .obtain_baseline_image (item , result_dir )
507
+ # Get the baseline and generate a diff image, always so that
508
+ # --mpl-results-always can be respected.
509
+ # Ignore Errors here as it's possible the reference image dosen't exist yet.
510
+ try :
511
+ baseline_comparison = self .compare_image_to_baseline (item , fig , result_dir )
512
+ except Exception as e :
513
+ pass
514
+
515
+ # If the hash comparison passes then return
516
+ if hash_comparison_pass :
517
+ return
518
+
519
+ # If this is not a new test try and get the baseline image.
520
+ if not new_test :
521
+ baseline_image_path = self .obtain_baseline_image (item , result_dir )
522
+
491
523
try :
492
524
baseline_image = baseline_image_path
493
- baseline_image = None if not baseline_image .exists () else baseline_image
525
+ baseline_image = None if ( baseline_image and not baseline_image .exists () ) else baseline_image
494
526
except Exception :
495
527
baseline_image = None
496
528
497
529
if baseline_image is None :
498
- error_message += f"\n Unable to find baseline image { baseline_image_path } ."
530
+ error_message += f"\n Unable to find baseline image { baseline_image_path or '' } ."
499
531
return error_message
500
532
501
533
# Override the tolerance (if not explicitly set) to 0 as the hashes are not forgiving
502
534
tolerance = compare .kwargs .get ('tolerance' , None )
503
535
if not tolerance :
504
536
compare .kwargs ['tolerance' ] = 0
505
537
506
- comparison_error = (self . compare_image_to_baseline ( item , fig , result_dir ) or
538
+ comparison_error = (baseline_comparison or
507
539
"\n However, the comparison to the baseline image succeeded." )
508
540
509
541
return f"{ error_message } \n { comparison_error } "
@@ -551,10 +583,13 @@ def item_function_wrapper(*args, **kwargs):
551
583
# reference images or simply running the test.
552
584
if self .generate_dir is not None :
553
585
self .generate_baseline_image (item , fig )
586
+ if self .generate_hash_library is None :
587
+ pytest .skip ("Skipping test, since generating image." )
554
588
555
589
if self .generate_hash_library is not None :
556
590
hash_name = self .generate_test_name (item )
557
591
self ._generated_hash_library [hash_name ] = self .generate_image_hash (item , fig )
592
+ pytest .skip ("Skipping test as generating hash library." )
558
593
559
594
# Only test figures if we are not generating hashes or images
560
595
if self .generate_dir is None and self .generate_hash_library is None :
@@ -571,7 +606,8 @@ def item_function_wrapper(*args, **kwargs):
571
606
close_mpl_figure (fig )
572
607
573
608
if msg is None :
574
- shutil .rmtree (result_dir )
609
+ if not self .results_always :
610
+ shutil .rmtree (result_dir )
575
611
else :
576
612
pytest .fail (msg , pytrace = False )
577
613
0 commit comments