From 1a573dc0faac020aa9d161c11f0ecbd955803dce Mon Sep 17 00:00:00 2001 From: Alexander Nguyen Date: Sat, 30 May 2026 00:02:16 -0700 Subject: [PATCH] test: retry the flaky cancel-with-discard integration test `test_cancel_with_discard_files_removes_partial_dir` races the creation pipeline against a mid-flight cancel (it polls with asyncio.sleep and branches on whether the directory landed first). Under load the race can transiently lose, flaking the suite. Add pytest-rerunfailures to the test extra and mark the test `@pytest.mark.flaky(reruns=3, reruns_delay=0.5)` so a transient timing miss retries instead of failing CI. Verified the marker re-runs on failure (fails twice -> passes on the third attempt). Co-Authored-By: Claude Opus 4.8 --- pyproject.toml | 1 + .../integration/controller/test_creation_flow.py | 5 +++++ uv.lock | 16 ++++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index ffa67e2..fafcd00 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,6 +68,7 @@ test = [ "pytest-asyncio>=0.23", "playwright>=1.40", # E2E browser automation against http://127.0.0.1: (Backend ยง4.10.3) "pytest-cov>=4.1", # Coverage reporting; configured under [tool.coverage.run] + "pytest-rerunfailures>=14", # Opt-in retries for timing-sensitive flakes (@pytest.mark.flaky) # httpx is already in core deps -- used for AsyncClient(app=app) in integration tests too ] diff --git a/tests/integration/controller/test_creation_flow.py b/tests/integration/controller/test_creation_flow.py index b4ef636..1f8c524 100644 --- a/tests/integration/controller/test_creation_flow.py +++ b/tests/integration/controller/test_creation_flow.py @@ -492,6 +492,11 @@ def get_record(self, name: str) -> PluginRecord | None: # --------------------------------------------------------------------------- +# Timing-sensitive: this test races the creation pipeline against a mid-flight +# cancel (it polls with ``asyncio.sleep`` and branches on whether the dir landed +# first). Under load the race can occasionally lose; retry rather than fail the +# suite on a transient timing miss. +@pytest.mark.flaky(reruns=3, reruns_delay=0.5) async def test_cancel_with_discard_files_removes_partial_dir(tmp_path: Path) -> None: """A cancel with ``discard_files=True`` deletes the partial directory.""" local_root = tmp_path / "data" diff --git a/uv.lock b/uv.lock index 7068f0b..ca61465 100644 --- a/uv.lock +++ b/uv.lock @@ -748,6 +748,7 @@ dev = [ { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-cov" }, + { name = "pytest-rerunfailures" }, { name = "python-docx" }, { name = "ruff" }, { name = "sphinx" }, @@ -779,6 +780,7 @@ test = [ { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-cov" }, + { name = "pytest-rerunfailures" }, ] [package.metadata] @@ -810,6 +812,7 @@ requires-dist = [ { name = "pytest", marker = "extra == 'test'", specifier = ">=8.0" }, { name = "pytest-asyncio", marker = "extra == 'test'", specifier = ">=0.23" }, { name = "pytest-cov", marker = "extra == 'test'", specifier = ">=4.1" }, + { name = "pytest-rerunfailures", marker = "extra == 'test'", specifier = ">=14" }, { name = "python-docx", marker = "extra == 'plugin-examples'", specifier = ">=1.1" }, { name = "pywebview", specifier = ">=5.0" }, { name = "pywin32", marker = "sys_platform == 'win32'", specifier = ">=306" }, @@ -2398,6 +2401,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl", hash = "sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678", size = 22876, upload-time = "2026-03-21T20:11:14.438Z" }, ] +[[package]] +name = "pytest-rerunfailures" +version = "16.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4d/f0/74f8e685be7ecd1572c1256132f18fce3a665d7e07649a3f23b7eb2d3bec/pytest_rerunfailures-16.3.tar.gz", hash = "sha256:37c9b1231c8083e9f4e724f50f7a21241822f9516c15c700ebbf218d6452355c", size = 34148, upload-time = "2026-05-22T06:51:22.292Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f8/98/58a71d68d3126d7f6a6ed1944c37ec207a4ff3dc66cad3bed7b59d38df61/pytest_rerunfailures-16.3-py3-none-any.whl", hash = "sha256:6bdfb8ffb46c46072e6c16bdedee38b6c13eac620d9415ed5b63152cbf283170", size = 15396, upload-time = "2026-05-22T06:51:20.547Z" }, +] + [[package]] name = "python-discovery" version = "1.3.0"