Merge branch 'pytest-dev:main' into ZeroDivErrorFix

This commit is contained in:
Jay 2023-01-13 22:11:46 +05:30 committed by GitHub
commit a84b203b6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 89 additions and 2 deletions

View File

@ -315,6 +315,7 @@ Samuel Searles-Bryant
Samuele Pedroni Samuele Pedroni
Sanket Duthade Sanket Duthade
Sankt Petersbug Sankt Petersbug
Saravanan Padmanaban
Segev Finer Segev Finer
Serhii Mozghovyi Serhii Mozghovyi
Seth Junot Seth Junot

View File

@ -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.

View File

@ -48,6 +48,10 @@ def pytest_configure(config: Config) -> None:
def pytest_sessionfinish(session: Session) -> None: def pytest_sessionfinish(session: Session) -> None:
if not session.config.getoption("stepwise"): if not session.config.getoption("stepwise"):
assert session.config.cache is not None 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. # Clear the list of failing tests if the plugin is not active.
session.config.cache.set(STEPWISE_CACHE_DIR, []) session.config.cache.set(STEPWISE_CACHE_DIR, [])
@ -119,4 +123,8 @@ class StepwisePlugin:
return None return None
def pytest_sessionfinish(self) -> 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) self.cache.set(STEPWISE_CACHE_DIR, self.lastfailed)

View File

@ -1,5 +1,5 @@
anyio[curio,trio]==3.6.2 anyio[curio,trio]==3.6.2
django==4.1.3 django==4.1.5
pytest-asyncio==0.20.2 pytest-asyncio==0.20.2
pytest-bdd==6.1.1 pytest-bdd==6.1.1
pytest-cov==4.0.0 pytest-cov==4.0.0

View File

@ -1,6 +1,10 @@
from pathlib import Path
import pytest import pytest
from _pytest.cacheprovider import Cache
from _pytest.monkeypatch import MonkeyPatch from _pytest.monkeypatch import MonkeyPatch
from _pytest.pytester import Pytester from _pytest.pytester import Pytester
from _pytest.stepwise import STEPWISE_CACHE_DIR
@pytest.fixture @pytest.fixture
@ -278,3 +282,76 @@ def test_stepwise_skip_is_independent(pytester: Pytester) -> None:
def test_sw_skip_help(pytester: Pytester) -> None: def test_sw_skip_help(pytester: Pytester) -> None:
result = pytester.runpytest("-h") result = pytester.runpytest("-h")
result.stdout.fnmatch_lines("*Implicitly enables --stepwise.") 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

View File

@ -104,7 +104,7 @@ deps =
PyYAML PyYAML
regendoc>=0.8.1 regendoc>=0.8.1
sphinx sphinx
whitelist_externals = allowlist_externals =
make make
commands = commands =
make regen make regen