1
1
from __future__ import annotations
2
2
3
3
import os
4
+ import pathlib
4
5
import pprint
5
6
import re
6
7
import shutil
7
8
from typing import cast
9
+ from uuid import uuid1
8
10
9
11
import pytest
10
12
@@ -1199,9 +1201,23 @@ def pytest_collection_modifyitems():
1199
1201
result .stdout .fnmatch_lines (["*RuntimeError: Some runtime error*" ])
1200
1202
1201
1203
1204
+ @pytest .fixture (scope = "session" )
1205
+ def shared_scope_setup_status_path (
1206
+ tmp_path_factory : pytest .TempPathFactory , testrun_uid : str
1207
+ ) -> pathlib .Path :
1208
+ return (
1209
+ tmp_path_factory .getbasetemp ().parent
1210
+ / "test_distributed_setup_teardown_coordination"
1211
+ / testrun_uid
1212
+ / uuid1 ().hex
1213
+ / "scope_setup_status.txt"
1214
+ )
1215
+
1216
+
1202
1217
class TestIsoScope :
1203
1218
def test_distributed_setup_teardown_coordination (
1204
- self , pytester : pytest .Pytester
1219
+ self , pytester : pytest .Pytester ,
1220
+ shared_scope_setup_status_path : pathlib .Path
1205
1221
) -> None :
1206
1222
"""
1207
1223
The isoscope scheduler provides a distributed coordination mechanism
@@ -1215,58 +1231,63 @@ def test_distributed_setup_teardown_coordination(
1215
1231
5. Resource Setup of the next test Scope begins after completion of
1216
1232
the previous test Scope's Resource Teardown.
1217
1233
"""
1218
- test_file = """
1219
- from __future__ import annotations
1220
- import pathlib
1221
- from uuid import uuid1
1222
- from typing import TYPE_CHECKING
1223
- import pytest
1224
- if TYPE_CHECKING:
1225
- from xdist.iso_scheduling_utils import (
1226
- IsoSchedulingFixture,
1227
- DistributedSetupContext,
1228
- DistributedTeardownContext
1229
- )
1230
- class TestScopeA:
1231
- @classmethod
1232
- @pytest.fixture(scope='class', autouse=True)
1233
- def distributed_setup_and_teardown(
1234
- cls,
1235
- iso_scheduling: IsoSchedulingFixture,
1236
- request: pytest.FixtureRequest):
1237
- with iso_scheduling.coordinate_setup_teardown(
1238
- setup_request=request) as coordinator:
1239
- # Distributed Setup
1240
- coordinator.maybe_call_setup(cls.patch_system_under_test)
1241
- try:
1242
- # Yield control back to the XDist Worker to allow the
1243
- # test cases to run
1244
- yield
1245
- finally:
1246
- # Distributed Teardown
1247
- coordinator.maybe_call_teardown(cls.revert_system_under_test)
1248
- @classmethod
1249
- def patch_system_under_test(
1250
- cls,
1251
- setup_context: DistributedSetupContext) -> None:
1252
- # Initialize the System Under Test for all the test cases in
1253
- # this test class and store state in `setup_context.client_dir`.
1254
- pass
1255
-
1256
- @classmethod
1257
- def revert_system_under_test(
1258
- cls,
1259
- teardown_context: DistributedTeardownContext):
1260
- # Fetch state from `teardown_context.client_dir` and revert
1261
- # changes made by `patch_system_under_test()`.
1262
- pass
1263
-
1264
- @pytest.mark.parametrize('i', range(5))
1265
- def test(self, i):
1266
- pass
1234
+ test_file = f"""
1235
+ from __future__ import annotations
1236
+ import pathlib
1237
+ from typing import TYPE_CHECKING
1238
+ import pytest
1239
+ if TYPE_CHECKING:
1240
+ from xdist.iso_scheduling_utils import (
1241
+ IsoSchedulingFixture,
1242
+ DistributedSetupContext,
1243
+ DistributedTeardownContext
1244
+ )
1267
1245
1268
- class TestScopeB(TestScopeA):
1269
- pass
1246
+ _SHARED_SCOPE_SETUP_STATUS_PATH = pathlib.Path(
1247
+ { str (shared_scope_setup_status_path )} )
1248
+
1249
+ class TestScopeA:
1250
+ @classmethod
1251
+ @pytest.fixture(scope='class', autouse=True)
1252
+ def distributed_setup_and_teardown(
1253
+ cls,
1254
+ iso_scheduling: IsoSchedulingFixture,
1255
+ request: pytest.FixtureRequest):
1256
+ with iso_scheduling.coordinate_setup_teardown(
1257
+ setup_request=request) as coordinator:
1258
+ # Distributed Setup
1259
+ coordinator.maybe_call_setup(cls.patch_system_under_test)
1260
+ try:
1261
+ # Yield control back to the XDist Worker to allow the
1262
+ # test cases to run
1263
+ yield
1264
+ finally:
1265
+ # Distributed Teardown
1266
+ coordinator.maybe_call_teardown(cls.revert_system_under_test)
1267
+ @classmethod
1268
+ def patch_system_under_test(
1269
+ cls,
1270
+ setup_context: DistributedSetupContext) -> None:
1271
+ # Initialize the System Under Test for all the test cases in
1272
+ # this test class and store state in `setup_context.client_dir`.
1273
+ assert _SHARED_SCOPE_SETUP_STATUS_PATH.read_text() == "TEARDOWN_COMPLETE"
1274
+ _SHARED_SCOPE_SETUP_STATUS_PATH.write_text("SETUP_COMPLETE")
1275
+
1276
+ @classmethod
1277
+ def revert_system_under_test(
1278
+ cls,
1279
+ teardown_context: DistributedTeardownContext):
1280
+ # Fetch state from `teardown_context.client_dir` and revert
1281
+ # changes made by `patch_system_under_test()`.
1282
+ assert _SHARED_SCOPE_SETUP_STATUS_PATH.read_text() == "SETUP_COMPLETE"
1283
+ _SHARED_SCOPE_SETUP_STATUS_PATH.write_text("TEARDOWN_COMPLETE")
1284
+
1285
+ @pytest.mark.parametrize('i', range(5))
1286
+ def test(self, i):
1287
+ assert _SHARED_SCOPE_SETUP_STATUS_PATH.read_text() == "SETUP_COMPLETE"
1288
+
1289
+ class TestScopeB(TestScopeA):
1290
+ pass
1270
1291
"""
1271
1292
pytester .makepyfile (test_a = test_file , test_b = test_file )
1272
1293
result = pytester .runpytest ("-n2" , "--dist=isoscope" , "-v" )
0 commit comments