From a7f17026d1e64a9c377d0b34a5fe1579331613b7 Mon Sep 17 00:00:00 2001 From: danielmeppiel Date: Sat, 14 Mar 2026 13:11:41 +0100 Subject: [PATCH] fix(test): handle Windows temp directory cleanup in integration tests TemporaryDirectory context manager fails on Windows when subprocesses still hold file locks. Use ignore_cleanup_errors=True (Python 3.10+) and close Popen stdout in finally block to release handles. Same WinError 32 pattern as the auto-install teardown fix (#295). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- tests/integration/test_guardrailing_hero_e2e.py | 7 +++++-- tests/integration/test_mcp_registry_e2e.py | 12 ++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/tests/integration/test_guardrailing_hero_e2e.py b/tests/integration/test_guardrailing_hero_e2e.py index b79f8299..bbc10739 100644 --- a/tests/integration/test_guardrailing_hero_e2e.py +++ b/tests/integration/test_guardrailing_hero_e2e.py @@ -122,7 +122,7 @@ def test_2_minute_guardrailing_flow(self, apm_binary): 5. apm run design-review executes prompt from first installed package """ - with tempfile.TemporaryDirectory() as workspace: + with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as workspace: # Step 1: apm init my-project print("\n=== Step 1: apm init my-project ===") result = run_command(f"{apm_binary} init my-project --yes", cwd=workspace, show_output=True) @@ -233,7 +233,7 @@ def test_2_minute_guardrailing_flow(self, apm_binary): if process.poll() is None: process.terminate() try: - process.wait(timeout=5) + process.wait(timeout=10) except subprocess.TimeoutExpired: process.kill() process.wait() @@ -242,6 +242,9 @@ def test_2_minute_guardrailing_flow(self, apm_binary): process.kill() process.wait() pytest.fail(f"Error monitoring design-review execution: {e}") + finally: + if process.stdout: + process.stdout.close() # Verify prompt was found and started full_output = '\n'.join(output_lines) diff --git a/tests/integration/test_mcp_registry_e2e.py b/tests/integration/test_mcp_registry_e2e.py index 6decf06c..ff4df1eb 100644 --- a/tests/integration/test_mcp_registry_e2e.py +++ b/tests/integration/test_mcp_registry_e2e.py @@ -91,7 +91,7 @@ def run_command(cmd, check=True, capture_output=True, timeout=180, cwd=None, inp @pytest.fixture(scope="module") def temp_e2e_home(): """Create a temporary home directory for E2E testing.""" - with tempfile.TemporaryDirectory() as temp_dir: + with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as temp_dir: original_home = os.environ.get('HOME') test_home = os.path.join(temp_dir, 'e2e_home') os.makedirs(test_home) @@ -191,7 +191,7 @@ def test_registry_installation_with_codex(self, temp_e2e_home, apm_binary): assert codex_config.exists(), "Codex configuration not created" # Step 2: Create test project with MCP dependencies - with tempfile.TemporaryDirectory() as project_workspace: + with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as project_workspace: project_dir = Path(project_workspace) / "registry-test-project" print("Creating project with MCP dependencies...") @@ -318,7 +318,7 @@ def test_empty_string_handling_e2e(self, temp_e2e_home, apm_binary): if result.returncode != 0: pytest.skip("Codex setup failed, skipping empty string test") - with tempfile.TemporaryDirectory() as project_workspace: + with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as project_workspace: project_dir = Path(project_workspace) / "empty-string-test" result = run_command(f"{apm_binary} init empty-string-test --yes", cwd=project_workspace) @@ -427,7 +427,7 @@ def test_empty_string_handling_e2e(self, temp_e2e_home, apm_binary): if result.returncode != 0: pytest.skip("Codex setup failed, skipping empty string test") - with tempfile.TemporaryDirectory() as project_workspace: + with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as project_workspace: project_dir = Path(project_workspace) / "empty-string-test" result = run_command(f"{apm_binary} init empty-string-test --yes", cwd=project_workspace) @@ -488,7 +488,7 @@ def test_cross_adapter_consistency(self, temp_e2e_home, apm_binary): if result.returncode != 0: pytest.skip("Codex setup failed, skipping consistency test") - with tempfile.TemporaryDirectory() as project_workspace: + with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as project_workspace: project_dir = Path(project_workspace) / "consistency-test" result = run_command(f"{apm_binary} init consistency-test --yes", cwd=project_workspace) @@ -552,7 +552,7 @@ def test_duplication_prevention_e2e(self, temp_e2e_home, apm_binary): if result.returncode != 0: pytest.skip("Codex setup failed, skipping duplication test") - with tempfile.TemporaryDirectory() as project_workspace: + with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as project_workspace: project_dir = Path(project_workspace) / "duplication-test" result = run_command(f"{apm_binary} init duplication-test --yes", cwd=project_workspace)