Do not update cache from xdist worker (#10641)
This commit is contained in:
parent
3ad4344656
commit
8efb4bb9c1
1
AUTHORS
1
AUTHORS
|
@ -315,6 +315,7 @@ Samuel Searles-Bryant
|
|||
Samuele Pedroni
|
||||
Sanket Duthade
|
||||
Sankt Petersbug
|
||||
Saravanan Padmanaban
|
||||
Segev Finer
|
||||
Serhii Mozghovyi
|
||||
Seth Junot
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Fix a race condition when creating or updating the stepwise plugin's cache, which could occur when multiple xdist worker nodes try to simultaneously update the stepwise plugin's cache.
|
|
@ -48,6 +48,10 @@ def pytest_configure(config: Config) -> None:
|
|||
def pytest_sessionfinish(session: Session) -> None:
|
||||
if not session.config.getoption("stepwise"):
|
||||
assert session.config.cache is not None
|
||||
if hasattr(session.config, "workerinput"):
|
||||
# Do not update cache if this process is a xdist worker to prevent
|
||||
# race conditions (#10641).
|
||||
return
|
||||
# Clear the list of failing tests if the plugin is not active.
|
||||
session.config.cache.set(STEPWISE_CACHE_DIR, [])
|
||||
|
||||
|
@ -119,4 +123,8 @@ class StepwisePlugin:
|
|||
return None
|
||||
|
||||
def pytest_sessionfinish(self) -> None:
|
||||
if hasattr(self.config, "workerinput"):
|
||||
# Do not update cache if this process is a xdist worker to prevent
|
||||
# race conditions (#10641).
|
||||
return
|
||||
self.cache.set(STEPWISE_CACHE_DIR, self.lastfailed)
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from _pytest.cacheprovider import Cache
|
||||
from _pytest.monkeypatch import MonkeyPatch
|
||||
from _pytest.pytester import Pytester
|
||||
from _pytest.stepwise import STEPWISE_CACHE_DIR
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -278,3 +282,76 @@ def test_stepwise_skip_is_independent(pytester: Pytester) -> None:
|
|||
def test_sw_skip_help(pytester: Pytester) -> None:
|
||||
result = pytester.runpytest("-h")
|
||||
result.stdout.fnmatch_lines("*Implicitly enables --stepwise.")
|
||||
|
||||
|
||||
def test_stepwise_xdist_dont_store_lastfailed(pytester: Pytester) -> None:
|
||||
pytester.makefile(
|
||||
ext=".ini",
|
||||
pytest=f"[pytest]\ncache_dir = {pytester.path}\n",
|
||||
)
|
||||
|
||||
pytester.makepyfile(
|
||||
conftest="""
|
||||
import pytest
|
||||
|
||||
@pytest.hookimpl(tryfirst=True)
|
||||
def pytest_configure(config) -> None:
|
||||
config.workerinput = True
|
||||
"""
|
||||
)
|
||||
pytester.makepyfile(
|
||||
test_one="""
|
||||
def test_one():
|
||||
assert False
|
||||
"""
|
||||
)
|
||||
result = pytester.runpytest("--stepwise")
|
||||
assert result.ret == pytest.ExitCode.INTERRUPTED
|
||||
|
||||
stepwise_cache_file = (
|
||||
pytester.path / Cache._CACHE_PREFIX_VALUES / STEPWISE_CACHE_DIR
|
||||
)
|
||||
assert not Path(stepwise_cache_file).exists()
|
||||
|
||||
|
||||
def test_disabled_stepwise_xdist_dont_clear_cache(pytester: Pytester) -> None:
|
||||
pytester.makefile(
|
||||
ext=".ini",
|
||||
pytest=f"[pytest]\ncache_dir = {pytester.path}\n",
|
||||
)
|
||||
|
||||
stepwise_cache_file = (
|
||||
pytester.path / Cache._CACHE_PREFIX_VALUES / STEPWISE_CACHE_DIR
|
||||
)
|
||||
stepwise_cache_dir = stepwise_cache_file.parent
|
||||
stepwise_cache_dir.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
stepwise_cache_file_relative = f"{Cache._CACHE_PREFIX_VALUES}/{STEPWISE_CACHE_DIR}"
|
||||
|
||||
expected_value = '"test_one.py::test_one"'
|
||||
content = {f"{stepwise_cache_file_relative}": expected_value}
|
||||
|
||||
pytester.makefile(ext="", **content)
|
||||
|
||||
pytester.makepyfile(
|
||||
conftest="""
|
||||
import pytest
|
||||
|
||||
@pytest.hookimpl(tryfirst=True)
|
||||
def pytest_configure(config) -> None:
|
||||
config.workerinput = True
|
||||
"""
|
||||
)
|
||||
pytester.makepyfile(
|
||||
test_one="""
|
||||
def test_one():
|
||||
assert True
|
||||
"""
|
||||
)
|
||||
result = pytester.runpytest()
|
||||
assert result.ret == 0
|
||||
|
||||
assert Path(stepwise_cache_file).exists()
|
||||
with stepwise_cache_file.open() as file_handle:
|
||||
observed_value = file_handle.readlines()
|
||||
assert [expected_value] == observed_value
|
||||
|
|
Loading…
Reference in New Issue