From fe7907d78cd21a111542e8bf445526922bda9237 Mon Sep 17 00:00:00 2001 From: Dave Hall Date: Wed, 14 Feb 2024 18:50:34 +0000 Subject: [PATCH 01/28] Add `logot` to plugin list (#11972) --- scripts/update-plugin-list.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/update-plugin-list.py b/scripts/update-plugin-list.py index 2c57414c0..c21520819 100644 --- a/scripts/update-plugin-list.py +++ b/scripts/update-plugin-list.py @@ -61,6 +61,7 @@ DEVELOPMENT_STATUS_CLASSIFIERS = ( ) ADDITIONAL_PROJECTS = { # set of additional projects to consider as plugins "logassert", + "logot", "nuts", "flask_fixture", } From 46e6fb12c7d6d95750959964c1f59039dd51b579 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 14 Feb 2024 15:53:28 -0300 Subject: [PATCH 02/28] Consider paths and pathlists relative to cwd in case of an absent ini-file (#11963) Previously this would trigger an `AssertionError`. While it could be considered a bug-fix, but given it now can be relied upon, it is probably better to consider it an improvement. Fix #11311 --- changelog/11311.improvement.rst | 4 ++++ src/_pytest/config/__init__.py | 8 +++++--- src/_pytest/config/argparsing.py | 7 +++++++ testing/test_config.py | 12 ++++++++++++ 4 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 changelog/11311.improvement.rst diff --git a/changelog/11311.improvement.rst b/changelog/11311.improvement.rst new file mode 100644 index 000000000..0072f3974 --- /dev/null +++ b/changelog/11311.improvement.rst @@ -0,0 +1,4 @@ +When using ``--override-ini`` for paths in invocations without a configuration file defined, the current working directory is used +as the relative directory. + +Previoulsy this would raise an :class:`AssertionError`. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index cada2aa09..3d448214c 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1563,9 +1563,11 @@ class Config: # in this case, we already have a list ready to use. # if type == "paths": - # TODO: This assert is probably not valid in all cases. - assert self.inipath is not None - dp = self.inipath.parent + dp = ( + self.inipath.parent + if self.inipath is not None + else self.invocation_params.dir + ) input_values = shlex.split(value) if isinstance(value, str) else value return [dp / x for x in input_values] elif type == "args": diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index da05acf39..d98f1ae9a 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -198,9 +198,16 @@ class Parser: * ``paths``: a list of :class:`pathlib.Path`, separated as in a shell * ``pathlist``: a list of ``py.path``, separated as in a shell + For ``paths`` and ``pathlist`` types, they are considered relative to the ini-file. + In case the execution is happening without an ini-file defined, + they will be considered relative to the current working directory (for example with ``--override-ini``). + .. versionadded:: 7.0 The ``paths`` variable type. + .. versionadded:: 8.1 + Use the current working directory to resolve ``paths`` and ``pathlist`` in the absence of an ini-file. + Defaults to ``string`` if ``None`` or not passed. :param default: Default value if no ini-file option exists but is queried. diff --git a/testing/test_config.py b/testing/test_config.py index ead693cf4..4377257b1 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -1874,6 +1874,18 @@ class TestOverrideIniArgs: assert "ERROR:" not in result.stderr.str() result.stdout.fnmatch_lines(["collected 1 item", "*= 1 passed in *="]) + def test_override_ini_without_config_file(self, pytester: Pytester) -> None: + pytester.makepyfile(**{"src/override_ini_without_config_file.py": ""}) + pytester.makepyfile( + **{ + "tests/test_override_ini_without_config_file.py": ( + "import override_ini_without_config_file\ndef test(): pass" + ), + } + ) + result = pytester.runpytest("--override-ini", "pythonpath=src") + assert result.parseoutcomes() == {"passed": 1} + def test_help_via_addopts(pytester: Pytester) -> None: pytester.makeini( From acafd003aa643765abed144c618ab13cab24ecc1 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 14 Feb 2024 16:08:45 -0300 Subject: [PATCH 03/28] Consider pyproject.toml files for config if no other config files were found (#11962) Today `pyproject.toml` is the standard for declaring a Python project root, so seems reasonable to consider it for the ini configuration (and specially `rootdir`) in case we do not find other suitable candidates. Related to #11311 --- changelog/11962.improvement.rst | 1 + doc/en/reference/customize.rst | 13 +++++++++---- src/_pytest/config/findpaths.py | 5 +++++ testing/test_config.py | 32 +++++++++++++++++++++++++++++++- 4 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 changelog/11962.improvement.rst diff --git a/changelog/11962.improvement.rst b/changelog/11962.improvement.rst new file mode 100644 index 000000000..453b99d33 --- /dev/null +++ b/changelog/11962.improvement.rst @@ -0,0 +1 @@ +In case no other suitable candidates for configuration file are found, a ``pyproject.toml`` (even without a ``[tool.pytest.ini_options]`` table) will be considered as the configuration file and define the ``rootdir``. diff --git a/doc/en/reference/customize.rst b/doc/en/reference/customize.rst index 24c0ed217..cab111726 100644 --- a/doc/en/reference/customize.rst +++ b/doc/en/reference/customize.rst @@ -177,13 +177,20 @@ Files will only be matched for configuration if: * ``tox.ini``: contains a ``[pytest]`` section. * ``setup.cfg``: contains a ``[tool:pytest]`` section. +Finally, a ``pyproject.toml`` file will be considered the ``configfile`` if no other match was found, in this case +even if it does not contain a ``[tool.pytest.ini_options]`` table (this was added in ``8.1``). + The files are considered in the order above. Options from multiple ``configfiles`` candidates are never merged - the first match wins. +The configuration file also determines the value of the ``rootpath``. + The :class:`Config ` object (accessible via hooks or through the :fixture:`pytestconfig` fixture) will subsequently carry these attributes: -- :attr:`config.rootpath `: the determined root directory, guaranteed to exist. +- :attr:`config.rootpath `: the determined root directory, guaranteed to exist. It is used as + a reference directory for constructing test addresses ("nodeids") and can be used also by plugins for storing + per-testrun information. - :attr:`config.inipath `: the determined ``configfile``, may be ``None`` (it is named ``inipath`` for historical reasons). @@ -193,9 +200,7 @@ will subsequently carry these attributes: versions of the older ``config.rootdir`` and ``config.inifile``, which have type ``py.path.local``, and still exist for backward compatibility. -The ``rootdir`` is used as a reference directory for constructing test -addresses ("nodeids") and can be used also by plugins for storing -per-testrun information. + Example: diff --git a/src/_pytest/config/findpaths.py b/src/_pytest/config/findpaths.py index 96f353651..9909376de 100644 --- a/src/_pytest/config/findpaths.py +++ b/src/_pytest/config/findpaths.py @@ -101,15 +101,20 @@ def locate_config( args = [x for x in args if not str(x).startswith("-")] if not args: args = [invocation_dir] + found_pyproject_toml: Optional[Path] = None for arg in args: argpath = absolutepath(arg) for base in (argpath, *argpath.parents): for config_name in config_names: p = base / config_name if p.is_file(): + if p.name == "pyproject.toml" and found_pyproject_toml is None: + found_pyproject_toml = p ini_config = load_config_dict_from_file(p) if ini_config is not None: return base, p, ini_config + if found_pyproject_toml is not None: + return found_pyproject_toml.parent, found_pyproject_toml, {} return None, None, {} diff --git a/testing/test_config.py b/testing/test_config.py index 4377257b1..88470ff2d 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -135,15 +135,45 @@ class TestParseIni: assert config.getini("minversion") == "3.36" def test_pyproject_toml(self, pytester: Pytester) -> None: - pytester.makepyprojecttoml( + pyproject_toml = pytester.makepyprojecttoml( """ [tool.pytest.ini_options] minversion = "1.0" """ ) config = pytester.parseconfig() + assert config.inipath == pyproject_toml assert config.getini("minversion") == "1.0" + def test_empty_pyproject_toml(self, pytester: Pytester) -> None: + """An empty pyproject.toml is considered as config if no other option is found.""" + pyproject_toml = pytester.makepyprojecttoml("") + config = pytester.parseconfig() + assert config.inipath == pyproject_toml + + def test_empty_pyproject_toml_found_many(self, pytester: Pytester) -> None: + """ + In case we find multiple pyproject.toml files in our search, without a [tool.pytest.ini_options] + table and without finding other candidates, the closest to where we started wins. + """ + pytester.makefile( + ".toml", + **{ + "pyproject": "", + "foo/pyproject": "", + "foo/bar/pyproject": "", + }, + ) + config = pytester.parseconfig(pytester.path / "foo/bar") + assert config.inipath == pytester.path / "foo/bar/pyproject.toml" + + def test_pytest_ini_trumps_pyproject_toml(self, pytester: Pytester) -> None: + """A pytest.ini always take precedence over a pyproject.toml file.""" + pytester.makepyprojecttoml("[tool.pytest.ini_options]") + pytest_ini = pytester.makefile(".ini", pytest="") + config = pytester.parseconfig() + assert config.inipath == pytest_ini + def test_toxini_before_lower_pytestini(self, pytester: Pytester) -> None: sub = pytester.mkdir("sub") sub.joinpath("tox.ini").write_text( From cbb5c82c3952b90178c7f3185f2267a0658528e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Feb 2024 16:11:20 -0300 Subject: [PATCH 04/28] build(deps): Bump peter-evans/create-pull-request from 5.0.2 to 6.0.0 (#11922) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 5.0.2 to 6.0.0. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/153407881ec5c347639a548ade7d8ad1d6740e38...b1ddad2c994a25fbc81a28b3ec0e368bb2021c50) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/update-plugin-list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index 214d734c9..55fb4dc6f 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -46,7 +46,7 @@ jobs: run: python scripts/update-plugin-list.py - name: Create Pull Request - uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 + uses: peter-evans/create-pull-request@b1ddad2c994a25fbc81a28b3ec0e368bb2021c50 with: commit-message: '[automated] Update plugin list' author: 'pytest bot ' From 5d7a5a9343ec7d675a9599312f8055e2a81cc1db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Feb 2024 16:11:30 -0300 Subject: [PATCH 05/28] build(deps): Bump codecov/codecov-action from 3 to 4 (#11921) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3 to 4. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v3...v4) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 363cbe901..9fe01dc72 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -205,7 +205,7 @@ jobs: - name: Upload coverage to Codecov if: "matrix.use_coverage" - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 continue-on-error: true with: fail_ci_if_error: true From c6313a06fbc837316bddda64e97b23ad6cc44afd Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 16 Feb 2024 12:03:38 +0200 Subject: [PATCH 06/28] scripts/update-plugin-list: include packages starting with "pytest_" (underscore) Fix #11985. --- scripts/update-plugin-list.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/update-plugin-list.py b/scripts/update-plugin-list.py index c21520819..6226bc8c9 100644 --- a/scripts/update-plugin-list.py +++ b/scripts/update-plugin-list.py @@ -29,7 +29,7 @@ Pytest Plugin List ================== Below is an automated compilation of ``pytest``` plugins available on `PyPI `_. -It includes PyPI projects whose names begin with "pytest-" and a handful of manually selected projects. +It includes PyPI projects whose names begin with "pytest-" or "pytest_" and a handful of manually selected projects. Packages classified as inactive are excluded. For detailed insights into how this list is generated, @@ -110,7 +110,10 @@ def pytest_plugin_projects_from_pypi(session: CachedSession) -> dict[str, int]: return { name: p["_last-serial"] for p in response.json()["projects"] - if (name := p["name"]).startswith("pytest-") or name in ADDITIONAL_PROJECTS + if ( + (name := p["name"]).startswith(("pytest-", "pytest_")) + or name in ADDITIONAL_PROJECTS + ) } From 288201b8f579efd3ebc4ca243966444f99686d9d Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 4 Feb 2024 22:25:49 +0200 Subject: [PATCH 07/28] recwarn: let base exceptions propagate through `pytest.warns` again Fix #11907. --- changelog/11907.bugfix.rst | 1 + src/_pytest/recwarn.py | 12 +++++++ testing/test_recwarn.py | 70 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 changelog/11907.bugfix.rst diff --git a/changelog/11907.bugfix.rst b/changelog/11907.bugfix.rst new file mode 100644 index 000000000..10aa39aeb --- /dev/null +++ b/changelog/11907.bugfix.rst @@ -0,0 +1 @@ +Fix a regression in pytest 8.0.0 whereby calling :func:`pytest.skip` and similar control-flow exceptions within a :func:`pytest.warns()` block would get suppressed instead of propagating. diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 62df274bd..ddb240eb2 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -20,6 +20,7 @@ import warnings from _pytest.deprecated import check_ispytest from _pytest.fixtures import fixture +from _pytest.outcomes import Exit from _pytest.outcomes import fail @@ -302,6 +303,17 @@ class WarningsChecker(WarningsRecorder): __tracebackhide__ = True + # BaseExceptions like pytest.{skip,fail,xfail,exit} or Ctrl-C within + # pytest.warns should *not* trigger "DID NOT WARN" and get suppressed + # when the warning doesn't happen. Control-flow exceptions should always + # propagate. + if exc_val is not None and ( + not isinstance(exc_val, Exception) + # Exit is an Exception, not a BaseException, for some reason. + or isinstance(exc_val, Exit) + ): + return + def found_str(): return pformat([record.message for record in self], indent=2) diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index e269bd7dd..1feb3e654 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -5,9 +5,10 @@ from typing import Optional from typing import Type import warnings -from _pytest.pytester import Pytester -from _pytest.recwarn import WarningsRecorder import pytest +from pytest import ExitCode +from pytest import Pytester +from pytest import WarningsRecorder def test_recwarn_stacklevel(recwarn: WarningsRecorder) -> None: @@ -479,6 +480,71 @@ class TestWarns: warnings.warn("some warning", category=FutureWarning) raise ValueError("some exception") + def test_skip_within_warns(self, pytester: Pytester) -> None: + """Regression test for #11907.""" + pytester.makepyfile( + """ + import pytest + + def test_it(): + with pytest.warns(Warning): + pytest.skip("this is OK") + """, + ) + + result = pytester.runpytest() + assert result.ret == ExitCode.OK + result.assert_outcomes(skipped=1) + + def test_fail_within_warns(self, pytester: Pytester) -> None: + """Regression test for #11907.""" + pytester.makepyfile( + """ + import pytest + + def test_it(): + with pytest.warns(Warning): + pytest.fail("BOOM") + """, + ) + + result = pytester.runpytest() + assert result.ret == ExitCode.TESTS_FAILED + result.assert_outcomes(failed=1) + assert "DID NOT WARN" not in str(result.stdout) + + def test_exit_within_warns(self, pytester: Pytester) -> None: + """Regression test for #11907.""" + pytester.makepyfile( + """ + import pytest + + def test_it(): + with pytest.warns(Warning): + pytest.exit() + """, + ) + + result = pytester.runpytest() + assert result.ret == ExitCode.INTERRUPTED + result.assert_outcomes() + + def test_keyboard_interrupt_within_warns(self, pytester: Pytester) -> None: + """Regression test for #11907.""" + pytester.makepyfile( + """ + import pytest + + def test_it(): + with pytest.warns(Warning): + raise KeyboardInterrupt() + """, + ) + + result = pytester.runpytest_subprocess() + assert result.ret == ExitCode.INTERRUPTED + result.assert_outcomes() + def test_raise_type_error_on_non_string_warning() -> None: """Check pytest.warns validates warning messages are strings (#10865).""" From dcf9da92be44e5347fdb559c6717c031daae2b25 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 16 Feb 2024 13:38:55 +0200 Subject: [PATCH 08/28] recwarn: minor style improvements In preparation for next commit. --- src/_pytest/recwarn.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index ddb240eb2..5e1fea2a0 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -314,7 +314,7 @@ class WarningsChecker(WarningsRecorder): ): return - def found_str(): + def found_str() -> str: return pformat([record.message for record in self], indent=2) try: @@ -341,14 +341,19 @@ class WarningsChecker(WarningsRecorder): module=w.__module__, source=w.source, ) - # Check warnings has valid argument type (#10865). - wrn: warnings.WarningMessage - for wrn in self: - self._validate_message(wrn) - @staticmethod - def _validate_message(wrn: Any) -> None: - if not isinstance(msg := wrn.message.args[0], str): - raise TypeError( - f"Warning message must be str, got {msg!r} (type {type(msg).__name__})" - ) + # Currently in Python it is possible to pass other types than an + # `str` message when creating `Warning` instances, however this + # causes an exception when :func:`warnings.filterwarnings` is used + # to filter those warnings. See + # https://github.com/python/cpython/issues/103577 for a discussion. + # While this can be considered a bug in CPython, we put guards in + # pytest as the error message produced without this check in place + # is confusing (#10865). + for w in self: + msg = w.message.args[0] # type: ignore[union-attr] + if isinstance(msg, str): + continue + raise TypeError( + f"Warning message must be str, got {msg!r} (type {type(msg).__name__})" + ) From 0475b1c925d40930172d5e198861864905a2b15d Mon Sep 17 00:00:00 2001 From: Eero Vaher Date: Fri, 9 Feb 2024 21:13:41 +0100 Subject: [PATCH 09/28] Allow using `warnings.warn()` with Warnings Test: `warnings.warn()` expects that its first argument is a `str` or a `Warning`, but since 9454fc38d3636b79ee657d6cacf7477eb8acee52 `pytest.warns()` no longer allows `Warning` instances unless the first argument the `Warning` was initialized with is a `str`. Furthermore, if the `Warning` was created without arguments then `pytest.warns()` raises an unexpected `IndexError`. The new tests reveal the problem. Fix: `pytest.warns()` now allows using `warnings.warn()` with a `Warning` instance, as is required by Python, with one exception. If the warning used is a `UserWarning` that was created by passing it arguments and the first argument was not a `str` then `pytest.raises()` still considers that an error. This is because if an invalid type was used in `warnings.warn()` then Python creates a `UserWarning` anyways and it becomes impossible for `pytest` to figure out if that was done automatically or not. [ran: rebased on previous commit] --- AUTHORS | 1 + changelog/10865.improvement.rst | 3 ++- src/_pytest/recwarn.py | 15 +++++++++++++-- testing/test_recwarn.py | 27 +++++++++++++++++++-------- 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/AUTHORS b/AUTHORS index 25159b8b0..dce91c4fe 100644 --- a/AUTHORS +++ b/AUTHORS @@ -127,6 +127,7 @@ Edison Gustavo Muenz Edoardo Batini Edson Tadeu M. Manoel Eduardo Schettino +Eero Vaher Eli Boyarski Elizaveta Shashkova Éloi Rivard diff --git a/changelog/10865.improvement.rst b/changelog/10865.improvement.rst index 2c2856dfe..a5ced8e9a 100644 --- a/changelog/10865.improvement.rst +++ b/changelog/10865.improvement.rst @@ -1,2 +1,3 @@ -:func:`pytest.warns` now validates that warning object's ``message`` is of type `str` -- currently in Python it is possible to pass other types than `str` when creating `Warning` instances, however this causes an exception when :func:`warnings.filterwarnings` is used to filter those warnings. See `CPython #103577 `__ for a discussion. +:func:`pytest.warns` now validates that :func:`warnings.warn` was called with a `str` or a `Warning`. +Currently in Python it is possible to use other types, however this causes an exception when :func:`warnings.filterwarnings` is used to filter those warnings (see `CPython #103577 `__ for a discussion). While this can be considered a bug in CPython, we decided to put guards in pytest as the error message produced without this check in place is confusing. diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 5e1fea2a0..9eced36ff 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -351,9 +351,20 @@ class WarningsChecker(WarningsRecorder): # pytest as the error message produced without this check in place # is confusing (#10865). for w in self: - msg = w.message.args[0] # type: ignore[union-attr] + if type(w.message) is not UserWarning: + # If the warning was of an incorrect type then `warnings.warn()` + # creates a UserWarning. Any other warning must have been specified + # explicitly. + continue + if not w.message.args: + # UserWarning() without arguments must have been specified explicitly. + continue + msg = w.message.args[0] if isinstance(msg, str): continue + # It's possible that UserWarning was explicitly specified, and + # its first argument was not a string. But that case can't be + # distinguished from an invalid type. raise TypeError( - f"Warning message must be str, got {msg!r} (type {type(msg).__name__})" + f"Warning must be str or Warning, got {msg!r} (type {type(msg).__name__})" ) diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index 1feb3e654..edd4f51b5 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -3,6 +3,7 @@ import sys from typing import List from typing import Optional from typing import Type +from typing import Union import warnings import pytest @@ -546,24 +547,34 @@ class TestWarns: result.assert_outcomes() -def test_raise_type_error_on_non_string_warning() -> None: - """Check pytest.warns validates warning messages are strings (#10865).""" - with pytest.raises(TypeError, match="Warning message must be str"): +def test_raise_type_error_on_invalid_warning() -> None: + """Check pytest.warns validates warning messages are strings (#10865) or + Warning instances (#11959).""" + with pytest.raises(TypeError, match="Warning must be str or Warning"): with pytest.warns(UserWarning): warnings.warn(1) # type: ignore -def test_no_raise_type_error_on_string_warning() -> None: - """Check pytest.warns validates warning messages are strings (#10865).""" - with pytest.warns(UserWarning): - warnings.warn("Warning") +@pytest.mark.parametrize( + "message", + [ + pytest.param("Warning", id="str"), + pytest.param(UserWarning(), id="UserWarning"), + pytest.param(Warning(), id="Warning"), + ], +) +def test_no_raise_type_error_on_valid_warning(message: Union[str, Warning]) -> None: + """Check pytest.warns validates warning messages are strings (#10865) or + Warning instances (#11959).""" + with pytest.warns(Warning): + warnings.warn(message) @pytest.mark.skipif( hasattr(sys, "pypy_version_info"), reason="Not for pypy", ) -def test_raise_type_error_on_non_string_warning_cpython() -> None: +def test_raise_type_error_on_invalid_warning_message_cpython() -> None: # Check that we get the same behavior with the stdlib, at least if filtering # (see https://github.com/python/cpython/issues/103577 for details) with pytest.raises(TypeError): From 9b838f491f895c8b46778c38953295364999aaee Mon Sep 17 00:00:00 2001 From: Reagan Lee <96998476+reaganjlee@users.noreply.github.com> Date: Fri, 16 Feb 2024 14:01:41 +0200 Subject: [PATCH 10/28] recwarn: fix pytest.warns handling of Warnings with multiple arguments Fix #11906 --- changelog/11906.bugfix.rst | 1 + src/_pytest/recwarn.py | 8 ++++---- testing/test_recwarn.py | 14 ++++++++++++++ 3 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 changelog/11906.bugfix.rst diff --git a/changelog/11906.bugfix.rst b/changelog/11906.bugfix.rst new file mode 100644 index 000000000..68bede540 --- /dev/null +++ b/changelog/11906.bugfix.rst @@ -0,0 +1 @@ +Fix regression with :func:`pytest.warns` using custom warning subclasses which have more than one parameter in their `__init__`. diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 9eced36ff..bcf9f1466 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -334,10 +334,10 @@ class WarningsChecker(WarningsRecorder): for w in self: if not self.matches(w): warnings.warn_explicit( - str(w.message), - w.message.__class__, # type: ignore[arg-type] - w.filename, - w.lineno, + message=w.message, + category=w.category, + filename=w.filename, + lineno=w.lineno, module=w.__module__, source=w.source, ) diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index edd4f51b5..27ee9aa72 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -581,3 +581,17 @@ def test_raise_type_error_on_invalid_warning_message_cpython() -> None: with warnings.catch_warnings(): warnings.filterwarnings("ignore", "test") warnings.warn(1) # type: ignore + + +def test_multiple_arg_custom_warning() -> None: + """Test for issue #11906.""" + + class CustomWarning(UserWarning): + def __init__(self, a, b): + pass + + with pytest.warns(CustomWarning): + with pytest.raises(pytest.fail.Exception, match="DID NOT WARN"): + with pytest.warns(CustomWarning, match="not gonna match"): + a, b = 1, 2 + warnings.warn(CustomWarning(a, b)) From 22b541e4eb46d53370938da239c686eaecbbf8e4 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 17 Feb 2024 00:09:47 +0200 Subject: [PATCH 11/28] Merge pull request #11993 from pytest-dev/release-8.0.1 Prepare release 8.0.1 (cherry picked from commit 68524d48586e7f8d070fc1146e5ff90e770d0382) --- changelog/11875.bugfix.rst | 1 - changelog/11879.bugfix.rst | 1 - changelog/11906.bugfix.rst | 1 - changelog/11907.bugfix.rst | 1 - changelog/11929.bugfix.rst | 1 - changelog/11937.bugfix.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-8.0.1.rst | 21 +++++++++++++++++++ doc/en/builtin.rst | 34 ++++++++++++++----------------- doc/en/changelog.rst | 24 ++++++++++++++++++++++ doc/en/example/parametrize.rst | 6 +++--- doc/en/getting-started.rst | 2 +- doc/en/reference/reference.rst | 2 +- 13 files changed, 66 insertions(+), 30 deletions(-) delete mode 100644 changelog/11875.bugfix.rst delete mode 100644 changelog/11879.bugfix.rst delete mode 100644 changelog/11906.bugfix.rst delete mode 100644 changelog/11907.bugfix.rst delete mode 100644 changelog/11929.bugfix.rst delete mode 100644 changelog/11937.bugfix.rst create mode 100644 doc/en/announce/release-8.0.1.rst diff --git a/changelog/11875.bugfix.rst b/changelog/11875.bugfix.rst deleted file mode 100644 index d646be631..000000000 --- a/changelog/11875.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Correctly handle errors from :func:`getpass.getuser` in Python 3.13. diff --git a/changelog/11879.bugfix.rst b/changelog/11879.bugfix.rst deleted file mode 100644 index 70b6cce72..000000000 --- a/changelog/11879.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix an edge case where ``ExceptionInfo._stringify_exception`` could crash :func:`pytest.raises`. diff --git a/changelog/11906.bugfix.rst b/changelog/11906.bugfix.rst deleted file mode 100644 index 68bede540..000000000 --- a/changelog/11906.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix regression with :func:`pytest.warns` using custom warning subclasses which have more than one parameter in their `__init__`. diff --git a/changelog/11907.bugfix.rst b/changelog/11907.bugfix.rst deleted file mode 100644 index 10aa39aeb..000000000 --- a/changelog/11907.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a regression in pytest 8.0.0 whereby calling :func:`pytest.skip` and similar control-flow exceptions within a :func:`pytest.warns()` block would get suppressed instead of propagating. diff --git a/changelog/11929.bugfix.rst b/changelog/11929.bugfix.rst deleted file mode 100644 index 8ab50e6f4..000000000 --- a/changelog/11929.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a regression in pytest 8.0.0 whereby autouse fixtures defined in a module get ignored by the doctests in the module. diff --git a/changelog/11937.bugfix.rst b/changelog/11937.bugfix.rst deleted file mode 100644 index 3b15fb528..000000000 --- a/changelog/11937.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a regression in pytest 8.0.0 whereby items would be collected in reverse order in some circumstances. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 120aae662..780451146 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-8.0.1 release-8.0.0 release-8.0.0rc2 release-8.0.0rc1 diff --git a/doc/en/announce/release-8.0.1.rst b/doc/en/announce/release-8.0.1.rst new file mode 100644 index 000000000..7d828e55b --- /dev/null +++ b/doc/en/announce/release-8.0.1.rst @@ -0,0 +1,21 @@ +pytest-8.0.1 +======================================= + +pytest 8.0.1 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Bruno Oliveira +* Clément Robert +* Pierre Sassoulas +* Ran Benita + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index c565a87c4..e9e42b9e8 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -22,7 +22,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a cachedir: .pytest_cache rootdir: /home/sweet/project collected 0 items - cache -- .../_pytest/cacheprovider.py:526 + cache -- .../_pytest/cacheprovider.py:527 Return a cache object that can persist state between testing sessions. cache.get(key, default) @@ -33,7 +33,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Values can be any object handled by the json stdlib module. - capsysbinary -- .../_pytest/capture.py:1008 + capsysbinary -- .../_pytest/capture.py:1007 Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``. The captured output is made available via ``capsysbinary.readouterr()`` @@ -43,7 +43,6 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Returns an instance of :class:`CaptureFixture[bytes] `. Example: - .. code-block:: python def test_output(capsysbinary): @@ -51,7 +50,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capsysbinary.readouterr() assert captured.out == b"hello\n" - capfd -- .../_pytest/capture.py:1036 + capfd -- .../_pytest/capture.py:1034 Enable text capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method @@ -61,7 +60,6 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Returns an instance of :class:`CaptureFixture[str] `. Example: - .. code-block:: python def test_system_echo(capfd): @@ -69,7 +67,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capfd.readouterr() assert captured.out == "hello\n" - capfdbinary -- .../_pytest/capture.py:1064 + capfdbinary -- .../_pytest/capture.py:1061 Enable bytes capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method @@ -79,7 +77,6 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Returns an instance of :class:`CaptureFixture[bytes] `. Example: - .. code-block:: python def test_system_echo(capfdbinary): @@ -97,7 +94,6 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Returns an instance of :class:`CaptureFixture[str] `. Example: - .. code-block:: python def test_output(capsys): @@ -105,7 +101,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capsys.readouterr() assert captured.out == "hello\n" - doctest_namespace [session scope] -- .../_pytest/doctest.py:743 + doctest_namespace [session scope] -- .../_pytest/doctest.py:745 Fixture that returns a :py:class:`dict` that will be injected into the namespace of doctests. @@ -119,7 +115,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a For more details: :ref:`doctest_namespace`. - pytestconfig [session scope] -- .../_pytest/fixtures.py:1365 + pytestconfig [session scope] -- .../_pytest/fixtures.py:1354 Session-scoped fixture that returns the session's :class:`pytest.Config` object. @@ -129,7 +125,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a if pytestconfig.getoption("verbose") > 0: ... - record_property -- .../_pytest/junitxml.py:284 + record_property -- .../_pytest/junitxml.py:283 Add extra properties to the calling test. User properties become part of the test report and are available to the @@ -143,13 +139,13 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a def test_function(record_property): record_property("example_key", 1) - record_xml_attribute -- .../_pytest/junitxml.py:307 + record_xml_attribute -- .../_pytest/junitxml.py:306 Add extra xml attributes to the tag for the calling test. The fixture is callable with ``name, value``. The value is automatically XML-encoded. - record_testsuite_property [session scope] -- .../_pytest/junitxml.py:345 + record_testsuite_property [session scope] -- .../_pytest/junitxml.py:344 Record a new ```` tag as child of the root ````. This is suitable to writing global information regarding the entire test @@ -174,10 +170,10 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a `pytest-xdist `__ plugin. See :issue:`7767` for details. - tmpdir_factory [session scope] -- .../_pytest/legacypath.py:300 + tmpdir_factory [session scope] -- .../_pytest/legacypath.py:302 Return a :class:`pytest.TempdirFactory` instance for the test session. - tmpdir -- .../_pytest/legacypath.py:307 + tmpdir -- .../_pytest/legacypath.py:309 Return a temporary directory path object which is unique to each test function invocation, created as a sub directory of the base temporary directory. @@ -207,7 +203,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a * caplog.record_tuples -> list of (logger_name, level, message) tuples * caplog.clear() -> clear captured records and formatted log output string - monkeypatch -- .../_pytest/monkeypatch.py:30 + monkeypatch -- .../_pytest/monkeypatch.py:32 A convenient fixture for monkey-patching. The fixture provides these methods to modify objects, dictionaries, or @@ -231,16 +227,16 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a To undo modifications done by the fixture in a contained scope, use :meth:`context() `. - recwarn -- .../_pytest/recwarn.py:30 + recwarn -- .../_pytest/recwarn.py:32 Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions. See https://docs.pytest.org/en/latest/how-to/capture-warnings.html for information on warning categories. - tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:239 + tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:241 Return a :class:`pytest.TempPathFactory` instance for the test session. - tmp_path -- .../_pytest/tmpdir.py:254 + tmp_path -- .../_pytest/tmpdir.py:256 Return a temporary directory path object which is unique to each test function invocation, created as a sub directory of the base temporary directory. diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 6f67b7ba1..6ed764207 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,30 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 8.0.1 (2024-02-16) +========================= + +Bug Fixes +--------- + +- `#11875 `_: Correctly handle errors from :func:`getpass.getuser` in Python 3.13. + + +- `#11879 `_: Fix an edge case where ``ExceptionInfo._stringify_exception`` could crash :func:`pytest.raises`. + + +- `#11906 `_: Fix regression with :func:`pytest.warns` using custom warning subclasses which have more than one parameter in their `__init__`. + + +- `#11907 `_: Fix a regression in pytest 8.0.0 whereby calling :func:`pytest.skip` and similar control-flow exceptions within a :func:`pytest.warns()` block would get suppressed instead of propagating. + + +- `#11929 `_: Fix a regression in pytest 8.0.0 whereby autouse fixtures defined in a module get ignored by the doctests in the module. + + +- `#11937 `_: Fix a regression in pytest 8.0.0 whereby items would be collected in reverse order in some circumstances. + + pytest 8.0.0 (2024-01-27) ========================= diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index 207aa145b..99afaded8 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -503,10 +503,10 @@ Running it results in some skips if we don't have all the python interpreters in .. code-block:: pytest . $ pytest -rs -q multipython.py - ssssssssssssssssssssssss... [100%] + ssssssssssss...ssssssssssss [100%] ========================= short test summary info ========================== - SKIPPED [12] multipython.py:68: 'python3.9' not found - SKIPPED [12] multipython.py:68: 'python3.10' not found + SKIPPED [12] multipython.py:65: 'python3.9' not found + SKIPPED [12] multipython.py:65: 'python3.11' not found 3 passed, 24 skipped in 0.12s Parametrization of optional implementations/imports diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 48af9d975..114d69328 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 8.0.0 + pytest 8.0.1 .. _`simpletest`: diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 4f0b1835b..1076026c2 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -2028,7 +2028,7 @@ All the command-line flags can be obtained by running ``pytest --help``:: failure --doctest-glob=pat Doctests file matching pattern, default: test*.txt --doctest-ignore-import-errors - Ignore doctest ImportErrors + Ignore doctest collection errors --doctest-continue-on-failure For a given doctest, continue to run after the first failure From 9f13d41d7bf773d9a64ff84f7c26fec7fbd431cf Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 17 Feb 2024 12:13:57 +0200 Subject: [PATCH 12/28] code: fix `IndexError` crash in `getstatementrange_ast` Fix #11953. --- changelog/11953.bugfix.rst | 1 + src/_pytest/_code/source.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 changelog/11953.bugfix.rst diff --git a/changelog/11953.bugfix.rst b/changelog/11953.bugfix.rst new file mode 100644 index 000000000..5aff5f7fd --- /dev/null +++ b/changelog/11953.bugfix.rst @@ -0,0 +1 @@ +Fix an ``IndexError`` crash raising from ``getstatementrange_ast``. diff --git a/src/_pytest/_code/source.py b/src/_pytest/_code/source.py index 69f580e20..dac3c3867 100644 --- a/src/_pytest/_code/source.py +++ b/src/_pytest/_code/source.py @@ -197,7 +197,9 @@ def getstatementrange_ast( # by using the BlockFinder helper used which inspect.getsource() uses itself. block_finder = inspect.BlockFinder() # If we start with an indented line, put blockfinder to "started" mode. - block_finder.started = source.lines[start][0].isspace() + block_finder.started = ( + bool(source.lines[start]) and source.lines[start][0].isspace() + ) it = ((x + "\n") for x in source.lines[start:end]) try: for tok in tokenize.generate_tokens(lambda: next(it)): From 5f241f388be3aaf4faa5e5e0029548863413014f Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 17 Feb 2024 16:10:21 -0300 Subject: [PATCH 13/28] Revert sys.platform verification to simple comparison (#11998) As the comment above it states, we need to keep the comparison simple so mypy can understand it, otherwise it will fail to properly handle this on Windows and will flag ``os.getuid()`` missing. --- src/_pytest/compat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 077fa65da..fa387f6db 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -289,7 +289,7 @@ def get_user_id() -> int | None: # mypy follows the version and platform checking expectation of PEP 484: # https://mypy.readthedocs.io/en/stable/common_issues.html?highlight=platform#python-version-and-system-platform-checks # Containment checks are too complex for mypy v1.5.0 and cause failure. - if sys.platform in {"win32", "emscripten"}: + if sys.platform == "win32" or sys.platform == "emscripten": # noqa: PLR1714 # win32 does not have a getuid() function. # Emscripten has a return 0 stub. return None From cefb3e2277b6ea24acc7b1088f80ef0f9e9f3858 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 17 Feb 2024 17:46:58 -0300 Subject: [PATCH 14/28] Disallow Sphinx 6 and 7 (#12000) Using Sphinx 6.x and 7.x the search bar disappears. Restrict to Sphinx 5.x for now until we find a solution. Reverts #11568 Fixes #11988 --- doc/en/requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/en/requirements.txt b/doc/en/requirements.txt index 36801746a..3369bd10b 100644 --- a/doc/en/requirements.txt +++ b/doc/en/requirements.txt @@ -2,7 +2,8 @@ pallets-sphinx-themes pluggy>=1.2.0 pygments-pytest>=2.3.0 sphinx-removed-in>=0.2.0 -sphinx>=5,<8 +# In Sphinx 6 and 7, the search bar disappears; restrict this for now until we find a solution. +sphinx>=5,<6 sphinxcontrib-trio sphinxcontrib-svg2pdfconverter # Pin packaging because it no longer handles 'latest' version, which From 52da8dd66c9eaba3c8557f80fc9a5b87a4ea03b1 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 18 Feb 2024 00:19:26 +0000 Subject: [PATCH 15/28] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 408 +++++++++++++++++++++++-------- 1 file changed, 312 insertions(+), 96 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index ce1e4f6bd..f9d3d02f0 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -7,7 +7,7 @@ Pytest Plugin List ================== Below is an automated compilation of ``pytest``` plugins available on `PyPI `_. -It includes PyPI projects whose names begin with "pytest-" and a handful of manually selected projects. +It includes PyPI projects whose names begin with "pytest-" or "pytest_" and a handful of manually selected projects. Packages classified as inactive are excluded. For detailed insights into how this list is generated, @@ -27,7 +27,7 @@ please refer to `the update script =7,<9) ; extra == "pytest" :pypi:`nuts` Network Unit Testing System Aug 11, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-abq` Pytest integration for the ABQ universal test runner. Apr 07, 2023 N/A N/A :pypi:`pytest-abstracts` A contextmanager pytest fixture for handling multiple mock abstracts May 25, 2022 N/A N/A - :pypi:`pytest-accept` A pytest-plugin for updating doctest outputs Dec 21, 2022 N/A pytest (>=6,<8) + :pypi:`pytest-accept` A pytest-plugin for updating doctest outputs Feb 10, 2024 N/A pytest (>=6) :pypi:`pytest-adaptavist` pytest plugin for generating test execution results within Jira Test Management (tm4j) Oct 13, 2022 N/A pytest (>=5.4.0) :pypi:`pytest-adaptavist-fixed` pytest plugin for generating test execution results within Jira Test Management (tm4j) Nov 08, 2023 N/A pytest >=5.4.0 :pypi:`pytest-addons-test` 用于测试pytest的插件 Aug 02, 2021 N/A pytest (>=6.2.4,<7.0.0) @@ -67,7 +68,7 @@ This list contains 1367 plugins. :pypi:`pytest-allure-intersection` Oct 27, 2022 N/A pytest (<5) :pypi:`pytest-allure-spec-coverage` The pytest plugin aimed to display test coverage of the specs(requirements) in Allure Oct 26, 2021 N/A pytest :pypi:`pytest-alphamoon` Static code checks used at Alphamoon Dec 30, 2021 5 - Production/Stable pytest (>=3.5.0) - :pypi:`pytest-analyzer` this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system Feb 06, 2024 N/A pytest >=7.3.1 + :pypi:`pytest-analyzer` this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system Feb 12, 2024 N/A pytest >=7.3.1 :pypi:`pytest-android` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Feb 21, 2019 3 - Alpha pytest :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) @@ -104,9 +105,10 @@ This list contains 1367 plugins. :pypi:`pytest-astropy` Meta-package containing dependencies for testing Sep 26, 2023 5 - Production/Stable pytest >=4.6 :pypi:`pytest-astropy-header` pytest plugin to add diagnostic information to the header of the test output Sep 06, 2022 3 - Alpha pytest (>=4.6) :pypi:`pytest-ast-transformer` May 04, 2019 3 - Alpha pytest + :pypi:`pytest_async` pytest-async - Run your coroutine in event loop without decorator Feb 26, 2020 N/A N/A :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A :pypi:`pytest-asyncio` Pytest support for asyncio Feb 09, 2024 4 - Beta pytest <9,>=7.0.0 - :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Nov 30, 2023 N/A N/A + :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Feb 12, 2024 N/A N/A :pypi:`pytest-asyncio-network-simulator` pytest-asyncio-network-simulator: Plugin for pytest for simulator the network in tests Jul 31, 2018 3 - Alpha pytest (<3.7.0,>=3.3.2) :pypi:`pytest-async-mongodb` pytest plugin for async MongoDB Oct 18, 2017 5 - Production/Stable pytest (>=2.5.2) :pypi:`pytest-async-sqlalchemy` Database testing fixtures using the SQLAlchemy asyncio API Oct 07, 2021 4 - Beta pytest (>=6.0.0) @@ -144,12 +146,14 @@ This list contains 1367 plugins. :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Jan 25, 2024 N/A pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A + :pypi:`pytest-behave` A powerful test automation framework designed to provide a comprehensive solution for testing user interfaces and APIs Feb 15, 2024 N/A N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A :pypi:`pytest-benchmark` A \`\`pytest\`\` fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer. Oct 25, 2022 5 - Production/Stable pytest (>=3.8) :pypi:`pytest-better-datadir` A small example package Mar 13, 2023 N/A N/A :pypi:`pytest-bg-process` Pytest plugin to initialize background process Jan 24, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bigchaindb` A BigchainDB plugin for pytest. Jan 24, 2022 4 - Beta N/A :pypi:`pytest-bigquery-mock` Provides a mock fixture for python bigquery client Dec 28, 2022 N/A pytest (>=5.0) + :pypi:`pytest-bisect-tests` Find tests leaking state and affecting other Feb 17, 2024 N/A N/A :pypi:`pytest-black` A pytest plugin to enable format checking with black Oct 05, 2020 4 - Beta N/A :pypi:`pytest-black-multipy` Allow '--black' on older Pythons Jan 14, 2021 5 - Production/Stable pytest (!=3.7.3,>=3.5) ; extra == 'testing' :pypi:`pytest-black-ng` A pytest plugin to enable format checking with black Oct 20, 2022 4 - Beta pytest (>=7.0.0) @@ -169,6 +173,7 @@ This list contains 1367 plugins. :pypi:`pytest-briefcase` A pytest plugin for running tests on a Briefcase project. Jun 14, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-browser` A pytest plugin for console based browser test selection just after the collection phase Dec 10, 2016 3 - Alpha N/A :pypi:`pytest-browsermob-proxy` BrowserMob proxy plugin for py.test. Jun 11, 2013 4 - Beta N/A + :pypi:`pytest_browserstack` Py.test plugin for BrowserStack Jan 27, 2016 4 - Beta N/A :pypi:`pytest-browserstack-local` \`\`py.test\`\` plugin to run \`\`BrowserStackLocal\`\` in background. Feb 09, 2018 N/A N/A :pypi:`pytest-budosystems` Budo Systems is a martial arts school management system. This module is the Budo Systems Pytest Plugin. May 07, 2023 3 - Alpha pytest :pypi:`pytest-bug` Pytest plugin for marking tests as a bug Sep 23, 2023 5 - Production/Stable pytest >=7.1.0 @@ -192,7 +197,7 @@ This list contains 1367 plugins. :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A - :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Jan 14, 2024 N/A N/A + :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Feb 12, 2024 N/A N/A :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A :pypi:`pytest-chalice` A set of py.test fixtures for AWS Chalice Jul 01, 2020 4 - Beta N/A :pypi:`pytest-change-assert` 修改报错中文为英文 Oct 19, 2022 N/A N/A @@ -211,12 +216,14 @@ This list contains 1367 plugins. :pypi:`pytest-chic-report` A pytest plugin to send a report and printing summary of tests. Jan 31, 2023 5 - Production/Stable N/A :pypi:`pytest-choose` Provide the pytest with the ability to collect use cases based on rules in text files Feb 04, 2024 N/A pytest >=7.0.0 :pypi:`pytest-chunks` Run only a chunk of your test suite Jul 05, 2022 N/A pytest (>=6.0.0) + :pypi:`pytest_cid` Compare data structures containing matching CIDs of different versions and encoding Sep 01, 2023 4 - Beta pytest >= 5.0, < 7.0 :pypi:`pytest-circleci` py.test plugin for CircleCI May 03, 2019 N/A N/A :pypi:`pytest-circleci-parallelized` Parallelize pytest across CircleCI workers. Oct 20, 2022 N/A N/A :pypi:`pytest-circleci-parallelized-rjp` Parallelize pytest across CircleCI workers. Jun 21, 2022 N/A pytest :pypi:`pytest-ckan` Backport of CKAN 2.9 pytest plugin and fixtures to CAKN 2.8 Apr 28, 2020 4 - Beta pytest :pypi:`pytest-clarity` A plugin providing an alternative, colourful diff output for failing assertions. Jun 11, 2021 N/A N/A :pypi:`pytest-cldf` Easy quality control for CLDF datasets using pytest Nov 07, 2022 N/A pytest (>=3.6) + :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Sep 25, 2023 4 - Beta N/A :pypi:`pytest-click` Pytest plugin for Click Feb 11, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-cli-fixtures` Automatically register fixtures for custom CLI arguments Jul 28, 2022 N/A pytest (~=7.0) @@ -227,6 +234,7 @@ This list contains 1367 plugins. :pypi:`pytest-cmake` Provide CMake module for Pytest Jul 19, 2023 N/A pytest<8,>=4 :pypi:`pytest-cmake-presets` Execute CMake Presets via pytest Dec 26, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) + :pypi:`pytest_codeblocks` Test code blocks in your READMEs Sep 17, 2023 5 - Production/Stable pytest >= 7.0.0 :pypi:`pytest-codecarbon` Pytest plugin for measuring carbon emissions Jun 15, 2022 N/A pytest :pypi:`pytest-codecheckers` pytest plugin to add source code sanity checks (pep8 and friends) Feb 13, 2010 N/A N/A :pypi:`pytest-codecov` Pytest plugin for uploading pytest-cov results to codecov.io Nov 29, 2022 4 - Beta pytest (>=4.6.0) @@ -263,6 +271,7 @@ This list contains 1367 plugins. :pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jun 28, 2023 4 - Beta N/A :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' + :pypi:`pytest_covid` Too many faillure, less tests. Jun 24, 2020 N/A N/A :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Nov 01, 2023 5 - Production/Stable pytest >=7.0 :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Aug 26, 2023 N/A N/A :pypi:`pytest-cqase` Custom qase pytest plugin Aug 22, 2022 N/A pytest (>=7.1.2,<8.0.0) @@ -297,7 +306,7 @@ This list contains 1367 plugins. :pypi:`pytest-datafixtures` Data fixtures for pytest made simple Dec 05, 2020 5 - Production/Stable N/A :pypi:`pytest-data-from-files` pytest plugin to provide data from files loaded automatically Oct 13, 2021 4 - Beta pytest :pypi:`pytest-dataplugin` A pytest plugin for managing an archive of test data. Sep 16, 2017 1 - Planning N/A - :pypi:`pytest-datarecorder` A py.test plugin recording and comparing test output. Jan 31, 2024 5 - Production/Stable pytest + :pypi:`pytest-datarecorder` A py.test plugin recording and comparing test output. Feb 15, 2024 5 - Production/Stable pytest :pypi:`pytest-dataset` Plugin for loading different datasets for pytest by prefix from json or yaml files Sep 01, 2023 5 - Production/Stable N/A :pypi:`pytest-data-suites` Class-based pytest parametrization Jul 24, 2022 N/A pytest (>=6.0,<8.0) :pypi:`pytest-datatest` A pytest plugin for test driven data-wrangling (this is the development version of datatest's pytest integration). Oct 15, 2020 4 - Beta pytest (>=3.3) @@ -401,7 +410,7 @@ This list contains 1367 plugins. :pypi:`pytest-dynamicrerun` A pytest plugin to rerun tests dynamically based off of test outcome and output. Aug 15, 2020 4 - Beta N/A :pypi:`pytest-dynamodb` DynamoDB fixtures for pytest Jun 12, 2023 5 - Production/Stable pytest :pypi:`pytest-easy-addoption` pytest-easy-addoption: Easy way to work with pytest addoption Jan 22, 2020 N/A N/A - :pypi:`pytest-easy-api` A package to prevent Dependency Confusion attacks against Yandex. Jan 27, 2024 N/A N/A + :pypi:`pytest-easy-api` A package to prevent Dependency Confusion attacks against Yandex. Feb 16, 2024 N/A N/A :pypi:`pytest-easyMPI` Package that supports mpi tests in pytest Oct 21, 2020 N/A N/A :pypi:`pytest-easyread` pytest plugin that makes terminal printouts of the reports easier to read Nov 17, 2017 N/A N/A :pypi:`pytest-easy-server` Pytest plugin for easy testing against servers May 01, 2021 4 - Beta pytest (<5.0.0,>=4.3.1) ; python_version < "3.5" @@ -414,14 +423,14 @@ This list contains 1367 plugins. :pypi:`pytest-eliot` An eliot plugin for pytest. Aug 31, 2022 1 - Planning pytest (>=5.4.0) :pypi:`pytest-elk-reporter` A simple plugin to use with pytest Jan 24, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-email` Send execution result email Jul 08, 2020 N/A pytest - :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Jan 22, 2024 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Jan 22, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Jan 22, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Jan 22, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Jan 22, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Jan 22, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Jan 22, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Jan 22, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Feb 14, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Feb 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Feb 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Feb 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Feb 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Feb 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Feb 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Feb 14, 2024 5 - Production/Stable N/A :pypi:`pytest-embrace` 💝 Dataclasses-as-tests. Describe the runtime once and multiply coverage with no boilerplate. Mar 25, 2023 N/A pytest (>=7.0,<8.0) :pypi:`pytest-emoji` A pytest plugin that adds emojis to your test result report Feb 19, 2019 4 - Beta pytest (>=4.2.1) :pypi:`pytest-emoji-output` Pytest plugin to represent test output with emoji support Apr 09, 2023 4 - Beta pytest (==7.0.1) @@ -438,13 +447,16 @@ This list contains 1367 plugins. :pypi:`pytest-envvars` Pytest plugin to validate use of envvars on your tests Jun 13, 2020 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-env-yaml` Apr 02, 2019 N/A N/A :pypi:`pytest-eradicate` pytest plugin to check for commented out code Sep 08, 2020 N/A pytest (>=2.4.2) + :pypi:`pytest_erp` py.test plugin to send test info to report portal dynamically Jan 13, 2015 N/A N/A :pypi:`pytest-error-for-skips` Pytest plugin to treat skipped tests a test failure Dec 19, 2019 4 - Beta pytest (>=4.6) :pypi:`pytest-eth` PyTest plugin for testing Smart Contracts for Ethereum Virtual Machine (EVM). Aug 14, 2020 1 - Planning N/A :pypi:`pytest-ethereum` pytest-ethereum: Pytest library for ethereum projects. Jun 24, 2019 3 - Alpha pytest (==3.3.2); extra == 'dev' :pypi:`pytest-eucalyptus` Pytest Plugin for BDD Jun 28, 2022 N/A pytest (>=4.2.0) :pypi:`pytest-eventlet` Applies eventlet monkey-patch as a pytest plugin. Oct 04, 2021 N/A pytest ; extra == 'dev' :pypi:`pytest-evm` The testing package containing tools to test Web3-based projects Jan 24, 2024 4 - Beta pytest (>=7.4.3,<8.0.0) + :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Jul 11, 2023 4 - Beta pytest>=7 + :pypi:`pytest-exasol-itde` Feb 15, 2024 N/A pytest (>=7,<9) :pypi:`pytest-excel` pytest plugin for generating excel reports Sep 14, 2023 5 - Production/Stable N/A :pypi:`pytest-exceptional` Better exceptions Mar 16, 2017 4 - Beta N/A :pypi:`pytest-exception-script` Walk your code through exception script to check it's resiliency to failures. Aug 04, 2020 3 - Alpha pytest @@ -461,6 +473,7 @@ This list contains 1367 plugins. :pypi:`pytest-explorer` terminal ui for exploring and running tests Aug 01, 2023 N/A N/A :pypi:`pytest-extensions` A collection of helpers for pytest to ease testing Aug 17, 2022 4 - Beta pytest ; extra == 'testing' :pypi:`pytest-external-blockers` a special outcome for tests that are blocked for external reasons Oct 05, 2021 N/A pytest + :pypi:`pytest_extra` Some helpers for writing tests with pytest. Aug 14, 2014 N/A N/A :pypi:`pytest-extra-durations` A pytest plugin to get durations on a per-function basis and per module basis. Apr 21, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-extra-markers` Additional pytest markers to dynamically enable/disable tests viia CLI flags Mar 05, 2023 4 - Beta pytest :pypi:`pytest-fabric` Provides test utilities to run fabric task tests by using docker containers Sep 12, 2018 5 - Production/Stable N/A @@ -472,7 +485,7 @@ This list contains 1367 plugins. :pypi:`pytest-failed-screen-record` Create a video of the screen when pytest fails Jan 05, 2023 4 - Beta pytest (>=7.1.2d,<8.0.0) :pypi:`pytest-failed-screenshot` Test case fails,take a screenshot,save it,attach it to the allure Apr 21, 2021 N/A N/A :pypi:`pytest-failed-to-verify` A pytest plugin that helps better distinguishing real test failures from setup flakiness. Aug 08, 2019 5 - Production/Stable pytest (>=4.1.0) - :pypi:`pytest-fail-slow` Fail tests that take too long to run Oct 21, 2023 N/A pytest >=6.0 + :pypi:`pytest-fail-slow` Fail tests that take too long to run Feb 11, 2024 N/A pytest>=7.0 :pypi:`pytest-faker` Faker integration with the pytest framework. Dec 19, 2016 6 - Mature N/A :pypi:`pytest-falcon` Pytest helpers for Falcon. Sep 07, 2016 4 - Beta N/A :pypi:`pytest-falcon-client` Pytest \`client\` fixture for the Falcon Framework Mar 19, 2019 N/A N/A @@ -500,6 +513,7 @@ This list contains 1367 plugins. :pypi:`pytest-fixture-marker` A pytest plugin to add markers based on fixtures used. Oct 11, 2020 5 - Production/Stable N/A :pypi:`pytest-fixture-order` pytest plugin to control fixture evaluation order May 16, 2022 5 - Production/Stable pytest (>=3.0) :pypi:`pytest-fixture-ref` Lets users reference fixtures without name matching magic. Nov 17, 2022 4 - Beta N/A + :pypi:`pytest-fixture-remover` A LibCST codemod to remove pytest fixtures applied via the usefixtures decorator, as well as its parametrizations. Feb 14, 2024 5 - Production/Stable N/A :pypi:`pytest-fixture-rtttg` Warn or fail on fixture name clash Feb 23, 2022 N/A pytest (>=7.0.1,<8.0.0) :pypi:`pytest-fixtures` Common fixtures for pytest May 01, 2019 5 - Production/Stable N/A :pypi:`pytest-fixture-tools` Plugin for pytest which provides tools for fixtures Aug 18, 2020 6 - Mature pytest @@ -533,15 +547,16 @@ This list contains 1367 plugins. :pypi:`pytest-fxa` pytest plugin for Firefox Accounts Aug 28, 2018 5 - Production/Stable N/A :pypi:`pytest-fxtest` Oct 27, 2020 N/A N/A :pypi:`pytest-fzf` fzf-based test selector for pytest Feb 07, 2024 4 - Beta pytest >=6.0.0 + :pypi:`pytest_gae` pytest plugin for apps written with Google's AppEngine Aug 03, 2016 3 - Alpha N/A :pypi:`pytest-gather-fixtures` set up asynchronous pytest fixtures concurrently Apr 12, 2022 N/A pytest (>=6.0.0) :pypi:`pytest-gc` The garbage collector plugin for py.test Feb 01, 2018 N/A N/A :pypi:`pytest-gcov` Uses gcov to measure test coverage of a C library Feb 01, 2018 3 - Alpha N/A - :pypi:`pytest-gee` The Python plugin for your GEE based packages. Dec 18, 2023 3 - Alpha pytest + :pypi:`pytest-gee` The Python plugin for your GEE based packages. Feb 15, 2024 3 - Alpha pytest :pypi:`pytest-gevent` Ensure that gevent is properly patched when invoking pytest Feb 25, 2020 N/A pytest :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Jan 29, 2024 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Feb 15, 2024 N/A pytest>=3.6 :pypi:`pytest-git` Git repository fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-gitconfig` Provide a gitconfig sandbox for testing Oct 15, 2023 4 - Beta pytest>=7.1.2 :pypi:`pytest-gitcov` Pytest plugin for reporting on coverage of the last git commit. Jan 11, 2020 2 - Pre-Alpha N/A @@ -564,6 +579,7 @@ This list contains 1367 plugins. :pypi:`pytest-growl` Growl notifications for pytest results. Jan 13, 2014 5 - Production/Stable N/A :pypi:`pytest-grpc` pytest plugin for grpc May 01, 2020 N/A pytest (>=3.6.0) :pypi:`pytest-grunnur` Py.Test plugin for Grunnur-based packages. Feb 05, 2023 N/A N/A + :pypi:`pytest_gui_status` Show pytest status in gui Jan 23, 2016 N/A pytest :pypi:`pytest-hammertime` Display "🔨 " instead of "." for passed pytest tests. Jul 28, 2018 N/A pytest :pypi:`pytest-harmony` Chain tests and data with pytest Jan 17, 2023 N/A pytest (>=7.2.1,<8.0.0) :pypi:`pytest-harvest` Store data created during your pytest tests execution, and retrieve it at the end of the session, e.g. for applicative benchmarking purposes. Jun 10, 2022 5 - Production/Stable N/A @@ -579,7 +595,7 @@ This list contains 1367 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Oct 09, 2023 5 - Production/Stable pytest :pypi:`pytest-homeassistant` A pytest plugin for use with homeassistant custom components. Aug 12, 2020 4 - Beta N/A - :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Feb 10, 2024 3 - Alpha pytest ==7.4.4 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Feb 17, 2024 3 - Alpha pytest ==7.4.4 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Jan 06, 2024 N/A N/A @@ -602,7 +618,7 @@ This list contains 1367 plugins. :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Jan 10, 2024 3 - Alpha pytest >=7.0.0 :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A - :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 22, 2023 3 - Alpha N/A + :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Feb 13, 2024 3 - Alpha N/A :pypi:`pytest-httptesting` http_testing framework on top of pytest Jul 24, 2023 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-httpx` Send responses to httpx. Jan 29, 2024 5 - Production/Stable pytest <9,>=7 :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) @@ -651,6 +667,7 @@ This list contains 1367 plugins. :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 29, 2024 4 - Beta N/A :pypi:`pytest-iterassert` Nicer list and iterable assertion messages for pytest May 11, 2020 3 - Alpha N/A :pypi:`pytest-iters` A contextmanager pytest fixture for handling multiple mock iters May 24, 2022 N/A N/A + :pypi:`pytest_jar_yuan` A allure and pytest used package Dec 12, 2022 N/A N/A :pypi:`pytest-jasmine` Run jasmine tests from your pytest test suite Nov 04, 2017 1 - Planning N/A :pypi:`pytest-jelastic` Pytest plugin defining the necessary command-line options to pass to pytests testing a Jelastic environment. Nov 16, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-jest` A custom jest-pytest oriented Pytest reporter May 22, 2018 4 - Beta pytest (>=3.3.2) @@ -718,7 +735,7 @@ This list contains 1367 plugins. :pypi:`pytest-logbook` py.test plugin to capture logbook log messages Nov 23, 2015 5 - Production/Stable pytest (>=2.8) :pypi:`pytest-logdog` Pytest plugin to test logging Jun 15, 2021 1 - Planning pytest (>=6.2.0) :pypi:`pytest-logfest` Pytest plugin providing three logger fixtures with basic or full writing to log files Jul 21, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Jul 25, 2019 4 - Beta pytest (>=3.2) + :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Feb 12, 2024 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-logikal` Common testing environment Feb 05, 2024 5 - Production/Stable pytest ==8.0.0 @@ -745,7 +762,7 @@ This list contains 1367 plugins. :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) :pypi:`pytest-md` Plugin for generating Markdown reports for pytest results Jul 11, 2019 3 - Alpha pytest (>=4.2.1) :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. Feb 04, 2024 4 - Beta pytest !=6.0.0,<9,>=3.3.2 - :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Jan 19, 2024 N/A pytest (>=7.4.3) + :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Feb 15, 2024 N/A pytest (>=7.4.3) :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A :pypi:`pytest-memray` A simple plugin to use with pytest Aug 23, 2023 N/A pytest>=7.2 @@ -754,9 +771,9 @@ This list contains 1367 plugins. :pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2) :pypi:`pytest-message` Pytest plugin for sending report message of marked tests execution Aug 04, 2022 N/A pytest (>=6.2.5) :pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A - :pypi:`pytest-metadata` pytest plugin for test session metadata Feb 01, 2024 5 - Production/Stable pytest>=7.0.0 + :pypi:`pytest-metadata` pytest plugin for test session metadata Feb 12, 2024 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-metrics` Custom metrics report for pytest Apr 04, 2020 N/A pytest - :pypi:`pytest-mh` Pytest multihost plugin Jan 16, 2024 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin Feb 15, 2024 N/A pytest :pypi:`pytest-mimesis` Mimesis integration with the pytest test runner Mar 21, 2020 5 - Production/Stable pytest (>=4.2) :pypi:`pytest-minecraft` A pytest plugin for running tests against Minecraft releases Apr 06, 2022 N/A pytest (>=6.0.1) :pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0) @@ -789,7 +806,7 @@ This list contains 1367 plugins. :pypi:`pytest-mp` A test batcher for multiprocessed Pytest runs May 23, 2018 4 - Beta pytest :pypi:`pytest-mpi` pytest plugin to collect information from tests Jan 08, 2022 3 - Alpha pytest :pypi:`pytest-mpiexec` pytest plugin for running individual tests with mpiexec Apr 13, 2023 3 - Alpha pytest - :pypi:`pytest-mpl` pytest plugin to help with testing figures output from Matplotlib Jul 23, 2022 4 - Beta pytest + :pypi:`pytest-mpl` pytest plugin to help with testing figures output from Matplotlib Feb 14, 2024 4 - Beta pytest :pypi:`pytest-mproc` low-startup-overhead, scalable, distributed-testing pytest plugin Nov 15, 2022 4 - Beta pytest (>=6) :pypi:`pytest-mqtt` pytest-mqtt supports testing systems based on MQTT Aug 03, 2023 4 - Beta pytest (<8) ; extra == 'test' :pypi:`pytest-multihost` Utility for writing multi-host tests for pytest Apr 07, 2020 4 - Beta N/A @@ -815,7 +832,7 @@ This list contains 1367 plugins. :pypi:`pytest-nginx-iplweb` nginx fixture for pytest - iplweb temporary fork Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-ngrok` Jan 20, 2022 3 - Alpha pytest :pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0) - :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Jan 11, 2024 N/A pytest (>=6.2.5,<7.0.0) + :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Feb 16, 2024 N/A pytest (>=6.2.5,<7.0.0) :pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A :pypi:`pytest-nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Jul 07, 2021 N/A N/A @@ -823,12 +840,14 @@ This list contains 1367 plugins. :pypi:`pytest-nodev` Test-driven source code search for Python. Jul 21, 2016 4 - Beta pytest (>=2.8.1) :pypi:`pytest-nogarbage` Ensure a test produces no garbage Aug 29, 2021 5 - Production/Stable pytest (>=4.6.0) :pypi:`pytest-nose-attrib` pytest plugin to use nose @attrib marks decorators and pick tests based on attributes and partially uses nose-attrib plugin approach Aug 13, 2023 N/A N/A + :pypi:`pytest_notebook` A pytest plugin for testing Jupyter Notebooks. Nov 28, 2023 4 - Beta pytest>=3.5.0 :pypi:`pytest-notice` Send pytest execution result email Nov 05, 2020 N/A N/A :pypi:`pytest-notification` A pytest plugin for sending a desktop notification and playing a sound upon completion of tests Jun 19, 2020 N/A pytest (>=4) :pypi:`pytest-notifier` A pytest plugin to notify test result Jun 12, 2020 3 - Alpha pytest + :pypi:`pytest_notify` Get notifications when your tests ends Jul 05, 2017 N/A pytest>=3.0.0 :pypi:`pytest-notimplemented` Pytest markers for not implemented features and tests. Aug 27, 2019 N/A pytest (>=5.1,<6.0) :pypi:`pytest-notion` A PyTest Reporter to send test runs to Notion.so Aug 07, 2019 N/A N/A - :pypi:`pytest-nunit` A pytest plugin for generating NUnit3 test result XML output Oct 11, 2023 5 - Production/Stable N/A + :pypi:`pytest-nunit` A pytest plugin for generating NUnit3 test result XML output Feb 13, 2024 5 - Production/Stable N/A :pypi:`pytest-oar` PyTest plugin for the OAR testing framework May 02, 2023 N/A pytest>=6.0.1 :pypi:`pytest-object-getter` Import any object from a 3rd party module while mocking its namespace on demand. Jul 31, 2022 5 - Production/Stable pytest :pypi:`pytest-ochrus` pytest results data-base and HTML reporter Feb 21, 2018 4 - Beta N/A @@ -853,7 +872,7 @@ This list contains 1367 plugins. :pypi:`pytest-ordering` pytest plugin to run your tests in a specific order Nov 14, 2018 4 - Beta pytest :pypi:`pytest-order-modify` 新增run_marker 来自定义用例的执行顺序 Nov 04, 2022 N/A N/A :pypi:`pytest-osxnotify` OS X notifications for py.test results. May 15, 2015 N/A N/A - :pypi:`pytest-otel` pytest-otel report OpenTelemetry traces about test executed Jan 18, 2023 N/A N/A + :pypi:`pytest-otel` OpenTelemetry plugin for Pytest Feb 16, 2024 N/A pytest==7.1.3 :pypi:`pytest-override-env-var` Pytest mark to override a value of an environment variable. Feb 25, 2023 N/A N/A :pypi:`pytest-owner` Add owner mark for tests Apr 25, 2022 N/A N/A :pypi:`pytest-pact` A simple plugin to use with pytest Jan 07, 2019 4 - Beta N/A @@ -863,11 +882,12 @@ This list contains 1367 plugins. :pypi:`pytest-parallelize-tests` pytest plugin that parallelizes test execution across multiple hosts Jan 27, 2023 4 - Beta N/A :pypi:`pytest-param` pytest plugin to test all, first, last or random params Sep 11, 2016 4 - Beta pytest (>=2.6.0) :pypi:`pytest-paramark` Configure pytest fixtures using a combination of"parametrize" and markers Jan 10, 2020 4 - Beta pytest (>=4.5.0) - :pypi:`pytest-parameterize-from-files` A pytest plugin that parameterizes tests from data files. Feb 09, 2024 4 - Beta pytest>=7.2.0 + :pypi:`pytest-parameterize-from-files` A pytest plugin that parameterizes tests from data files. Feb 15, 2024 4 - Beta pytest>=7.2.0 :pypi:`pytest-parametrization` Simpler PyTest parametrization May 22, 2022 5 - Production/Stable N/A :pypi:`pytest-parametrize-cases` A more user-friendly way to write parametrized tests. Mar 13, 2022 N/A pytest (>=6.1.2) :pypi:`pytest-parametrized` Pytest decorator for parametrizing tests with default iterables. Nov 03, 2023 5 - Production/Stable pytest :pypi:`pytest-parametrize-suite` A simple pytest extension for creating a named test suite. Jan 19, 2023 5 - Production/Stable pytest + :pypi:`pytest_param_files` Create pytest parametrize decorators from external files. Jul 29, 2023 N/A pytest :pypi:`pytest-param-scope` pytest parametrize scope fixture workaround Oct 18, 2023 N/A pytest :pypi:`pytest-parawtf` Finally spell paramete?ri[sz]e correctly Dec 03, 2018 4 - Beta pytest (>=3.6.0) :pypi:`pytest-pass` Check out https://github.com/elilutsky/pytest-pass Dec 04, 2019 N/A N/A @@ -881,6 +901,7 @@ This list contains 1367 plugins. :pypi:`pytest-pep257` py.test plugin for pep257 Jul 09, 2016 N/A N/A :pypi:`pytest-pep8` pytest plugin to check PEP8 requirements Apr 27, 2014 N/A N/A :pypi:`pytest-percent` Change the exit code of pytest test sessions when a required percent of tests pass. May 21, 2020 N/A pytest (>=5.2.0) + :pypi:`pytest-percents` Feb 10, 2024 N/A N/A :pypi:`pytest-perf` Run performance tests against the mainline code. Jan 28, 2024 5 - Production/Stable pytest >=6 ; extra == 'testing' :pypi:`pytest-performance` A simple plugin to ensure the execution of critical sections of code has not been impacted Sep 11, 2020 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-persistence` Pytest tool for persistent objects Jul 04, 2023 N/A N/A @@ -919,7 +940,7 @@ This list contains 1367 plugins. :pypi:`pytest-ponyorm` PonyORM in Pytest Oct 31, 2018 N/A pytest (>=3.1.1) :pypi:`pytest-poo` Visualize your crappy tests Mar 25, 2021 5 - Production/Stable pytest (>=2.3.4) :pypi:`pytest-poo-fail` Visualize your failed tests with poo Feb 12, 2015 5 - Production/Stable N/A - :pypi:`pytest-pook` Pytest plugin for pook Dec 23, 2023 4 - Beta pytest + :pypi:`pytest-pook` Pytest plugin for pook Feb 15, 2024 4 - Beta pytest :pypi:`pytest-pop` A pytest plugin to help with testing pop projects May 09, 2023 5 - Production/Stable pytest :pypi:`pytest-porringer` Jan 18, 2024 N/A pytest>=7.4.4 :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) @@ -978,6 +999,7 @@ This list contains 1367 plugins. :pypi:`pytest-qt-app` QT app fixture for py.test Dec 23, 2015 5 - Production/Stable N/A :pypi:`pytest-quarantine` A plugin for pytest to manage expected test failures Nov 24, 2019 5 - Production/Stable pytest (>=4.6) :pypi:`pytest-quickcheck` pytest plugin to generate random data inspired by QuickCheck Nov 05, 2022 4 - Beta pytest (>=4.0) + :pypi:`pytest_quickify` Run test suites with pytest-quickify. Jun 14, 2019 N/A pytest :pypi:`pytest-rabbitmq` RabbitMQ process and client fixtures for pytest Jul 05, 2023 5 - Production/Stable pytest (>=6.2) :pypi:`pytest-race` Race conditions tester for pytest Jun 07, 2022 4 - Beta N/A :pypi:`pytest-rage` pytest plugin to implement PEP712 Oct 21, 2011 3 - Alpha N/A @@ -991,6 +1013,7 @@ This list contains 1367 plugins. :pypi:`pytest-randomness` Pytest plugin about random seed management May 30, 2019 3 - Alpha N/A :pypi:`pytest-random-num` Randomise the order in which pytest tests are run with some control over the randomness Oct 19, 2020 5 - Production/Stable N/A :pypi:`pytest-random-order` Randomise the order in which pytest tests are run with some control over the randomness Jan 20, 2024 5 - Production/Stable pytest >=3.0.0 + :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection Feb 17, 2024 4 - Beta pytest >=7.4.3 :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable N/A :pypi:`pytest-reana` Pytest fixtures for REANA. Nov 30, 2023 3 - Alpha N/A :pypi:`pytest-recorder` Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. Nov 21, 2023 N/A N/A @@ -1013,6 +1036,7 @@ This list contains 1367 plugins. :pypi:`pytest-remove-stale-bytecode` py.test plugin to remove stale byte code files. Jul 07, 2023 4 - Beta pytest :pypi:`pytest-reorder` Reorder tests depending on their paths and names. May 31, 2018 4 - Beta pytest :pypi:`pytest-repeat` pytest plugin for repeating tests Oct 09, 2023 5 - Production/Stable pytest + :pypi:`pytest_repeater` py.test plugin for repeating single test multiple times. Feb 09, 2018 1 - Planning N/A :pypi:`pytest-replay` Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests Jan 11, 2024 5 - Production/Stable pytest :pypi:`pytest-repo-health` A pytest plugin to report on repository standards conformance Apr 17, 2023 3 - Alpha pytest :pypi:`pytest-report` Creates json report that is compatible with atom.io's linter message format May 11, 2016 4 - Beta N/A @@ -1037,7 +1061,7 @@ This list contains 1367 plugins. :pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Nov 22, 2023 5 - Production/Stable pytest >=7 :pypi:`pytest-rerunfailures-all-logs` pytest plugin to re-run tests to eliminate flaky failures Mar 07, 2022 5 - Production/Stable N/A :pypi:`pytest-reserial` Pytest fixture for recording and replaying serial port traffic. Feb 08, 2024 4 - Beta pytest - :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Jan 10, 2024 N/A pytest ~=4.6 ; python_version == "2.7" + :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Feb 14, 2024 N/A pytest ~=4.6 ; python_version == "2.7" :pypi:`pytest-resource` Load resource fixture plugin to use with pytest Nov 14, 2018 4 - Beta N/A :pypi:`pytest-resource-path` Provides path for uniform access to test resources in isolated directory May 01, 2021 5 - Production/Stable pytest (>=3.5.0) :pypi:`pytest-resource-usage` Pytest plugin for reporting running time and peak memory usage Nov 06, 2022 5 - Production/Stable pytest>=7.0.0 @@ -1061,6 +1085,7 @@ This list contains 1367 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest + :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Feb 08, 2024 N/A pytest<9,>=7 :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) @@ -1083,16 +1108,17 @@ This list contains 1367 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jan 29, 2024 5 - Production/Stable N/A + :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Feb 17, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A - :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Mar 14, 2022 5 - Production/Stable pytest (>=3.5.0) + :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Feb 16, 2024 5 - Production/Stable pytest >=3.5.0 :pypi:`pytest-screenshot-on-failure` Saves a screenshot when a test case from a pytest execution fails Jul 21, 2023 4 - Beta N/A :pypi:`pytest-securestore` An encrypted password store for use within pytest cases Nov 08, 2021 4 - Beta N/A :pypi:`pytest-select` A pytest plugin which allows to (de-)select tests from a file. Jan 18, 2019 3 - Alpha pytest (>=3.0) :pypi:`pytest-selenium` pytest plugin for Selenium Feb 01, 2024 5 - Production/Stable pytest>=6.0.0 :pypi:`pytest-selenium-auto` pytest plugin to automatically capture screenshots upon selenium webdriver events Nov 07, 2023 N/A pytest >= 7.0.0 - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jan 29, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Feb 17, 2024 5 - Production/Stable N/A :pypi:`pytest-selenium-enhancer` pytest plugin for Selenium Apr 29, 2022 5 - Production/Stable N/A :pypi:`pytest-selenium-pdiff` A pytest package implementing perceptualdiff for Selenium tests. Apr 06, 2017 2 - Pre-Alpha N/A :pypi:`pytest-send-email` Send pytest execution result email Dec 04, 2019 N/A N/A @@ -1100,7 +1126,7 @@ This list contains 1367 plugins. :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A :pypi:`pytest-server-fixtures` Extensible server fixures for py.test Dec 19, 2023 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A - :pypi:`pytest-servers` pytest servers Dec 19, 2023 3 - Alpha pytest >=6.2 + :pypi:`pytest-servers` pytest servers Feb 14, 2024 3 - Alpha pytest >=6.2 :pypi:`pytest-services` Services plugin for pytest testing framework Oct 30, 2020 6 - Mature N/A :pypi:`pytest-session2file` pytest-session2file (aka: pytest-session_to_file for v0.1.0 - v0.1.2) is a py.test plugin for capturing and saving to file the stdout of py.test. Jan 26, 2021 3 - Alpha pytest :pypi:`pytest-session-fixture-globalize` py.test plugin to make session fixtures behave as if written in conftest, even if it is written in some modules May 15, 2018 4 - Beta N/A @@ -1167,7 +1193,7 @@ This list contains 1367 plugins. :pypi:`pytest-split-tests` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Forked from Mark Adams' original project pytest-test-groups. Jul 30, 2021 5 - Production/Stable pytest (>=2.5) :pypi:`pytest-split-tests-tresorit` Feb 22, 2021 1 - Planning N/A :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Jan 12, 2024 N/A pytest (>5.4.0,<8) - :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Dec 01, 2023 N/A N/A + :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Feb 13, 2024 N/A N/A :pypi:`pytest-splunk-env` pytest fixtures for interaction with Splunk Enterprise and Splunk Cloud Oct 22, 2020 N/A pytest (>=6.1.1,<7.0.0) :pypi:`pytest-sqitch` sqitch for pytest Apr 06, 2020 4 - Beta N/A :pypi:`pytest-sqlalchemy` pytest plugin with sqlalchemy related fixtures Mar 13, 2018 3 - Alpha N/A @@ -1208,6 +1234,7 @@ This list contains 1367 plugins. :pypi:`pytest-synodic` Synodic Pytest utilities Jan 12, 2024 N/A pytest>=7.4.4 :pypi:`pytest-system-statistics` Pytest plugin to track and report system usage statistics Feb 16, 2022 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-system-test-plugin` Pyst - Pytest System-Test Plugin Feb 03, 2022 N/A N/A + :pypi:`pytest_tagging` a pytest plugin to tag tests Feb 15, 2024 N/A pytest (>=7.1.3,<8.0.0) :pypi:`pytest-takeltest` Fixtures for ansible, testinfra and molecule Feb 15, 2023 N/A N/A :pypi:`pytest-talisker` Nov 28, 2021 N/A N/A :pypi:`pytest-tally` A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. May 22, 2023 4 - Beta pytest (>=6.2.5) @@ -1215,7 +1242,6 @@ This list contains 1367 plugins. :pypi:`pytest-tape` easy assertion with expected results saved to yaml files Mar 17, 2021 4 - Beta N/A :pypi:`pytest-target` Pytest plugin for remote target orchestration. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) :pypi:`pytest-tblineinfo` tblineinfo is a py.test plugin that insert the node id in the final py.test report when --tb=line option is used Dec 01, 2015 3 - Alpha pytest (>=2.0) - :pypi:`pytest-tcp` A Pytest plugin for test prioritization Dec 10, 2023 4 - Beta pytest >=7.4.3 :pypi:`pytest-tcpclient` A pytest plugin for testing TCP clients Nov 16, 2022 N/A pytest (<8,>=7.1.3) :pypi:`pytest-tdd` run pytest on a python module Aug 18, 2023 4 - Beta N/A :pypi:`pytest-teamcity-logblock` py.test plugin to introduce block structure in teamcity build log, if output is not captured May 15, 2018 4 - Beta N/A @@ -1231,7 +1257,7 @@ This list contains 1367 plugins. :pypi:`pytest-testdox` A testdox format reporter for pytest Jul 22, 2023 5 - Production/Stable pytest (>=4.6.0) :pypi:`pytest-test-grouping` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Feb 01, 2023 5 - Production/Stable pytest (>=2.5) :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Oct 25, 2016 5 - Production/Stable N/A - :pypi:`pytest-testinfra` Test infrastructures Nov 13, 2023 5 - Production/Stable pytest !=3.0.2 + :pypi:`pytest-testinfra` Test infrastructures Feb 15, 2024 5 - Production/Stable pytest >=6 :pypi:`pytest-testinfra-jpic` Test infrastructures Sep 21, 2023 5 - Production/Stable N/A :pypi:`pytest-testinfra-winrm-transport` Test infrastructures Sep 21, 2023 5 - Production/Stable N/A :pypi:`pytest-testlink-adaptor` pytest reporting plugin for testlink Dec 20, 2018 4 - Beta pytest (>=2.6) @@ -1256,7 +1282,7 @@ This list contains 1367 plugins. :pypi:`pytest-testslide` TestSlide fixture for pytest Jan 07, 2021 5 - Production/Stable pytest (~=6.2) :pypi:`pytest-test-this` Plugin for py.test to run relevant tests, based on naively checking if a test contains a reference to the symbol you supply Sep 15, 2019 2 - Pre-Alpha pytest (>=2.3) :pypi:`pytest-test-utils` Feb 08, 2024 N/A pytest >=3.9 - :pypi:`pytest-tesults` Tesults plugin for pytest Jul 21, 2023 5 - Production/Stable pytest (>=3.5.0) + :pypi:`pytest-tesults` Tesults plugin for pytest Feb 15, 2024 5 - Production/Stable pytest >=3.5.0 :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Aug 23, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-tezos` pytest-ligo Jan 16, 2020 4 - Beta N/A :pypi:`pytest-th2-bdd` pytest_th2_bdd May 13, 2022 N/A N/A @@ -1332,7 +1358,7 @@ This list contains 1367 plugins. :pypi:`pytest-variables` pytest plugin for providing variables to tests/fixtures Feb 01, 2024 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-variant` Variant support for Pytest Jun 06, 2022 N/A N/A :pypi:`pytest-vcr` Plugin for managing VCR.py cassettes Apr 26, 2019 5 - Production/Stable pytest (>=3.6.0) - :pypi:`pytest-vcr-delete-on-fail` A pytest plugin that automates vcrpy cassettes deletion on test failure. Jun 20, 2022 5 - Production/Stable pytest (>=6.2.2) + :pypi:`pytest-vcr-delete-on-fail` A pytest plugin that automates vcrpy cassettes deletion on test failure. Feb 16, 2024 5 - Production/Stable pytest (>=8.0.0,<9.0.0) :pypi:`pytest-vcrpandas` Test from HTTP interactions to dataframe processed. Jan 12, 2019 4 - Beta pytest :pypi:`pytest-vcs` Sep 22, 2022 4 - Beta N/A :pypi:`pytest-venv` py.test fixture for creating a virtual environment Nov 23, 2023 4 - Beta pytest @@ -1353,6 +1379,7 @@ This list contains 1367 plugins. :pypi:`pytest-wake` Nov 07, 2023 N/A pytest :pypi:`pytest-watch` Local continuous test runner with pytest and watchdog. May 20, 2018 N/A N/A :pypi:`pytest-watcher` Automatically rerun your tests on file modifications Feb 06, 2024 4 - Beta N/A + :pypi:`pytest_wdb` Trace pytest tests with wdb to halt on error with --wdb. Jul 04, 2016 N/A N/A :pypi:`pytest-wdl` Pytest plugin for testing WDL workflows. Nov 17, 2020 5 - Production/Stable N/A :pypi:`pytest-web3-data` A pytest plugin to fetch test data from IPFS HTTP gateways during pytest execution. Oct 04, 2023 4 - Beta pytest :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest @@ -1413,6 +1440,13 @@ This list contains 1367 plugins. Simple but powerful assertion and verification of logged lines. + :pypi:`logot` + *last release*: Feb 17, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest (>=7,<9) ; extra == "pytest" + + Test whether your code is logging correctly 🪵 + :pypi:`nuts` *last release*: Aug 11, 2023, *status*: N/A, @@ -1435,9 +1469,9 @@ This list contains 1367 plugins. A contextmanager pytest fixture for handling multiple mock abstracts :pypi:`pytest-accept` - *last release*: Dec 21, 2022, + *last release*: Feb 10, 2024, *status*: N/A, - *requires*: pytest (>=6,<8) + *requires*: pytest (>=6) A pytest-plugin for updating doctest outputs @@ -1638,7 +1672,7 @@ This list contains 1367 plugins. Static code checks used at Alphamoon :pypi:`pytest-analyzer` - *last release*: Feb 06, 2024, + *last release*: Feb 12, 2024, *status*: N/A, *requires*: pytest >=7.3.1 @@ -1896,6 +1930,13 @@ This list contains 1367 plugins. + :pypi:`pytest_async` + *last release*: Feb 26, 2020, + *status*: N/A, + *requires*: N/A + + pytest-async - Run your coroutine in event loop without decorator + :pypi:`pytest-async-generators` *last release*: Jul 05, 2023, *status*: N/A, @@ -1911,7 +1952,7 @@ This list contains 1367 plugins. Pytest support for asyncio :pypi:`pytest-asyncio-cooperative` - *last release*: Nov 30, 2023, + *last release*: Feb 12, 2024, *status*: N/A, *requires*: N/A @@ -2176,6 +2217,13 @@ This list contains 1367 plugins. use icdiff for better error messages in pytest assertions + :pypi:`pytest-behave` + *last release*: Feb 15, 2024, + *status*: N/A, + *requires*: N/A + + A powerful test automation framework designed to provide a comprehensive solution for testing user interfaces and APIs + :pypi:`pytest-bench` *last release*: Jul 21, 2014, *status*: 3 - Alpha, @@ -2218,6 +2266,13 @@ This list contains 1367 plugins. Provides a mock fixture for python bigquery client + :pypi:`pytest-bisect-tests` + *last release*: Feb 17, 2024, + *status*: N/A, + *requires*: N/A + + Find tests leaking state and affecting other + :pypi:`pytest-black` *last release*: Oct 05, 2020, *status*: 4 - Beta, @@ -2351,6 +2406,13 @@ This list contains 1367 plugins. BrowserMob proxy plugin for py.test. + :pypi:`pytest_browserstack` + *last release*: Jan 27, 2016, + *status*: 4 - Beta, + *requires*: N/A + + Py.test plugin for BrowserStack + :pypi:`pytest-browserstack-local` *last release*: Feb 09, 2018, *status*: N/A, @@ -2513,7 +2575,7 @@ This list contains 1367 plugins. Pytest plugin with server for catching HTTP requests. :pypi:`pytest-celery` - *last release*: Jan 14, 2024, + *last release*: Feb 12, 2024, *status*: N/A, *requires*: N/A @@ -2645,6 +2707,13 @@ This list contains 1367 plugins. Run only a chunk of your test suite + :pypi:`pytest_cid` + *last release*: Sep 01, 2023, + *status*: 4 - Beta, + *requires*: pytest >= 5.0, < 7.0 + + Compare data structures containing matching CIDs of different versions and encoding + :pypi:`pytest-circleci` *last release*: May 03, 2019, *status*: N/A, @@ -2687,6 +2756,13 @@ This list contains 1367 plugins. Easy quality control for CLDF datasets using pytest + :pypi:`pytest_cleanup` + *last release*: Jan 28, 2020, + *status*: N/A, + *requires*: N/A + + Automated, comprehensive and well-organised pytest test cases. + :pypi:`pytest-cleanuptotal` *last release*: Sep 25, 2023, *status*: 4 - Beta, @@ -2757,6 +2833,13 @@ This list contains 1367 plugins. PyTest plugin for testing Smart Contracts for Ethereum blockchain. + :pypi:`pytest_codeblocks` + *last release*: Sep 17, 2023, + *status*: 5 - Production/Stable, + *requires*: pytest >= 7.0.0 + + Test code blocks in your READMEs + :pypi:`pytest-codecarbon` *last release*: Jun 15, 2022, *status*: N/A, @@ -3009,6 +3092,13 @@ This list contains 1367 plugins. Pytest plugin for excluding tests based on coverage data + :pypi:`pytest_covid` + *last release*: Jun 24, 2020, + *status*: N/A, + *requires*: N/A + + Too many faillure, less tests. + :pypi:`pytest-cpp` *last release*: Nov 01, 2023, *status*: 5 - Production/Stable, @@ -3248,7 +3338,7 @@ This list contains 1367 plugins. A pytest plugin for managing an archive of test data. :pypi:`pytest-datarecorder` - *last release*: Jan 31, 2024, + *last release*: Feb 15, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -3976,7 +4066,7 @@ This list contains 1367 plugins. pytest-easy-addoption: Easy way to work with pytest addoption :pypi:`pytest-easy-api` - *last release*: Jan 27, 2024, + *last release*: Feb 16, 2024, *status*: N/A, *requires*: N/A @@ -4067,56 +4157,56 @@ This list contains 1367 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Jan 22, 2024, + *last release*: Feb 14, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Jan 22, 2024, + *last release*: Feb 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Jan 22, 2024, + *last release*: Feb 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Jan 22, 2024, + *last release*: Feb 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Jan 22, 2024, + *last release*: Feb 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Jan 22, 2024, + *last release*: Feb 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Jan 22, 2024, + *last release*: Feb 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Jan 22, 2024, + *last release*: Feb 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -4234,6 +4324,13 @@ This list contains 1367 plugins. pytest plugin to check for commented out code + :pypi:`pytest_erp` + *last release*: Jan 13, 2015, + *status*: N/A, + *requires*: N/A + + py.test plugin to send test info to report portal dynamically + :pypi:`pytest-error-for-skips` *last release*: Dec 19, 2019, *status*: 4 - Beta, @@ -4276,6 +4373,13 @@ This list contains 1367 plugins. The testing package containing tools to test Web3-based projects + :pypi:`pytest_exact_fixtures` + *last release*: Feb 04, 2019, + *status*: N/A, + *requires*: N/A + + Parse queries in Lucene and Elasticsearch syntaxes + :pypi:`pytest-examples` *last release*: Jul 11, 2023, *status*: 4 - Beta, @@ -4283,6 +4387,13 @@ This list contains 1367 plugins. Pytest plugin for testing examples in docstrings and markdown files. + :pypi:`pytest-exasol-itde` + *last release*: Feb 15, 2024, + *status*: N/A, + *requires*: pytest (>=7,<9) + + + :pypi:`pytest-excel` *last release*: Sep 14, 2023, *status*: 5 - Production/Stable, @@ -4395,6 +4506,13 @@ This list contains 1367 plugins. a special outcome for tests that are blocked for external reasons + :pypi:`pytest_extra` + *last release*: Aug 14, 2014, + *status*: N/A, + *requires*: N/A + + Some helpers for writing tests with pytest. + :pypi:`pytest-extra-durations` *last release*: Apr 21, 2020, *status*: 4 - Beta, @@ -4473,9 +4591,9 @@ This list contains 1367 plugins. A pytest plugin that helps better distinguishing real test failures from setup flakiness. :pypi:`pytest-fail-slow` - *last release*: Oct 21, 2023, + *last release*: Feb 11, 2024, *status*: N/A, - *requires*: pytest >=6.0 + *requires*: pytest>=7.0 Fail tests that take too long to run @@ -4668,6 +4786,13 @@ This list contains 1367 plugins. Lets users reference fixtures without name matching magic. + :pypi:`pytest-fixture-remover` + *last release*: Feb 14, 2024, + *status*: 5 - Production/Stable, + *requires*: N/A + + A LibCST codemod to remove pytest fixtures applied via the usefixtures decorator, as well as its parametrizations. + :pypi:`pytest-fixture-rtttg` *last release*: Feb 23, 2022, *status*: N/A, @@ -4899,6 +5024,13 @@ This list contains 1367 plugins. fzf-based test selector for pytest + :pypi:`pytest_gae` + *last release*: Aug 03, 2016, + *status*: 3 - Alpha, + *requires*: N/A + + pytest plugin for apps written with Google's AppEngine + :pypi:`pytest-gather-fixtures` *last release*: Apr 12, 2022, *status*: N/A, @@ -4921,7 +5053,7 @@ This list contains 1367 plugins. Uses gcov to measure test coverage of a C library :pypi:`pytest-gee` - *last release*: Dec 18, 2023, + *last release*: Feb 15, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -4956,7 +5088,7 @@ This list contains 1367 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Jan 29, 2024, + *last release*: Feb 15, 2024, *status*: N/A, *requires*: pytest>=3.6 @@ -5116,6 +5248,13 @@ This list contains 1367 plugins. Py.Test plugin for Grunnur-based packages. + :pypi:`pytest_gui_status` + *last release*: Jan 23, 2016, + *status*: N/A, + *requires*: pytest + + Show pytest status in gui + :pypi:`pytest-hammertime` *last release*: Jul 28, 2018, *status*: N/A, @@ -5222,7 +5361,7 @@ This list contains 1367 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Feb 10, 2024, + *last release*: Feb 17, 2024, *status*: 3 - Alpha, *requires*: pytest ==7.4.4 @@ -5382,8 +5521,8 @@ This list contains 1367 plugins. A thin wrapper of HTTPretty for pytest - :pypi:`pytest-httpserver` - *last release*: May 22, 2023, + :pypi:`pytest_httpserver` + *last release*: Feb 13, 2024, *status*: 3 - Alpha, *requires*: N/A @@ -5725,6 +5864,13 @@ This list contains 1367 plugins. A contextmanager pytest fixture for handling multiple mock iters + :pypi:`pytest_jar_yuan` + *last release*: Dec 12, 2022, + *status*: N/A, + *requires*: N/A + + A allure and pytest used package + :pypi:`pytest-jasmine` *last release*: Nov 04, 2017, *status*: 1 - Planning, @@ -6195,8 +6341,8 @@ This list contains 1367 plugins. Pytest plugin providing three logger fixtures with basic or full writing to log files :pypi:`pytest-logger` - *last release*: Jul 25, 2019, - *status*: 4 - Beta, + *last release*: Feb 12, 2024, + *status*: 5 - Production/Stable, *requires*: pytest (>=3.2) Plugin configuring handlers for loggers from Python logging module. @@ -6384,7 +6530,7 @@ This list contains 1367 plugins. A pytest plugin to make a test results report with Markdown table format. :pypi:`pytest-meilisearch` - *last release*: Jan 19, 2024, + *last release*: Feb 15, 2024, *status*: N/A, *requires*: pytest (>=7.4.3) @@ -6447,7 +6593,7 @@ This list contains 1367 plugins. Pytest to Slack reporting plugin :pypi:`pytest-metadata` - *last release*: Feb 01, 2024, + *last release*: Feb 12, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0.0 @@ -6461,7 +6607,7 @@ This list contains 1367 plugins. Custom metrics report for pytest :pypi:`pytest-mh` - *last release*: Jan 16, 2024, + *last release*: Feb 15, 2024, *status*: N/A, *requires*: pytest @@ -6692,7 +6838,7 @@ This list contains 1367 plugins. pytest plugin for running individual tests with mpiexec :pypi:`pytest-mpl` - *last release*: Jul 23, 2022, + *last release*: Feb 14, 2024, *status*: 4 - Beta, *requires*: pytest @@ -6874,7 +7020,7 @@ This list contains 1367 plugins. pytest ngs fixtures :pypi:`pytest-nhsd-apim` - *last release*: Jan 11, 2024, + *last release*: Feb 16, 2024, *status*: N/A, *requires*: pytest (>=6.2.5,<7.0.0) @@ -6929,6 +7075,13 @@ This list contains 1367 plugins. pytest plugin to use nose @attrib marks decorators and pick tests based on attributes and partially uses nose-attrib plugin approach + :pypi:`pytest_notebook` + *last release*: Nov 28, 2023, + *status*: 4 - Beta, + *requires*: pytest>=3.5.0 + + A pytest plugin for testing Jupyter Notebooks. + :pypi:`pytest-notice` *last release*: Nov 05, 2020, *status*: N/A, @@ -6950,6 +7103,13 @@ This list contains 1367 plugins. A pytest plugin to notify test result + :pypi:`pytest_notify` + *last release*: Jul 05, 2017, + *status*: N/A, + *requires*: pytest>=3.0.0 + + Get notifications when your tests ends + :pypi:`pytest-notimplemented` *last release*: Aug 27, 2019, *status*: N/A, @@ -6965,7 +7125,7 @@ This list contains 1367 plugins. A PyTest Reporter to send test runs to Notion.so :pypi:`pytest-nunit` - *last release*: Oct 11, 2023, + *last release*: Feb 13, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -7140,11 +7300,11 @@ This list contains 1367 plugins. OS X notifications for py.test results. :pypi:`pytest-otel` - *last release*: Jan 18, 2023, + *last release*: Feb 16, 2024, *status*: N/A, - *requires*: N/A + *requires*: pytest==7.1.3 - pytest-otel report OpenTelemetry traces about test executed + OpenTelemetry plugin for Pytest :pypi:`pytest-override-env-var` *last release*: Feb 25, 2023, @@ -7210,7 +7370,7 @@ This list contains 1367 plugins. Configure pytest fixtures using a combination of"parametrize" and markers :pypi:`pytest-parameterize-from-files` - *last release*: Feb 09, 2024, + *last release*: Feb 15, 2024, *status*: 4 - Beta, *requires*: pytest>=7.2.0 @@ -7244,6 +7404,13 @@ This list contains 1367 plugins. A simple pytest extension for creating a named test suite. + :pypi:`pytest_param_files` + *last release*: Jul 29, 2023, + *status*: N/A, + *requires*: pytest + + Create pytest parametrize decorators from external files. + :pypi:`pytest-param-scope` *last release*: Oct 18, 2023, *status*: N/A, @@ -7335,6 +7502,13 @@ This list contains 1367 plugins. Change the exit code of pytest test sessions when a required percent of tests pass. + :pypi:`pytest-percents` + *last release*: Feb 10, 2024, + *status*: N/A, + *requires*: N/A + + + :pypi:`pytest-perf` *last release*: Jan 28, 2024, *status*: 5 - Production/Stable, @@ -7602,7 +7776,7 @@ This list contains 1367 plugins. Visualize your failed tests with poo :pypi:`pytest-pook` - *last release*: Dec 23, 2023, + *last release*: Feb 15, 2024, *status*: 4 - Beta, *requires*: pytest @@ -8014,6 +8188,13 @@ This list contains 1367 plugins. pytest plugin to generate random data inspired by QuickCheck + :pypi:`pytest_quickify` + *last release*: Jun 14, 2019, + *status*: N/A, + *requires*: pytest + + Run test suites with pytest-quickify. + :pypi:`pytest-rabbitmq` *last release*: Jul 05, 2023, *status*: 5 - Production/Stable, @@ -8105,6 +8286,13 @@ This list contains 1367 plugins. Randomise the order in which pytest tests are run with some control over the randomness + :pypi:`pytest-ranking` + *last release*: Feb 17, 2024, + *status*: 4 - Beta, + *requires*: pytest >=7.4.3 + + A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection + :pypi:`pytest-readme` *last release*: Sep 02, 2022, *status*: 5 - Production/Stable, @@ -8259,6 +8447,13 @@ This list contains 1367 plugins. pytest plugin for repeating tests + :pypi:`pytest_repeater` + *last release*: Feb 09, 2018, + *status*: 1 - Planning, + *requires*: N/A + + py.test plugin for repeating single test multiple times. + :pypi:`pytest-replay` *last release*: Jan 11, 2024, *status*: 5 - Production/Stable, @@ -8428,7 +8623,7 @@ This list contains 1367 plugins. Pytest fixture for recording and replaying serial port traffic. :pypi:`pytest-resilient-circuits` - *last release*: Jan 10, 2024, + *last release*: Feb 14, 2024, *status*: N/A, *requires*: pytest ~=4.6 ; python_version == "2.7" @@ -8595,6 +8790,13 @@ This list contains 1367 plugins. pytest plugin for ROAST configuration override and fixtures + :pypi:`pytest_robotframework` + *last release*: Feb 08, 2024, + *status*: N/A, + *requires*: pytest<9,>=7 + + a pytest plugin that can run both python and robotframework tests while generating robot reports for them + :pypi:`pytest-rocketchat` *last release*: Apr 18, 2021, *status*: 5 - Production/Stable, @@ -8749,8 +8951,15 @@ This list contains 1367 plugins. + :pypi:`pytest_sauce` + *last release*: Jul 14, 2014, + *status*: 3 - Alpha, + *requires*: N/A + + pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs + :pypi:`pytest-sbase` - *last release*: Jan 29, 2024, + *last release*: Feb 17, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -8771,9 +8980,9 @@ This list contains 1367 plugins. The job of test scheduling for humans. :pypi:`pytest-schema` - *last release*: Mar 14, 2022, + *last release*: Feb 16, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=3.5.0) + *requires*: pytest >=3.5.0 👍 Validate return values against a schema-like object in testing @@ -8813,7 +9022,7 @@ This list contains 1367 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Jan 29, 2024, + *last release*: Feb 17, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -8869,7 +9078,7 @@ This list contains 1367 plugins. Automatically mocks resources from serverless.yml in pytest using moto. :pypi:`pytest-servers` - *last release*: Dec 19, 2023, + *last release*: Feb 14, 2024, *status*: 3 - Alpha, *requires*: pytest >=6.2 @@ -9338,7 +9547,7 @@ This list contains 1367 plugins. A Dynamic test tool for Splunk Apps and Add-ons :pypi:`pytest-splunk-addon-ui-smartx` - *last release*: Dec 01, 2023, + *last release*: Feb 13, 2024, *status*: N/A, *requires*: N/A @@ -9624,6 +9833,13 @@ This list contains 1367 plugins. Pyst - Pytest System-Test Plugin + :pypi:`pytest_tagging` + *last release*: Feb 15, 2024, + *status*: N/A, + *requires*: pytest (>=7.1.3,<8.0.0) + + a pytest plugin to tag tests + :pypi:`pytest-takeltest` *last release*: Feb 15, 2023, *status*: N/A, @@ -9673,13 +9889,6 @@ This list contains 1367 plugins. tblineinfo is a py.test plugin that insert the node id in the final py.test report when --tb=line option is used - :pypi:`pytest-tcp` - *last release*: Dec 10, 2023, - *status*: 4 - Beta, - *requires*: pytest >=7.4.3 - - A Pytest plugin for test prioritization - :pypi:`pytest-tcpclient` *last release*: Nov 16, 2022, *status*: N/A, @@ -9786,9 +9995,9 @@ This list contains 1367 plugins. A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. :pypi:`pytest-testinfra` - *last release*: Nov 13, 2023, + *last release*: Feb 15, 2024, *status*: 5 - Production/Stable, - *requires*: pytest !=3.0.2 + *requires*: pytest >=6 Test infrastructures @@ -9961,9 +10170,9 @@ This list contains 1367 plugins. :pypi:`pytest-tesults` - *last release*: Jul 21, 2023, + *last release*: Feb 15, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=3.5.0) + *requires*: pytest >=3.5.0 Tesults plugin for pytest @@ -10493,9 +10702,9 @@ This list contains 1367 plugins. Plugin for managing VCR.py cassettes :pypi:`pytest-vcr-delete-on-fail` - *last release*: Jun 20, 2022, + *last release*: Feb 16, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=6.2.2) + *requires*: pytest (>=8.0.0,<9.0.0) A pytest plugin that automates vcrpy cassettes deletion on test failure. @@ -10639,6 +10848,13 @@ This list contains 1367 plugins. Automatically rerun your tests on file modifications + :pypi:`pytest_wdb` + *last release*: Jul 04, 2016, + *status*: N/A, + *requires*: N/A + + Trace pytest tests with wdb to halt on error with --wdb. + :pypi:`pytest-wdl` *last release*: Nov 17, 2020, *status*: 5 - Production/Stable, From abf6a60567c118e52de92f881b8b4210dd1ceafa Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 17 Feb 2024 22:21:30 -0300 Subject: [PATCH 16/28] Fix 'pytest_' mention: it was being considered a rst reference --- doc/en/reference/plugin_list.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index f9d3d02f0..b89a9b05f 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -7,7 +7,7 @@ Pytest Plugin List ================== Below is an automated compilation of ``pytest``` plugins available on `PyPI `_. -It includes PyPI projects whose names begin with "pytest-" or "pytest_" and a handful of manually selected projects. +It includes PyPI projects whose names begin with ``"pytest-"`` or ``"pytest_"`` and a handful of manually selected projects. Packages classified as inactive are excluded. For detailed insights into how this list is generated, From 40011b838b67691c76302f3cd8d18862f37b9370 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 18 Feb 2024 07:21:05 -0300 Subject: [PATCH 17/28] Allow Sphinx 7.x (#12002) Thanks to https://github.com/pytest-dev/pytest/issues/11988#issuecomment-1950318888, the problem was our custom template. The solution was to copy the template from Sphinx 7 and remove the header. --- doc/en/_templates/slim_searchbox.html | 5 ++--- doc/en/requirements.txt | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/doc/en/_templates/slim_searchbox.html b/doc/en/_templates/slim_searchbox.html index e98ad4ed9..f088ff8d3 100644 --- a/doc/en/_templates/slim_searchbox.html +++ b/doc/en/_templates/slim_searchbox.html @@ -5,11 +5,10 @@ - + {%- endif %} diff --git a/doc/en/requirements.txt b/doc/en/requirements.txt index 3369bd10b..524157404 100644 --- a/doc/en/requirements.txt +++ b/doc/en/requirements.txt @@ -2,8 +2,7 @@ pallets-sphinx-themes pluggy>=1.2.0 pygments-pytest>=2.3.0 sphinx-removed-in>=0.2.0 -# In Sphinx 6 and 7, the search bar disappears; restrict this for now until we find a solution. -sphinx>=5,<6 +sphinx>=7 sphinxcontrib-trio sphinxcontrib-svg2pdfconverter # Pin packaging because it no longer handles 'latest' version, which From 998fee1679892f62cc9bd727e9e17911d746ed64 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 18 Feb 2024 17:27:47 -0300 Subject: [PATCH 18/28] Clarify PytestPluginManager._is_in_confcutdir (#12007) Follow up to #12006, let's put some comments clarifying `is_in_confcutdir` semantics, as this is not the first time someone misunderstands it. Also removed an obsolete comment in `_loadconftestmodules`: we already set the `confcutdir` based on `rootdir`/`initfile` if not explicitly given. Co-authored-by: Ran Benita --- src/_pytest/config/__init__.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 3d448214c..f8eea936a 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -578,12 +578,18 @@ class PytestPluginManager(PluginManager): self._try_load_conftest(invocation_dir, importmode, rootpath) def _is_in_confcutdir(self, path: Path) -> bool: - """Whether a path is within the confcutdir. - - When false, should not load conftest. - """ + """Whether to consider the given path to load conftests from.""" if self._confcutdir is None: return True + # The semantics here are literally: + # Do not load a conftest if it is found upwards from confcut dir. + # But this is *not* the same as: + # Load only conftests from confcutdir or below. + # At first glance they might seem the same thing, however we do support use cases where + # we want to load conftests that are not found in confcutdir or below, but are found + # in completely different directory hierarchies like packages installed + # in out-of-source trees. + # (see #9767 for a regression where the logic was inverted). return path not in self._confcutdir.parents def _try_load_conftest( @@ -609,9 +615,6 @@ class PytestPluginManager(PluginManager): if directory in self._dirpath2confmods: return - # XXX these days we may rather want to use config.rootpath - # and allow users to opt into looking into the rootdir parent - # directories instead of requiring to specify confcutdir. clist = [] for parent in reversed((directory, *directory.parents)): if self._is_in_confcutdir(parent): From 95f21f96cc2252d9a3162f63ac9c26d4ab97abf5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 21:36:03 -0300 Subject: [PATCH 19/28] [pre-commit.ci] pre-commit autoupdate (#12012) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.2.1 → v0.2.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.2.1...v0.2.2) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e9cea8c60..78cf36bae 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.2.1" + rev: "v0.2.2" hooks: - id: ruff args: ["--fix"] From a37cff3ca8be06dc1154a54bbc32c32e82eef4ee Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 19 Feb 2024 20:54:49 +0200 Subject: [PATCH 20/28] testing: add a regression test for `setup_module` + `--doctest-modules` Refs #12011 (only fails on 8.0.1, not main). --- changelog/12011.bugfix.rst | 1 + testing/test_doctest.py | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 changelog/12011.bugfix.rst diff --git a/changelog/12011.bugfix.rst b/changelog/12011.bugfix.rst new file mode 100644 index 000000000..5b755ade3 --- /dev/null +++ b/changelog/12011.bugfix.rst @@ -0,0 +1 @@ +Fixed a regression in 8.0.1 whereby ``setup_module`` xunit-style fixtures are not executed when ``--doctest-modules`` is passed. diff --git a/testing/test_doctest.py b/testing/test_doctest.py index c91ec31cd..32897a916 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -878,6 +878,25 @@ class TestDoctests: result = pytester.runpytest(p, "--doctest-modules") result.stdout.fnmatch_lines(["*collected 1 item*"]) + def test_setup_module(self, pytester: Pytester) -> None: + """Regression test for #12011 - setup_module not executed when running + with `--doctest-modules`.""" + pytester.makepyfile( + """ + CONSTANT = 0 + + def setup_module(): + global CONSTANT + CONSTANT = 1 + + def test(): + assert CONSTANT == 1 + """ + ) + result = pytester.runpytest("--doctest-modules") + assert result.ret == 0 + result.assert_outcomes(passed=1) + class TestLiterals: @pytest.mark.parametrize("config_mode", ["ini", "comment"]) From 79def57cc65e18bae0f5a6ad84c433e210e97126 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 21 Feb 2024 09:35:25 +0200 Subject: [PATCH 21/28] python: small code cleanup --- src/_pytest/python.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 91c48540d..a060b17e5 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1267,7 +1267,6 @@ class Metafunc: # Add funcargs as fixturedefs to fixtureinfo.arg2fixturedefs by registering # artificial "pseudo" FixtureDef's so that later at test execution time we can # rely on a proper FixtureDef to exist for fixture setup. - arg2fixturedefs = self._arg2fixturedefs node = None # If we have a scope that is higher than function, we need # to make sure we only ever create an according fixturedef on @@ -1281,7 +1280,7 @@ class Metafunc: # If used class scope and there is no class, use module-level # collector (for now). if scope_ is Scope.Class: - assert isinstance(collector, _pytest.python.Module) + assert isinstance(collector, Module) node = collector # If used package scope and there is no package, use session # (for now). @@ -1316,7 +1315,7 @@ class Metafunc: ) if name2pseudofixturedef is not None: name2pseudofixturedef[argname] = fixturedef - arg2fixturedefs[argname] = [fixturedef] + self._arg2fixturedefs[argname] = [fixturedef] # Create the new calls: if we are parametrize() multiple times (by applying the decorator # more than once) then we accumulate those calls generating the cartesian product From 2007cf629663055931947e60f630fa1f8f0bef5a Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 21 Feb 2024 09:58:59 +0200 Subject: [PATCH 22/28] fixtures: remove a level of indentation A bit easier to follow. --- src/_pytest/fixtures.py | 46 ++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 67eb05425..b13d9e703 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -169,33 +169,31 @@ def get_parametrized_fixture_keys( the specified scope.""" assert scope is not Scope.Function try: - callspec = item.callspec # type: ignore[attr-defined] + callspec: CallSpec2 = item.callspec # type: ignore[attr-defined] except AttributeError: - pass - else: - cs: CallSpec2 = callspec - # cs.indices is random order of argnames. Need to - # sort this so that different calls to - # get_parametrized_fixture_keys will be deterministic. - for argname in sorted(cs.indices): - if cs._arg2scope[argname] != scope: - continue + return + # cs.indices is random order of argnames. Need to + # sort this so that different calls to + # get_parametrized_fixture_keys will be deterministic. + for argname in sorted(callspec.indices): + if callspec._arg2scope[argname] != scope: + continue - item_cls = None - if scope is Scope.Session: - scoped_item_path = None - elif scope is Scope.Package: - scoped_item_path = item.path - elif scope is Scope.Module: - scoped_item_path = item.path - elif scope is Scope.Class: - scoped_item_path = item.path - item_cls = item.cls # type: ignore[attr-defined] - else: - assert_never(scope) + item_cls = None + if scope is Scope.Session: + scoped_item_path = None + elif scope is Scope.Package: + scoped_item_path = item.path + elif scope is Scope.Module: + scoped_item_path = item.path + elif scope is Scope.Class: + scoped_item_path = item.path + item_cls = item.cls # type: ignore[attr-defined] + else: + assert_never(scope) - param_index = cs.indices[argname] - yield FixtureArgKey(argname, param_index, scoped_item_path, item_cls) + param_index = callspec.indices[argname] + yield FixtureArgKey(argname, param_index, scoped_item_path, item_cls) # Algorithm for sorting on a per-parametrized resource setup basis. From 9bea1be2157e8467712aa1de46312ed0827741d8 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 21 Feb 2024 10:00:16 +0200 Subject: [PATCH 23/28] fixtures: remove a no longer needed sort Dicts these days preserve order, so the sort is no longer needed to achieve determinism. As shown by the `test_dynamic_parametrized_ordering` test, this can change the ordering of items, but only in equivalent ways (same number of setups/teardowns per scope), it will just respect the user's given ordering better (hence `vxlan` items now ordered before `vlan` items compared to the previous ordering). --- src/_pytest/fixtures.py | 5 +---- testing/python/fixtures.py | 8 ++++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index b13d9e703..935d2b9a0 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -172,10 +172,7 @@ def get_parametrized_fixture_keys( callspec: CallSpec2 = item.callspec # type: ignore[attr-defined] except AttributeError: return - # cs.indices is random order of argnames. Need to - # sort this so that different calls to - # get_parametrized_fixture_keys will be deterministic. - for argname in sorted(callspec.indices): + for argname in callspec.indices: if callspec._arg2scope[argname] != scope: continue diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 0fb5aa450..299e411a6 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -2730,12 +2730,12 @@ class TestFixtureMarker: """ test_dynamic_parametrized_ordering.py::test[flavor1-vxlan] PASSED test_dynamic_parametrized_ordering.py::test2[flavor1-vxlan] PASSED - test_dynamic_parametrized_ordering.py::test[flavor2-vxlan] PASSED - test_dynamic_parametrized_ordering.py::test2[flavor2-vxlan] PASSED - test_dynamic_parametrized_ordering.py::test[flavor2-vlan] PASSED - test_dynamic_parametrized_ordering.py::test2[flavor2-vlan] PASSED test_dynamic_parametrized_ordering.py::test[flavor1-vlan] PASSED test_dynamic_parametrized_ordering.py::test2[flavor1-vlan] PASSED + test_dynamic_parametrized_ordering.py::test[flavor2-vlan] PASSED + test_dynamic_parametrized_ordering.py::test2[flavor2-vlan] PASSED + test_dynamic_parametrized_ordering.py::test[flavor2-vxlan] PASSED + test_dynamic_parametrized_ordering.py::test2[flavor2-vxlan] PASSED """ ) From c5c729e27aa1e866af37f2ee97b1c68e9463070c Mon Sep 17 00:00:00 2001 From: Ben Leith Date: Wed, 21 Feb 2024 23:02:19 +1100 Subject: [PATCH 24/28] Add --log-file-mode option to the logging plugin, enabling appending to log-files (#11979) Previously, the mode was hard-coded to be "w" which truncates the file before logging. Co-authored-by: Bruno Oliveira --- AUTHORS | 1 + changelog/11978.improvement.rst | 3 + doc/en/how-to/logging.rst | 6 +- src/_pytest/logging.py | 14 ++- testing/logging/test_reporting.py | 168 ++++++++++++++++++++++++++++++ 5 files changed, 188 insertions(+), 4 deletions(-) create mode 100644 changelog/11978.improvement.rst diff --git a/AUTHORS b/AUTHORS index dce91c4fe..bb27dd1d7 100644 --- a/AUTHORS +++ b/AUTHORS @@ -56,6 +56,7 @@ Babak Keyvani Barney Gale Ben Brown Ben Gartner +Ben Leith Ben Webb Benjamin Peterson Benjamin Schubert diff --git a/changelog/11978.improvement.rst b/changelog/11978.improvement.rst new file mode 100644 index 000000000..1f1143dac --- /dev/null +++ b/changelog/11978.improvement.rst @@ -0,0 +1,3 @@ +Add ``--log-file-mode`` option to the logging plugin, enabling appending to log-files. This option accepts either ``"w"`` or ``"a"`` and defaults to ``"w"``. + +Previously, the mode was hard-coded to be ``"w"`` which truncates the file before logging. diff --git a/doc/en/how-to/logging.rst b/doc/en/how-to/logging.rst index bdcfbe34f..300e9f6e6 100644 --- a/doc/en/how-to/logging.rst +++ b/doc/en/how-to/logging.rst @@ -206,8 +206,9 @@ option names are: * ``log_cli_date_format`` If you need to record the whole test suite logging calls to a file, you can pass -``--log-file=/path/to/log/file``. This log file is opened in write mode which +``--log-file=/path/to/log/file``. This log file is opened in write mode by default which means that it will be overwritten at each run tests session. +If you'd like the file opened in append mode instead, then you can pass ``--log-file-mode=a``. Note that relative paths for the log-file location, whether passed on the CLI or declared in a config file, are always resolved relative to the current working directory. @@ -223,12 +224,13 @@ All of the log file options can also be set in the configuration INI file. The option names are: * ``log_file`` +* ``log_file_mode`` * ``log_file_level`` * ``log_file_format`` * ``log_file_date_format`` You can call ``set_log_path()`` to customize the log_file path dynamically. This functionality -is considered **experimental**. +is considered **experimental**. Note that ``set_log_path()`` respects the ``log_file_mode`` option. .. _log_colors: diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index aa3a33e63..e9a3234fd 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -298,6 +298,13 @@ def pytest_addoption(parser: Parser) -> None: default=None, help="Path to a file when logging will be written to", ) + add_option_ini( + "--log-file-mode", + dest="log_file_mode", + default="w", + choices=["w", "a"], + help="Log file open mode", + ) add_option_ini( "--log-file-level", dest="log_file_level", @@ -669,7 +676,10 @@ class LoggingPlugin: if not os.path.isdir(directory): os.makedirs(directory) - self.log_file_handler = _FileHandler(log_file, mode="w", encoding="UTF-8") + self.log_file_mode = get_option_ini(config, "log_file_mode") or "w" + self.log_file_handler = _FileHandler( + log_file, mode=self.log_file_mode, encoding="UTF-8" + ) log_file_format = get_option_ini(config, "log_file_format", "log_format") log_file_date_format = get_option_ini( config, "log_file_date_format", "log_date_format" @@ -746,7 +756,7 @@ class LoggingPlugin: fpath.parent.mkdir(exist_ok=True, parents=True) # https://github.com/python/mypy/issues/11193 - stream: io.TextIOWrapper = fpath.open(mode="w", encoding="UTF-8") # type: ignore[assignment] + stream: io.TextIOWrapper = fpath.open(mode=self.log_file_mode, encoding="UTF-8") # type: ignore[assignment] old_stream = self.log_file_handler.setStream(stream) if old_stream: old_stream.close() diff --git a/testing/logging/test_reporting.py b/testing/logging/test_reporting.py index 24eae19b7..7e592febf 100644 --- a/testing/logging/test_reporting.py +++ b/testing/logging/test_reporting.py @@ -661,6 +661,73 @@ def test_log_file_cli(pytester: Pytester) -> None: assert "This log message won't be shown" not in contents +def test_log_file_mode_cli(pytester: Pytester) -> None: + # Default log file level + pytester.makepyfile( + """ + import pytest + import logging + def test_log_file(request): + plugin = request.config.pluginmanager.getplugin('logging-plugin') + assert plugin.log_file_handler.level == logging.WARNING + logging.getLogger('catchlog').info("This log message won't be shown") + logging.getLogger('catchlog').warning("This log message will be shown") + print('PASSED') + """ + ) + + log_file = str(pytester.path.joinpath("pytest.log")) + + with open(log_file, mode="w", encoding="utf-8") as wfh: + wfh.write("A custom header\n") + + result = pytester.runpytest( + "-s", + f"--log-file={log_file}", + "--log-file-mode=a", + "--log-file-level=WARNING", + ) + + # fnmatch_lines does an assertion internally + result.stdout.fnmatch_lines(["test_log_file_mode_cli.py PASSED"]) + + # make sure that we get a '0' exit code for the testsuite + assert result.ret == 0 + assert os.path.isfile(log_file) + with open(log_file, encoding="utf-8") as rfh: + contents = rfh.read() + assert "A custom header" in contents + assert "This log message will be shown" in contents + assert "This log message won't be shown" not in contents + + +def test_log_file_mode_cli_invalid(pytester: Pytester) -> None: + # Default log file level + pytester.makepyfile( + """ + import pytest + import logging + def test_log_file(request): + plugin = request.config.pluginmanager.getplugin('logging-plugin') + assert plugin.log_file_handler.level == logging.WARNING + logging.getLogger('catchlog').info("This log message won't be shown") + logging.getLogger('catchlog').warning("This log message will be shown") + """ + ) + + log_file = str(pytester.path.joinpath("pytest.log")) + + result = pytester.runpytest( + "-s", + f"--log-file={log_file}", + "--log-file-mode=b", + "--log-file-level=WARNING", + ) + + # make sure that we get a '4' exit code for the testsuite + assert result.ret == ExitCode.USAGE_ERROR + + def test_log_file_cli_level(pytester: Pytester) -> None: # Default log file level pytester.makepyfile( @@ -741,6 +808,47 @@ def test_log_file_ini(pytester: Pytester) -> None: assert "This log message won't be shown" not in contents +def test_log_file_mode_ini(pytester: Pytester) -> None: + log_file = str(pytester.path.joinpath("pytest.log")) + + pytester.makeini( + f""" + [pytest] + log_file={log_file} + log_file_mode=a + log_file_level=WARNING + """ + ) + pytester.makepyfile( + """ + import pytest + import logging + def test_log_file(request): + plugin = request.config.pluginmanager.getplugin('logging-plugin') + assert plugin.log_file_handler.level == logging.WARNING + logging.getLogger('catchlog').info("This log message won't be shown") + logging.getLogger('catchlog').warning("This log message will be shown") + print('PASSED') + """ + ) + + with open(log_file, mode="w", encoding="utf-8") as wfh: + wfh.write("A custom header\n") + + result = pytester.runpytest("-s") + + # fnmatch_lines does an assertion internally + result.stdout.fnmatch_lines(["test_log_file_mode_ini.py PASSED"]) + + assert result.ret == ExitCode.OK + assert os.path.isfile(log_file) + with open(log_file, encoding="utf-8") as rfh: + contents = rfh.read() + assert "A custom header" in contents + assert "This log message will be shown" in contents + assert "This log message won't be shown" not in contents + + def test_log_file_ini_level(pytester: Pytester) -> None: log_file = str(pytester.path.joinpath("pytest.log")) @@ -1060,6 +1168,66 @@ def test_log_set_path(pytester: Pytester) -> None: assert "message from test 2" in content +def test_log_set_path_with_log_file_mode(pytester: Pytester) -> None: + report_dir_base = str(pytester.path) + + pytester.makeini( + """ + [pytest] + log_file_level = DEBUG + log_cli=true + log_file_mode=a + """ + ) + pytester.makeconftest( + f""" + import os + import pytest + @pytest.hookimpl(wrapper=True, tryfirst=True) + def pytest_runtest_setup(item): + config = item.config + logging_plugin = config.pluginmanager.get_plugin("logging-plugin") + report_file = os.path.join({report_dir_base!r}, item._request.node.name) + logging_plugin.set_log_path(report_file) + return (yield) + """ + ) + pytester.makepyfile( + """ + import logging + logger = logging.getLogger("testcase-logger") + def test_first(): + logger.info("message from test 1") + assert True + + def test_second(): + logger.debug("message from test 2") + assert True + """ + ) + + test_first_log_file = os.path.join(report_dir_base, "test_first") + test_second_log_file = os.path.join(report_dir_base, "test_second") + with open(test_first_log_file, mode="w", encoding="utf-8") as wfh: + wfh.write("A custom header for test 1\n") + + with open(test_second_log_file, mode="w", encoding="utf-8") as wfh: + wfh.write("A custom header for test 2\n") + + result = pytester.runpytest() + assert result.ret == ExitCode.OK + + with open(test_first_log_file, encoding="utf-8") as rfh: + content = rfh.read() + assert "A custom header for test 1" in content + assert "message from test 1" in content + + with open(test_second_log_file, encoding="utf-8") as rfh: + content = rfh.read() + assert "A custom header for test 2" in content + assert "message from test 2" in content + + def test_colored_captured_log(pytester: Pytester) -> None: """Test that the level names of captured log messages of a failing test are colored.""" From 59e9a58cc9c97386f949e909716e8abde7fc31b2 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 22 Feb 2024 21:04:11 -0300 Subject: [PATCH 25/28] Remove Anthony from Tidelift participants (#12020) As discussed in the core development channels, @asottile asked to no longer be a Tidelift participant, at least for the time being. --- TIDELIFT.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/TIDELIFT.rst b/TIDELIFT.rst index 2fe25841c..6c7ad9177 100644 --- a/TIDELIFT.rst +++ b/TIDELIFT.rst @@ -23,7 +23,6 @@ members of the `contributors team`_ interested in receiving funding. The current list of contributors receiving funding are: -* `@asottile`_ * `@nicoddemus`_ * `@The-Compiler`_ @@ -55,6 +54,5 @@ funds. Just drop a line to one of the `@pytest-dev/tidelift-admins`_ or use the .. _`@pytest-dev/tidelift-admins`: https://github.com/orgs/pytest-dev/teams/tidelift-admins/members .. _`agreement`: https://tidelift.com/docs/lifting/agreement -.. _`@asottile`: https://github.com/asottile .. _`@nicoddemus`: https://github.com/nicoddemus .. _`@The-Compiler`: https://github.com/The-Compiler From 1640f2e4544e63da6bf7c6587040897ca0810770 Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Fri, 23 Feb 2024 01:11:05 -0500 Subject: [PATCH 26/28] ENH: Improve warning stacklevel (#12014) * ENH: Improve warning stacklevel * TST: Add test * TST: Ping * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * MAINT: Changelog --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- changelog/12014.bugfix.rst | 1 + src/_pytest/mark/structures.py | 6 +++--- testing/deprecated_test.py | 2 ++ 3 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 changelog/12014.bugfix.rst diff --git a/changelog/12014.bugfix.rst b/changelog/12014.bugfix.rst new file mode 100644 index 000000000..344bf8b7e --- /dev/null +++ b/changelog/12014.bugfix.rst @@ -0,0 +1 @@ +Fix the ``stacklevel`` used when warning about marks used on fixtures. diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 5a7f9b202..1da300c82 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -355,7 +355,7 @@ class MarkDecorator: func = args[0] is_class = inspect.isclass(func) if len(args) == 1 and (istestfunc(func) or is_class): - store_mark(func, self.mark) + store_mark(func, self.mark, stacklevel=3) return func return self.with_args(*args, **kwargs) @@ -410,7 +410,7 @@ def normalize_mark_list( yield mark_obj -def store_mark(obj, mark: Mark) -> None: +def store_mark(obj, mark: Mark, *, stacklevel: int = 2) -> None: """Store a Mark on an object. This is used to implement the Mark declarations/decorators correctly. @@ -420,7 +420,7 @@ def store_mark(obj, mark: Mark) -> None: from ..fixtures import getfixturemarker if getfixturemarker(obj) is not None: - warnings.warn(MARKED_FIXTURE, stacklevel=2) + warnings.warn(MARKED_FIXTURE, stacklevel=stacklevel) # Always reassign name to avoid updating pytestmark in a reference that # was only borrowed. diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index 52752d4e8..a5f513063 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -118,6 +118,8 @@ def test_fixture_disallow_marks_on_fixtures(): raise NotImplementedError() assert len(record) == 2 # one for each mark decorator + # should point to this file + assert all(rec.filename == __file__ for rec in record) def test_fixture_disallowed_between_marks(): From 010ce2ab0f6d2e90f295d4e3f9e725d31dd5721d Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 23 Feb 2024 09:35:57 +0200 Subject: [PATCH 27/28] Add typing to `from_parent` return values (#11916) Up to now the return values of `from_parent` were untyped, this is an attempt to make it work with `typing.Self`. --- src/_pytest/doctest.py | 11 +++++------ src/_pytest/main.py | 11 ++++++++--- src/_pytest/nodes.py | 22 +++++++++++++--------- src/_pytest/python.py | 25 +++++++++++++------------ src/_pytest/unittest.py | 3 +-- testing/test_collection.py | 2 +- 6 files changed, 41 insertions(+), 33 deletions(-) diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index 8fe992b6a..ced3b82f5 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -47,6 +47,7 @@ from _pytest.warning_types import PytestWarning if TYPE_CHECKING: import doctest + from typing import Self DOCTEST_REPORT_CHOICE_NONE = "none" DOCTEST_REPORT_CHOICE_CDIFF = "cdiff" @@ -133,11 +134,9 @@ def pytest_collect_file( if config.option.doctestmodules and not any( (_is_setup_py(file_path), _is_main_py(file_path)) ): - mod: DoctestModule = DoctestModule.from_parent(parent, path=file_path) - return mod + return DoctestModule.from_parent(parent, path=file_path) elif _is_doctest(config, file_path, parent): - txt: DoctestTextfile = DoctestTextfile.from_parent(parent, path=file_path) - return txt + return DoctestTextfile.from_parent(parent, path=file_path) return None @@ -272,14 +271,14 @@ class DoctestItem(Item): self._initrequest() @classmethod - def from_parent( # type: ignore + def from_parent( # type: ignore[override] cls, parent: "Union[DoctestTextfile, DoctestModule]", *, name: str, runner: "doctest.DocTestRunner", dtest: "doctest.DocTest", - ): + ) -> "Self": # incompatible signature due to imposed limits on subclass """The public named constructor.""" return super().from_parent(name=name, parent=parent, runner=runner, dtest=dtest) diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 5c70ad74e..672ad67b9 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -21,6 +21,7 @@ from typing import Optional from typing import overload from typing import Sequence from typing import Tuple +from typing import TYPE_CHECKING from typing import Union import warnings @@ -49,6 +50,10 @@ from _pytest.runner import SetupState from _pytest.warning_types import PytestWarning +if TYPE_CHECKING: + from typing import Self + + def pytest_addoption(parser: Parser) -> None: parser.addini( "norecursedirs", @@ -491,16 +496,16 @@ class Dir(nodes.Directory): @classmethod def from_parent( # type: ignore[override] cls, - parent: nodes.Collector, # type: ignore[override] + parent: nodes.Collector, *, path: Path, - ) -> "Dir": + ) -> "Self": """The public constructor. :param parent: The parent collector of this Dir. :param path: The directory's path. """ - return super().from_parent(parent=parent, path=path) # type: ignore[no-any-return] + return super().from_parent(parent=parent, path=path) def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]: config = self.config diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 48f7d5841..2381b65ea 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -11,6 +11,7 @@ from typing import Iterable from typing import Iterator from typing import List from typing import MutableMapping +from typing import NoReturn from typing import Optional from typing import overload from typing import Set @@ -41,6 +42,8 @@ from _pytest.warning_types import PytestWarning if TYPE_CHECKING: + from typing import Self + # Imported here due to circular import. from _pytest._code.code import _TracebackStyle from _pytest.main import Session @@ -51,6 +54,7 @@ SEP = "/" tracebackcutdir = Path(_pytest.__file__).parent +_T = TypeVar("_T") _NodeType = TypeVar("_NodeType", bound="Node") @@ -69,33 +73,33 @@ class NodeMeta(abc.ABCMeta): progress on detangling the :class:`Node` classes. """ - def __call__(self, *k, **kw): + def __call__(cls, *k, **kw) -> NoReturn: msg = ( "Direct construction of {name} has been deprecated, please use {name}.from_parent.\n" "See " "https://docs.pytest.org/en/stable/deprecations.html#node-construction-changed-to-node-from-parent" " for more details." - ).format(name=f"{self.__module__}.{self.__name__}") + ).format(name=f"{cls.__module__}.{cls.__name__}") fail(msg, pytrace=False) - def _create(self, *k, **kw): + def _create(cls: Type[_T], *k, **kw) -> _T: try: - return super().__call__(*k, **kw) + return super().__call__(*k, **kw) # type: ignore[no-any-return,misc] except TypeError: - sig = signature(getattr(self, "__init__")) + sig = signature(getattr(cls, "__init__")) known_kw = {k: v for k, v in kw.items() if k in sig.parameters} from .warning_types import PytestDeprecationWarning warnings.warn( PytestDeprecationWarning( - f"{self} is not using a cooperative constructor and only takes {set(known_kw)}.\n" + f"{cls} is not using a cooperative constructor and only takes {set(known_kw)}.\n" "See https://docs.pytest.org/en/stable/deprecations.html" "#constructors-of-custom-pytest-node-subclasses-should-take-kwargs " "for more details." ) ) - return super().__call__(*k, **known_kw) + return super().__call__(*k, **known_kw) # type: ignore[no-any-return,misc] class Node(abc.ABC, metaclass=NodeMeta): @@ -181,7 +185,7 @@ class Node(abc.ABC, metaclass=NodeMeta): self._store = self.stash @classmethod - def from_parent(cls, parent: "Node", **kw): + def from_parent(cls, parent: "Node", **kw) -> "Self": """Public constructor for Nodes. This indirection got introduced in order to enable removing @@ -583,7 +587,7 @@ class FSCollector(Collector, abc.ABC): *, path: Optional[Path] = None, **kw, - ): + ) -> "Self": """The public constructor.""" return super().from_parent(parent=parent, path=path, **kw) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index a060b17e5..ca64a877d 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -27,6 +27,7 @@ from typing import Pattern from typing import Sequence from typing import Set from typing import Tuple +from typing import TYPE_CHECKING from typing import Union import warnings @@ -81,6 +82,10 @@ from _pytest.warning_types import PytestReturnNotNoneWarning from _pytest.warning_types import PytestUnhandledCoroutineWarning +if TYPE_CHECKING: + from typing import Self + + _PYTEST_DIR = Path(_pytest.__file__).parent @@ -204,8 +209,7 @@ def pytest_collect_directory( ) -> Optional[nodes.Collector]: pkginit = path / "__init__.py" if pkginit.is_file(): - pkg: Package = Package.from_parent(parent, path=path) - return pkg + return Package.from_parent(parent, path=path) return None @@ -230,8 +234,7 @@ def path_matches_patterns(path: Path, patterns: Iterable[str]) -> bool: def pytest_pycollect_makemodule(module_path: Path, parent) -> "Module": - mod: Module = Module.from_parent(parent, path=module_path) - return mod + return Module.from_parent(parent, path=module_path) @hookimpl(trylast=True) @@ -242,8 +245,7 @@ def pytest_pycollect_makeitem( # Nothing was collected elsewhere, let's do it here. if safe_isclass(obj): if collector.istestclass(obj, name): - klass: Class = Class.from_parent(collector, name=name, obj=obj) - return klass + return Class.from_parent(collector, name=name, obj=obj) elif collector.istestfunction(obj, name): # mock seems to store unbound methods (issue473), normalize it. obj = getattr(obj, "__func__", obj) @@ -262,7 +264,7 @@ def pytest_pycollect_makeitem( ) elif getattr(obj, "__test__", True): if is_generator(obj): - res: Function = Function.from_parent(collector, name=name) + res = Function.from_parent(collector, name=name) reason = ( f"yield tests were removed in pytest 4.0 - {name} will be ignored" ) @@ -465,9 +467,7 @@ class PyCollector(PyobjMixin, nodes.Collector, abc.ABC): clscol = self.getparent(Class) cls = clscol and clscol.obj or None - definition: FunctionDefinition = FunctionDefinition.from_parent( - self, name=name, callobj=funcobj - ) + definition = FunctionDefinition.from_parent(self, name=name, callobj=funcobj) fixtureinfo = definition._fixtureinfo # pytest_generate_tests impls call metafunc.parametrize() which fills @@ -751,7 +751,7 @@ class Class(PyCollector): """Collector for test methods (and nested classes) in a Python class.""" @classmethod - def from_parent(cls, parent, *, name, obj=None, **kw): + def from_parent(cls, parent, *, name, obj=None, **kw) -> "Self": # type: ignore[override] """The public constructor.""" return super().from_parent(name=name, parent=parent, **kw) @@ -1730,8 +1730,9 @@ class Function(PyobjMixin, nodes.Item): self.fixturenames = fixtureinfo.names_closure self._initrequest() + # todo: determine sound type limitations @classmethod - def from_parent(cls, parent, **kw): # todo: determine sound type limitations + def from_parent(cls, parent, **kw) -> "Self": """The public constructor.""" return super().from_parent(parent=parent, **kw) diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 6598bdbc5..2b7966531 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -55,8 +55,7 @@ def pytest_pycollect_makeitem( except Exception: return None # Yes, so let's collect it. - item: UnitTestCase = UnitTestCase.from_parent(collector, name=name, obj=obj) - return item + return UnitTestCase.from_parent(collector, name=name, obj=obj) class UnitTestCase(Class): diff --git a/testing/test_collection.py b/testing/test_collection.py index 98cff8fe9..de8cacb8f 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -1613,7 +1613,7 @@ def test_fscollector_from_parent(pytester: Pytester, request: FixtureRequest) -> assert collector.x == 10 -def test_class_from_parent(pytester: Pytester, request: FixtureRequest) -> None: +def test_class_from_parent(request: FixtureRequest) -> None: """Ensure Class.from_parent can forward custom arguments to the constructor.""" class MyCollector(pytest.Class): From 8d9b95dcdb131716b72b300abe969d4bf5209bd9 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 23 Feb 2024 07:51:15 -0300 Subject: [PATCH 28/28] Fix collection of short paths on Windows (#11936) Passing a short path in the command line was causing the matchparts check to fail, because ``Path(short_path) != Path(long_path)``. Using ``os.path.samefile`` as fallback ensures the comparsion works on Windows when comparing short/long paths. Fix #11895 --- changelog/11895.bugfix.rst | 1 + src/_pytest/main.py | 4 ++++ testing/test_collection.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 changelog/11895.bugfix.rst diff --git a/changelog/11895.bugfix.rst b/changelog/11895.bugfix.rst new file mode 100644 index 000000000..4211213c1 --- /dev/null +++ b/changelog/11895.bugfix.rst @@ -0,0 +1 @@ +Fix collection on Windows where initial paths contain the short version of a path (for example ``c:\PROGRA~1\tests``). diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 672ad67b9..639bf26c1 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -906,6 +906,10 @@ class Session(nodes.Collector): # Path part e.g. `/a/b/` in `/a/b/test_file.py::TestIt::test_it`. if isinstance(matchparts[0], Path): is_match = node.path == matchparts[0] + if sys.platform == "win32" and not is_match: + # In case the file paths do not match, fallback to samefile() to + # account for short-paths on Windows (#11895). + is_match = os.path.samefile(node.path, matchparts[0]) # Name part e.g. `TestIt` in `/a/b/test_file.py::TestIt::test_it`. else: # TODO: Remove parametrized workaround once collection structure contains diff --git a/testing/test_collection.py b/testing/test_collection.py index de8cacb8f..050740045 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -4,9 +4,11 @@ from pathlib import Path import pprint import shutil import sys +import tempfile import textwrap from typing import List +from _pytest.assertion.util import running_on_ci from _pytest.config import ExitCode from _pytest.fixtures import FixtureRequest from _pytest.main import _in_venv @@ -1759,3 +1761,29 @@ def test_does_not_crash_on_recursive_symlink(pytester: Pytester) -> None: assert result.ret == ExitCode.OK assert result.parseoutcomes() == {"passed": 1} + + +@pytest.mark.skipif(not sys.platform.startswith("win"), reason="Windows only") +def test_collect_short_file_windows(pytester: Pytester) -> None: + """Reproducer for #11895: short paths not colleced on Windows.""" + short_path = tempfile.mkdtemp() + if "~" not in short_path: # pragma: no cover + if running_on_ci(): + # On CI, we are expecting that under the current GitHub actions configuration, + # tempfile.mkdtemp() is producing short paths, so we want to fail to prevent + # this from silently changing without us noticing. + pytest.fail( + f"tempfile.mkdtemp() failed to produce a short path on CI: {short_path}" + ) + else: + # We want to skip failing this test locally in this situation because + # depending on the local configuration tempfile.mkdtemp() might not produce a short path: + # For example, user might have configured %TEMP% exactly to avoid generating short paths. + pytest.skip( + f"tempfile.mkdtemp() failed to produce a short path: {short_path}, skipping" + ) + + test_file = Path(short_path).joinpath("test_collect_short_file_windows.py") + test_file.write_text("def test(): pass", encoding="UTF-8") + result = pytester.runpytest(short_path) + assert result.parseoutcomes() == {"passed": 1}