test(tests): TDD for test_live_gui_workspace_exists xdist race (failing test)
Captures the xdist race condition in the live_gui_workspace fixture. In batched runs (pytest-xdist), the owner worker's live_gui fixture teardown can rmtree the shared workspace path before a client worker's test asserts live_gui_workspace.exists(). The test simulates this race by pointing the handle at a fresh, never-existed path (Windows file locks block rmtree on the live workspace) and asserting that the live_gui_workspace fixture recreates the directory before returning the path. This test FAILS on the current commit because the fixture is just 'return handle.workspace' without ensuring the path exists. The fix (in tests/conftest.py:727) will add workspace.mkdir(parents=True, exist_ok=True) before the return.
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
"""Tests for the live_gui_workspace fixture (Phase 3, Task 3.2)."""
|
||||
import importlib.util
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
@@ -29,3 +31,34 @@ def test_live_gui_workspace_writable(live_gui_workspace) -> None:
|
||||
test_file = live_gui_workspace / "test_write.txt"
|
||||
test_file.write_text("hello", encoding="utf-8")
|
||||
assert test_file.read_text(encoding="utf-8") == "hello"
|
||||
|
||||
|
||||
def test_live_gui_workspace_recreates_missing_workspace(live_gui) -> None:
|
||||
"""[TDD red] Captures the xdist race in live_gui_workspace: when the owner
|
||||
worker's live_gui teardown rmtree's the shared workspace between client
|
||||
workers' tests, a client worker calling live_gui_workspace must recreate
|
||||
the directory before returning the path. The current fixture returns the
|
||||
path without mkdir, so the returned path does not exist after rmtree.
|
||||
NOTE: on Windows, the live_gui subprocess holds the live workspace as its
|
||||
CWD, which blocks shutil.rmtree on the live path. We instead point the
|
||||
handle at a fresh, never-existed path under tests/artifacts/ to simulate
|
||||
the post-teardown state deterministically on all platforms.
|
||||
"""
|
||||
import time
|
||||
fake_workspace = Path(f"tests/artifacts/_live_gui_workspace_race_sim_{int(time.time() * 1000000)}")
|
||||
assert not fake_workspace.exists(), f"sanity: fake workspace must not exist pre-call: {fake_workspace}"
|
||||
original_workspace = live_gui._workspace
|
||||
live_gui._workspace = fake_workspace
|
||||
try:
|
||||
spec = importlib.util.spec_from_file_location(
|
||||
"tests.conftest",
|
||||
str(Path(__file__).parent / "conftest.py"),
|
||||
)
|
||||
conftest = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(conftest)
|
||||
result = conftest.live_gui_workspace.__wrapped__(live_gui)
|
||||
assert result.exists(), f"live_gui_workspace did not recreate missing workspace at {result}"
|
||||
finally:
|
||||
live_gui._workspace = original_workspace
|
||||
if fake_workspace.exists():
|
||||
shutil.rmtree(fake_workspace, ignore_errors=True)
|
||||
|
||||
Reference in New Issue
Block a user