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