22
22
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
23
# SOFTWARE.
24
24
25
- """Pytest Fixtures for supporting the PARALLEL_MONO_SCOPE Test Distribution Mode .
25
+ """Pytest Fixtures for supporting users of isoscope scheduling .
26
26
27
- NOTE: These fixtures are NOT compatible with any other Test Distribution Modes .
27
+ NOTE: These fixtures are NOT compatible with any other xdist schedulers .
28
28
29
29
NOTE: DO NOT IMPORT this module. It needs to be loaded via pytest's
30
30
`conftest.pytest_plugins` mechanism. Pytest doc discourages importing fixtures
46
46
import filelock
47
47
import pytest
48
48
49
- from utils . common . parallel_mono_scope_utils import (
50
- ParallelMonoScopeFixture ,
49
+ from xdist . iso_scheduling_utils import (
50
+ IsoSchedulingFixture ,
51
51
DistributedSetupCoordinator ,
52
52
DistributedSetupContext ,
53
53
DistributedTeardownContext ,
63
63
64
64
65
65
@pytest .fixture (scope = 'session' )
66
- def parallel_mono_scope (
66
+ def iso_scheduling (
67
67
tmp_path_factory : pytest .TempPathFactory ,
68
68
testrun_uid : str ,
69
69
worker_id : str
70
- ) -> ParallelMonoScopeFixture :
70
+ ) -> IsoSchedulingFixture :
71
71
"""A session-scoped pytest fixture for coordinating setup/teardown of test
72
- scope/class which is executing in the parallel_mono_scope Test Distribution
73
- Mode.
72
+ scope/class which is executing under isoscope scheduling.
74
73
75
- NOTE: Each XDist remote worker is running its own Pytest Session.
74
+ Based on the filelock idea described in section
75
+ "Making session-scoped fixtures execute only once" of
76
+ https://pytest-xdist.readthedocs.io/en/stable/how-to.html.
77
+
78
+ NOTE: Each XDist remote worker is running its own Pytest Session, so we want
79
+ only the worker that starts its session first to execute the setup logic and
80
+ only the worker that finishes its session last to execute the teardown logic
81
+ using a form of distributed coordination. This way, setup is executed exactly
82
+ once before any worker executes any of the scope's tests, and teardown is
83
+ executed only after the last worker finishes test execution.
76
84
77
85
USAGE EXAMPLE:
78
86
@@ -82,24 +90,23 @@ def parallel_mono_scope(
82
90
import pytest
83
91
84
92
if TYPE_CHECKING:
85
- from utils.common.parallel_mono_scope_utils import (
86
- ParallelMonoScopeFixture ,
93
+ from xdist.iso_scheduling_utils import (
94
+ IsoSchedulingFixture ,
87
95
DistributedSetupContext,
88
96
DistributedTeardownContext
89
97
)
90
98
91
- @pytest.mark.parallel_mono_scope
92
- class TestDeng12345ParallelMonoScope:
99
+ class TestSomething:
93
100
94
101
@classmethod
95
102
@pytest.fixture(scope='class', autouse=True)
96
103
def distributed_setup_and_teardown(
97
104
cls,
98
- parallel_mono_scope: ParallelMonoScopeFixture :
105
+ iso_scheduling: IsoSchedulingFixture :
99
106
request: pytest.FixtureRequest):
100
107
101
108
# Distributed Setup and Teardown
102
- with parallel_mono_scope .coordinate_setup_teardown(
109
+ with iso_scheduling .coordinate_setup_teardown(
103
110
setup_request=request) as coordinator:
104
111
# Distributed Setup
105
112
coordinator.maybe_call_setup(cls.patch_system_under_test)
@@ -126,12 +133,13 @@ def revert_system_under_test(
126
133
# Fetch state from `teardown_context.client_dir` and revert
127
134
# changes made by `patch_system_under_test()`.
128
135
129
- perms, tc_ids = generate_tests(
130
- os.path.realpath(__file__),
131
- TestDistributionModeEnum.PARALLEL_MONO_SCOPE)
136
+ def test_case1(self)
137
+ ...
138
+
139
+ def test_case2(self)
140
+ ...
132
141
133
- @pytest.mark.parametrize('test_data', perms, ids=tc_ids)
134
- def test_case(self, test_data: dict[str, dict])
142
+ def test_case3(self)
135
143
...
136
144
```
137
145
@@ -146,17 +154,17 @@ def test_case(self, test_data: dict[str, dict])
146
154
yields an instance of `DistributedSetupCoordinator` for the current
147
155
Pytest Session.
148
156
"""
149
- return _ParallelMonoScopeFixtureImpl (tmp_path_factory = tmp_path_factory ,
150
- testrun_uid = testrun_uid ,
151
- worker_id = worker_id )
157
+ return _IsoSchedulingFixtureImpl (tmp_path_factory = tmp_path_factory ,
158
+ testrun_uid = testrun_uid ,
159
+ worker_id = worker_id )
152
160
153
161
154
- class _ParallelMonoScopeFixtureImpl ( ParallelMonoScopeFixture ):
162
+ class _IsoSchedulingFixtureImpl ( IsoSchedulingFixture ):
155
163
"""Context manager yielding a new instance of the implementation of the
156
164
`DistributedSetupCoordinator` interface.
157
165
158
- An instance of _ParallelMonoScopeFixtureImpl is returned by our pytest
159
- fixture `parallel_mono_scope `.
166
+ An instance of _IsoSchedulingFixtureImpl is returned by our pytest
167
+ fixture `iso_scheduling `.
160
168
"""
161
169
# pylint: disable=too-few-public-methods
162
170
@@ -206,11 +214,11 @@ def coordinate_setup_teardown(
206
214
207
215
208
216
class _DistributedSetupCoordinatorImpl (DistributedSetupCoordinator ):
209
- """Distributed scope/class setup/teardown coordination for the
210
- `parallel_mono_scope` Test Distribution Mode .
217
+ """Distributed scope/class setup/teardown coordination for isoscope
218
+ scheduling .
211
219
212
220
NOTE: do not instantiate this class directly. Use the
213
- `parallel_mono_scope ` fixture instead!
221
+ `iso_scheduling ` fixture instead!
214
222
215
223
"""
216
224
_DISTRIBUTED_SETUP_ROOT_DIR_LINK_NAME = 'distributed_setup'
@@ -257,7 +265,7 @@ def maybe_call_setup(
257
265
Process-safe.
258
266
259
267
Call `maybe_call_setup` from the pytest setup-teardown fixture of your
260
- `PARALLEL_MONO_SCOPE` test (typically test class) if it needs to
268
+ isoscope-scheduled test (typically test class) if it needs to
261
269
initialize a resource which is common to all of its test cases which may
262
270
be executing in different XDist worker processes (such as a subnet in
263
271
`subnet.xml`).
@@ -272,8 +280,7 @@ def maybe_call_setup(
272
280
:return: An instance of `DistributedSetupContext` which MUST be passed
273
281
in the corresponding call to `maybe_call_teardown`.
274
282
275
- :raise parallel_mono_scope.CoordinationTimeoutError: If attempt to
276
- acquire the lock times out.
283
+ :raise CoordinationTimeoutError: If attempt to acquire the lock times out.
277
284
"""
278
285
# `maybe_call_setup()` may be called only once per instance of
279
286
# `_SetupCoordinator`
@@ -307,7 +314,7 @@ def maybe_call_teardown(
307
314
tests for your test scope. Process-safe.
308
315
309
316
Call `maybe_call_teardown` from the pytest setup-teardown fixture of
310
- your `PARALLEL_MONO_SCOPE` test (typically test class) if it needs to
317
+ your isoscope-scheduled test (typically test class) if it needs to
311
318
initialize a resource which is common to all of its test cases which may
312
319
be executing in different XDist worker processes (such as a subnet in
313
320
`subnet.xml`).
@@ -320,8 +327,7 @@ def maybe_call_teardown(
320
327
invoked.
321
328
:param timeout: Lock acquisition timeout in seconds
322
329
323
- :raise parallel_mono_scope.CoordinationTimeoutError: If attempt to
324
- acquire the lock times out.
330
+ :raise CoordinationTimeoutError: If attempt to acquire the lock times out.
325
331
"""
326
332
# Make sure `maybe_call_setup()` was already called on this instance
327
333
# of `_SetupCoordinator`
@@ -359,8 +365,7 @@ def wrapper(*args, **kwargs):
359
365
360
366
class _DistributedSetupCoordinationImpl :
361
367
"""Low-level implementation of Context Managers for Coordinating
362
- Distributed Setup and Teardown for the `parallel_mono_scope`
363
- Test Distribution Mode.
368
+ Distributed Setup and Teardown for users of isoscope scheduling.
364
369
"""
365
370
_ROOT_STATE_FILE_NAME = 'root_state.json'
366
371
_ROOT_LOCK_FILE_NAME = 'lock'
@@ -426,7 +431,7 @@ def acquire_distributed_setup(
426
431
timeout : float
427
432
) -> Generator [DistributedSetupContext , None , None ]:
428
433
"""Low-level implementation of Context Manager for Coordinating
429
- Distributed Setup for the `parallel_mono_scope` Test Distribution Mode .
434
+ Distributed Setup for isoscope scheduling .
430
435
431
436
:param root_context_dir: Scope/class-specific root directory for
432
437
saving this context manager's state. This directory is common to
@@ -436,8 +441,7 @@ def acquire_distributed_setup(
436
441
directly by the calling setup-teardown fixture.
437
442
:param timeout: Lock acquisition timeout in seconds
438
443
439
- :raise parallel_mono_scope.CoordinationTimeoutError: If attempt to
440
- acquire the lock times out.
444
+ :raise CoordinationTimeoutError: If attempt to acquire the lock times out.
441
445
"""
442
446
#
443
447
# Before control passes to the managed code block
@@ -502,16 +506,14 @@ def acquire_distributed_teardown(
502
506
timeout : float
503
507
) -> Generator [DistributedTeardownContext , None , None ]:
504
508
"""Low-level implementation of Context Manager for Coordinating
505
- Distributed Teardown for the `parallel_mono_scope` Test Distribution
506
- Mode.
509
+ Distributed Teardown for the isoscope scheduling.
507
510
508
511
:param setup_context: The instance of `DistributedSetupContext` that was
509
512
yielded by the corresponding use of the
510
513
`_distributed_setup_permission` context manager.
511
514
:param timeout: Lock acquisition timeout in seconds
512
515
513
- :raise parallel_mono_scope.CoordinationTimeoutError: If attempt to
514
- acquire the lock times out.
516
+ :raise CoordinationTimeoutError: If attempt to acquire the lock times out.
515
517
"""
516
518
#
517
519
# Before control passes to the managed code block
0 commit comments