From 454c369e93c1ac12706061e1c0ccf6986b383b59 Mon Sep 17 00:00:00 2001 From: Arthur Pastel Date: Thu, 31 Aug 2023 17:50:08 +0200 Subject: [PATCH 1/4] feat: add a test for pytest-xdist compatibility --- .github/workflows/ci.yml | 8 ++++---- pyproject.toml | 2 +- tests/conftest.py | 3 +++ tests/test_pytest_plugin.py | 27 +++++++++++++++++++++++++++ 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 90e27ff..356b979 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,9 +49,9 @@ jobs: name: Install valgrind run: sudo apt-get install valgrind -y - name: Install dependencies - run: pip install .[dev] - - if: matrix.config == 'pytest-benchmark' - name: Install pytest-benchmark to test compatibility - run: pip install pytest-benchmark~=4.0.0 + run: pip install .[dev,compat] + - if: matrix.config != 'pytest-benchmark' + name: Uninstall pytest-benchmark + run: pip uninstall -y pytest-benchmark - name: Run tests run: pytest -vs diff --git a/pyproject.toml b/pyproject.toml index 21aef01..2d3c054 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,7 +42,7 @@ dependencies = [ [project.optional-dependencies] lint = ["black ~= 23.3.0", "isort ~=5.12.0", "mypy ~= 1.3.0", "ruff ~= 0.0.275"] -compat = ["pytest-benchmark ~= 4.0.0"] +compat = ["pytest-benchmark ~= 4.0.0", "pytest-xdist ~= 2.0.0"] test = ["pytest ~= 7.0", "pytest-cov ~= 4.0.0"] [project.entry-points] diff --git a/tests/conftest.py b/tests/conftest.py index f58a240..0fbbbc9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -10,6 +10,9 @@ skip_without_pytest_benchmark = pytest.mark.skipif( not IS_PYTEST_BENCHMARK_INSTALLED, reason="pytest_benchmark not installed" ) +skip_with_pytest_benchmark = pytest.mark.skipif( + IS_PYTEST_BENCHMARK_INSTALLED, reason="pytest_benchmark installed" +) if IS_PYTEST_BENCHMARK_INSTALLED: pytest_plugins.append("pytest_benchmark") print( diff --git a/tests/test_pytest_plugin.py b/tests/test_pytest_plugin.py index 70a6d14..216a087 100644 --- a/tests/test_pytest_plugin.py +++ b/tests/test_pytest_plugin.py @@ -5,6 +5,7 @@ from conftest import ( IS_PERF_TRAMPOLINE_SUPPORTED, skip_with_perf_trampoline, + skip_with_pytest_benchmark, skip_without_perf_trampoline, skip_without_pytest_benchmark, skip_without_valgrind, @@ -319,3 +320,29 @@ def fixtured_child(): "py::test_some_addition_fixtured..fixtured_child" in line for line in lines ), "No fixtured child test frame found in perf map" + + +@skip_without_valgrind +@skip_with_pytest_benchmark +def test_pytest_xdist_concurrency_compatibility( + pytester: pytest.Pytester, codspeed_env +) -> None: + pytester.makepyfile( + """ + import time, pytest + + def do_something(): + time.sleep(1) + + @pytest.mark.parametrize("i", range(256)) + def test_my_stuff(benchmark, i): + benchmark(do_something) + """ + ) + # Run the test multiple times to reduce the chance of a false positive + ITERATIONS = 5 + for i in range(ITERATIONS): + with codspeed_env(): + result = pytester.runpytest("--codspeed", "-n", "128") + assert result.ret == 0, "the run should have succeeded" + assert result.stdout.fnmatch_lines(["*256 passed*"]) From a74667578c4b92c0cb96998fcca260f8caba0946 Mon Sep 17 00:00:00 2001 From: Arthur Pastel Date: Thu, 31 Aug 2023 19:10:37 +0200 Subject: [PATCH 2/4] feat: avoid concurrent wrapper builds --- pyproject.toml | 1 + src/pytest_codspeed/_wrapper/__init__.py | 11 +++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 2d3c054..2411b8b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,6 +37,7 @@ classifiers = [ dependencies = [ "cffi ~= 1.15.1", "pytest>=3.8", + "filelock ~= 3.12.2", "setuptools ~= 67.8.0; python_full_version >= '3.12.0b1'", # FIXME: remove when cffi supports directly python 3.12 ] diff --git a/src/pytest_codspeed/_wrapper/__init__.py b/src/pytest_codspeed/_wrapper/__init__.py index 382a2b4..90e3fb3 100644 --- a/src/pytest_codspeed/_wrapper/__init__.py +++ b/src/pytest_codspeed/_wrapper/__init__.py @@ -2,6 +2,7 @@ from typing import TYPE_CHECKING from cffi import FFI # type: ignore +from filelock import FileLock if TYPE_CHECKING: from .wrapper import lib as LibType @@ -24,10 +25,12 @@ def _get_ffi(): def get_lib() -> "LibType": try: ffi = _get_ffi() - ffi.compile( - target="dist_callgrind_wrapper.*", - tmpdir=_wrapper_dir, - ) + build_lock = FileLock(f"{_wrapper_dir}/build.lock") + with build_lock: + ffi.compile( + target="dist_callgrind_wrapper.*", + tmpdir=_wrapper_dir, + ) from .dist_callgrind_wrapper import lib # type: ignore return lib From 9ec09ea99c1054a1952b45ea969f2ee3c21b510f Mon Sep 17 00:00:00 2001 From: Arthur Pastel Date: Fri, 1 Sep 2023 14:43:22 +0200 Subject: [PATCH 3/4] fix: fix xdist test output assertion --- tests/test_pytest_plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_pytest_plugin.py b/tests/test_pytest_plugin.py index 216a087..ce83032 100644 --- a/tests/test_pytest_plugin.py +++ b/tests/test_pytest_plugin.py @@ -345,4 +345,4 @@ def test_my_stuff(benchmark, i): with codspeed_env(): result = pytester.runpytest("--codspeed", "-n", "128") assert result.ret == 0, "the run should have succeeded" - assert result.stdout.fnmatch_lines(["*256 passed*"]) + result.stdout.fnmatch_lines(["*256 passed*"]) From faa4b7df22825e437c2e93e01a08044b459a592b Mon Sep 17 00:00:00 2001 From: Arthur Pastel Date: Fri, 1 Sep 2023 14:53:27 +0200 Subject: [PATCH 4/4] =?UTF-8?q?Release=20v2.2.0=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pytest_codspeed/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pytest_codspeed/__init__.py b/src/pytest_codspeed/__init__.py index 45e5a23..fda8a71 100644 --- a/src/pytest_codspeed/__init__.py +++ b/src/pytest_codspeed/__init__.py @@ -1,4 +1,4 @@ -__version__ = "2.1.0" +__version__ = "2.2.0" from .plugin import BenchmarkFixture