1import errno 2import itertools 3import os 4import os.path 5import pytest 6import yaml 7 8def pytest_addoption(parser): 9 parser.addoption("--rebaseline", action="store_true", help="output a new baseline instead of testing") 10 parser.addoption("--mark-failing", action="store_true", help="mark all failing tests as failing") 11 parser.addoption("--mark-succeeding", action="store_true", help="unmark all succeeding tests marked as failing") 12 parser.addoption("--output-diff", help="output diffs for failed tests to directory") 13 14EXPECTED = 'expected_%04u.png' 15RESULT = 'result_%04u.png' 16DIFF = 'diff_%04u.png' 17DIFF_NORM = 'diff_norm_%04u.png' 18 19def pytest_exception_interact(node, call, report): 20 outroot = node.config.getoption("--output-diff") 21 if report.failed and hasattr(node, 'funcargs'): 22 vtest = node.funcargs.get('vtest') 23 if outroot: 24 if not vtest: 25 return 26 outdir = os.path.join(outroot, *vtest.full_path) 27 try: 28 os.makedirs(outdir) 29 except OSError as e: 30 if e.errno == errno.EEXIST and os.path.isdir(outdir): 31 pass 32 else: 33 raise 34 for i, expected, result, diff, diffNorm in zip(itertools.count(), vtest.baseline, vtest.frames, *zip(*vtest.diffs)): 35 result.save(os.path.join(outdir, RESULT % i)) 36 if expected: 37 expected.save(os.path.join(outdir, EXPECTED % i)) 38 diff.save(os.path.join(outdir, DIFF % i)) 39 diffNorm.save(os.path.join(outdir, DIFF_NORM % i)) 40 41 if node.config.getoption("--mark-failing"): 42 try: 43 with open(os.path.join(vtest.path, 'manifest.yml'), 'r') as f: 44 settings = yaml.safe_load(f) 45 except IOError: 46 settings = {} 47 settings['fail'] = True 48 with open(os.path.join(vtest.path, 'manifest.yml'), 'w') as f: 49 yaml.dump(settings, f, default_flow_style=False) 50