userver: en/testsuite/plugins/assertrepr_compare.py Source File
Loading...
Searching...
No Matches
assertrepr_compare.py
1import contextlib
2import enum
3import io
4import itertools
5import logging
6import typing
7
8import pytest
9
10from testsuite._internal import compare_transform
11from testsuite.compare import CompareVisitor
12
13
14class AssertMode(enum.Enum):
15 DEFAULT = 'default'
16 COMBINE = 'combine'
17 ANALYZE = 'analyze'
18
19
21 def pytest_register_compare_visitors(self) -> list[CompareVisitor]:
22 raise NotImplementedError
23
24
25def pytest_addhooks(pluginmanager):
26 pluginmanager.add_hookspecs(CompareVisitorsHookspec)
27
28
30 def __init__(self, assert_mode):
31 self._disabled = False
32 self._assert_mode = assert_mode
33 self._compare_visitors: list[CompareVisitor] = []
34
35 @contextlib.contextmanager
36 def disabled(self):
37 saved = self._disabled
38 try:
39 self._disabled = True
40 yield
41 finally:
42 self._disabled = saved
43
44 def pytest_assertrepr_compare(
45 self,
46 config: pytest.Config,
47 op: str,
48 left: typing.Any,
49 right: typing.Any,
50 ):
51 if op != '==' or self._disabled:
52 return None
53
55 compare_visitors=self._compare_visitors,
56 )
57 try:
58 mapped_left, mapped_right = comparator.visit(left, right)
59 except Exception:
60 logging.exception('testsuite assertrepr_compare failed:')
61 return None
62
63 with self.disabled():
64 pytest_result = config.hook.pytest_assertrepr_compare(
65 config=config,
66 op=op,
67 left=mapped_left,
68 right=mapped_right,
69 )
70 if not pytest_result:
71 return pytest_result
72
73 output = io.StringIO()
74 if comparator.errors:
75 print(f'left {op} right')
76 for path, errors in comparator.errors.items():
77 print(f'{path}:', file=output)
78 for error in errors:
79 print(f' - {error}', file=output)
80
81 if self._assert_mode == AssertMode.COMBINE:
82 print('pytest default:\n', file=output)
83 for items in pytest_result:
84 for item in items:
85 print(item, file=output)
86 return output.getvalue().splitlines()
87
88 def pytest_sessionstart(self, session):
89 self._compare_visitors = list(
90 itertools.chain.from_iterable(
91 session.config.pluginmanager.hook.pytest_register_compare_visitors()
92 )
93 )
94
95
96def pytest_configure(config: pytest.Config):
97 if config.option.assert_mode != AssertMode.DEFAULT:
98 config.pluginmanager.register(
99 AssertionPlugin(config.option.assert_mode)
100 )
101
102
103def pytest_addoption(parser: pytest.Parser):
104 """
105 :param parser: pytest's argument parser
106 """
107 group = parser.getgroup('common')
108 group.addoption(
109 '--assert-mode',
110 choices=list(AssertMode),
111 type=AssertMode,
112 default=AssertMode.COMBINE,
113 help='Assertion representation mode, combined by default',
114 )
115 group.addoption(
116 '--assert-depth',
117 type=int,
118 default=None,
119 help='Depth of assertions, use 0 for simple print different items',
120 )