@@ -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
@@ -470,41 +484,60 @@ def compare_image_to_hash_library(self, item, fig, result_dir):
470
484
test_hash = self .generate_image_hash (item , fig )
471
485
472
486
if hash_name not in hash_library :
473
- return (f"Hash for test '{ hash_name } ' not found in { hash_library_filename } . "
474
- f"Generated hash is { test_hash } ." )
487
+ new_test = True
488
+ error_message = (f"Hash for test '{ hash_name } ' not found in { hash_library_filename } . "
489
+ f"Generated hash is { test_hash } ." )
475
490
476
- if test_hash == hash_library [hash_name ]:
477
- return
478
491
479
- error_message = (f"Hash { test_hash } doesn't match hash "
480
- f"{ hash_library [hash_name ]} in library "
481
- f"{ hash_library_filename } for test { hash_name } ." )
492
+ # Save the figure for later summary (will be removed later if not needed)
493
+ test_image = (result_dir / "result.png" ).absolute ()
494
+ fig .savefig (str (test_image ), ** savefig_kwargs )
495
+
496
+ if not new_test :
497
+ if test_hash == hash_library [hash_name ]:
498
+ hash_comparison_pass = True
499
+ else :
500
+ error_message = (f"Hash { test_hash } doesn't match hash "
501
+ f"{ hash_library [hash_name ]} in library "
502
+ f"{ hash_library_filename } for test { hash_name } ." )
482
503
483
504
# If the compare has only been specified with hash and not baseline
484
505
# dir, don't attempt to find a baseline image at the default path.
485
- if not self .baseline_directory_specified (item ):
486
- # Save the figure for later summary
487
- test_image = (result_dir / "result.png" ).absolute ()
488
- fig .savefig (str (test_image ), ** savefig_kwargs )
506
+ if not hash_comparison_pass and not self .baseline_directory_specified (item ) or new_test :
489
507
return error_message
490
508
491
- baseline_image_path = self .obtain_baseline_image (item , result_dir )
509
+ # Get the baseline and generate a diff image, always so that
510
+ # --mpl-results-always can be respected.
511
+ # Ignore Errors here as it's possible the reference image dosen't exist yet.
512
+ try :
513
+ baseline_comparison = self .compare_image_to_baseline (item , fig , result_dir )
514
+ except Exception as e :
515
+ pass
516
+
517
+ # If the hash comparison passes then return
518
+ if hash_comparison_pass :
519
+ return
520
+
521
+ # If this is not a new test try and get the baseline image.
522
+ if not new_test :
523
+ baseline_image_path = self .obtain_baseline_image (item , result_dir )
524
+
492
525
try :
493
526
baseline_image = baseline_image_path
494
- baseline_image = None if not baseline_image .exists () else baseline_image
527
+ baseline_image = None if ( baseline_image and not baseline_image .exists () ) else baseline_image
495
528
except Exception :
496
529
baseline_image = None
497
530
498
531
if baseline_image is None :
499
- error_message += f"\n Unable to find baseline image { baseline_image_path } ."
532
+ error_message += f"\n Unable to find baseline image { baseline_image_path or '' } ."
500
533
return error_message
501
534
502
535
# Override the tolerance (if not explicitly set) to 0 as the hashes are not forgiving
503
536
tolerance = compare .kwargs .get ('tolerance' , None )
504
537
if not tolerance :
505
538
compare .kwargs ['tolerance' ] = 0
506
539
507
- comparison_error = (self . compare_image_to_baseline ( item , fig , result_dir ) or
540
+ comparison_error = (baseline_comparison or
508
541
"\n However, the comparison to the baseline image succeeded." )
509
542
510
543
return f"{ error_message } \n { comparison_error } "
@@ -552,10 +585,13 @@ def item_function_wrapper(*args, **kwargs):
552
585
# reference images or simply running the test.
553
586
if self .generate_dir is not None :
554
587
self .generate_baseline_image (item , fig )
588
+ if self .generate_hash_library is None :
589
+ pytest .skip ("Skipping test, since generating image." )
555
590
556
591
if self .generate_hash_library is not None :
557
592
hash_name = self .generate_test_name (item )
558
593
self ._generated_hash_library [hash_name ] = self .generate_image_hash (item , fig )
594
+ pytest .skip ("Skipping test as generating hash library." )
559
595
560
596
# Only test figures if we are not generating hashes or images
561
597
if self .generate_dir is None and self .generate_hash_library is None :
@@ -572,7 +608,8 @@ def item_function_wrapper(*args, **kwargs):
572
608
close_mpl_figure (fig )
573
609
574
610
if msg is None :
575
- shutil .rmtree (result_dir )
611
+ if not self .results_always :
612
+ shutil .rmtree (result_dir )
576
613
else :
577
614
pytest .fail (msg , pytrace = False )
578
615
0 commit comments