diff --git a/docs/guide_simulations.md b/docs/guide_simulations.md index d79bc41c..fe5f5dc3 100644 --- a/docs/guide_simulations.md +++ b/docs/guide_simulations.md @@ -28,12 +28,14 @@ Defined in `tests/conftest.py`, this session-scoped fixture manages the lifecycl ```python @pytest.fixture(scope="session") -def live_gui() -> Generator[tuple[subprocess.Popen, str], None, None]: +def live_gui(request) -> Generator["_LiveGuiHandle", None, None]: process = subprocess.Popen( ["uv", "run", "python", "-u", gui_script, "--enable-test-hooks"], stdout=log_file, stderr=log_file, text=True, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP if os.name == 'nt' else 0 ) + # ... (readiness polling + xdist coordination) ... + yield _LiveGuiHandle(process, gui_script, workspace=temp_workspace) ``` - **`-u` flag**: Disables output buffering for real-time log capture. @@ -69,7 +71,20 @@ finally: Sends `reset_session()` via `ApiHookClient` before killing to prevent stale state files. -**Yield value:** `(process: subprocess.Popen, gui_script: str)`. +**Yield value:** A `_LiveGuiHandle` object (defined in `tests/conftest.py:416-465`): + +| Property | Type | Purpose | +|---|---|---| +| `.process` | `subprocess.Popen` | The sloppy.py subprocess. | +| `.gui_script` | `str` | Absolute path to `sloppy.py` that was launched. | +| `.workspace` | `Path` | Absolute path to the per-run workspace under `tests/artifacts/live_gui_workspace_/`. | +| `.is_alive()` | `() -> bool` | True if the subprocess is still running. | +| `.ensure_alive()` | `() -> None` | Stub — increments `respawn_count` if dead; full respawn is between test sessions. | +| `.respawn_count` | `int` | Diagnostic counter for subprocess deaths. | + +**Backward compatibility:** The handle supports tuple unpacking (`process, gui_script = handle`) via `__iter__`, and indexing (`handle[0]` = process, `handle[1]` = gui_script) via `__getitem__`. Tests written against the old tuple-yielding fixture still work without modification. + +**Xdist coordination:** The fixture uses an `O_EXCL`-atomic file lock at `tests/artifacts/live_gui_workspace_*/.live_gui_owner.lock`. The first xdist worker to acquire it spawns the subprocess; other workers wait and yield a null handle (`process=None`). Worker ID is read from `PYTEST_XDIST_WORKER`. ### Session Isolation