15 from collections
import defaultdict
16 from pathlib
import Path
17 from typing
import Callable, Generator, Optional
25 expand_reference_file_name,
37 yaml.representer.SafeRepresenter.add_representer(str, str_representer)
38 yaml.representer.SafeRepresenter.add_representer(
39 AlwaysTrueDefaultDict, yaml.representer.SafeRepresenter.represent_dict
60 config.addinivalue_line(
62 "shared_cwd(id): make SubprocessBaseTest tests share a working directory",
64 config.addinivalue_line(
66 "do_not_collect_source: flag the test code as not to be collected",
72 session.docstrings = {}
77 Record source code of tests.
80 if isinstance(item, pytest.Function)
and not item.get_closest_marker(
81 "do_not_collect_source"
84 f
"{item.parent.name}.{item.originalname}"
85 if isinstance(item.parent, pytest.Class)
86 else item.originalname
88 source_code =
CodeWrapper(inspect.getsource(item.function),
"python")
89 item.session.sources[name] = source_code
94 Extract the id of the shared cwd directory needed by the class, if any.
96 If the class is marked with shared_cwd multiple times only the last one
97 is taken into account.
99 Return the id or None.
101 if hasattr(cls,
"pytestmark"):
102 for mark
in cls.pytestmark:
103 if mark.name ==
"shared_cwd":
110 Return the path to the shared directory identified by id.
112 name = f
"gaudi.{get_platform()}.{cwd_id}".replace(
"/",
"_")
113 return config.cache.mkdir(name)
116 @pytest.fixture(scope=
"class")
118 request: pytest.FixtureRequest,
119 tmp_path_factory: Callable,
120 ) -> Generator[FixtureResult,
None,
None]:
123 if cls
and issubclass(cls, SubprocessBaseTest):
124 if hasattr(cls,
"popen_kwargs")
and "cwd" not in cls.popen_kwargs:
126 cls.popen_kwargs[
"cwd"] = (
129 else tmp_path_factory.mktemp(
"workdir")
131 result = cls.run_program(
132 tmp_path=tmp_path_factory.mktemp(
"tmp-", numbered=
True)
138 @pytest.fixture(scope=
"class")
140 fixture_result: FixtureResult,
141 ) -> Generator[subprocess.CompletedProcess,
None,
None]:
142 yield fixture_result.completed_process
if fixture_result
else None
145 @pytest.fixture(scope=
"class")
147 completed_process: subprocess.CompletedProcess,
148 ) -> Generator[bytes,
None,
None]:
149 yield completed_process.stdout
if completed_process
else None
152 @pytest.fixture(scope=
"class")
154 completed_process: subprocess.CompletedProcess,
155 ) -> Generator[bytes,
None,
None]:
156 yield completed_process.stderr
if completed_process
else None
159 @pytest.fixture(scope=
"class")
161 completed_process: subprocess.CompletedProcess,
162 ) -> Generator[int,
None,
None]:
163 yield completed_process.returncode
if completed_process
else None
166 @pytest.fixture(scope=
"class")
167 def cwd(fixture_result: FixtureResult) -> Generator[Path,
None,
None]:
168 yield Path(fixture_result.cwd)
if fixture_result
else None
171 @pytest.fixture(autouse=
True)
173 request: pytest.FixtureRequest, fixture_result: FixtureResult
177 and fixture_result.failure
is not None
178 and "test_fixture_setup" not in request.keywords
180 pytest.skip(f
"{fixture_result.failure}")
183 @pytest.fixture(scope=
"function", autouse=
True)
185 record_property: Callable[[str, str],
None],
186 ) -> Generator[
None,
None,
None]:
187 val_start_time = time.perf_counter()
189 record_property(
"validate_time", round(time.perf_counter() - val_start_time, 2))
192 @pytest.fixture(scope=
"class", autouse=
True)
194 request: pytest.FixtureRequest,
197 if cls
and cls.__doc__:
198 request.session.docstrings[cls.__name__] = inspect.getdoc(cls)
201 @pytest.fixture(scope=
"class")
205 if hasattr(cls,
"reference")
and cls.reference:
207 if hasattr(cls,
"resolve_path"):
208 path = cls.resolve_path(path)
211 yield Path(path)
if path
else None
214 @pytest.fixture(scope=
"class")
217 original_reference_data =
None
218 current_reference_data =
None
221 if reference_path.exists()
and reference_path.stat().st_size > 0:
222 with open(reference_path,
"r")
as f:
223 original_reference_data = yaml.safe_load(f)
230 current_reference_data = original_reference_data.copy()
232 yield current_reference_data
234 if current_reference_data != original_reference_data:
236 newrefname = f
"{reference_path}.new"
237 while os.path.exists(newrefname):
239 newrefname = f
"{reference_path}.~{cnt}~.new"
241 if os.environ.get(
"GAUDI_TEST_IGNORE_STDOUT_VALIDATION") ==
"1":
243 newrefname = reference_path
245 os.makedirs(os.path.dirname(newrefname), exist_ok=
True)
246 with open(newrefname,
"w")
as f:
247 yaml.safe_dump(current_reference_data, f, sort_keys=
False)