Merge branch 'main' into full_diff_issue

This commit is contained in:
JamieC2002 2023-12-07 20:01:31 -05:00 committed by GitHub
commit 154c11034d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 1025 additions and 654 deletions

View File

@ -47,7 +47,7 @@ jobs:
path: dist
- name: Publish package to PyPI
uses: pypa/gh-action-pypi-publish@v1.8.10
uses: pypa/gh-action-pypi-publish@v1.8.11
- name: Push tag
run: |

View File

@ -56,7 +56,7 @@ repos:
hooks:
- id: python-use-type-annotations
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.7.0
rev: v1.7.1
hooks:
- id: mypy
files: ^(src/|testing/)

View File

@ -189,6 +189,7 @@ Javier Romero
Jeff Rackauckas
Jeff Widman
Jenni Rinker
Jens Tröger
John Eddie Ayson
John Litborn
John Towler

View File

@ -1 +1,3 @@
Improved very verbose diff output to color it as a diff instead of only red.
Improved the error reporting to better separate each section.

View File

@ -0,0 +1 @@
Handle an edge case where :data:`sys.stderr` and :data:`sys.__stderr__` might already be closed when :ref:`faulthandler` is tearing down.

View File

@ -0,0 +1,2 @@
Added :func:`LogCaptureFixture.filtering() <pytest.LogCaptureFixture.filtering>` context manager that
adds a given :class:`logging.Filter` object to the caplog fixture.

View File

@ -0,0 +1 @@
Fixed the selftests to pass correctly if ``FORCE_COLOR``, ``NO_COLOR`` or ``PY_COLORS`` is set in the calling environment.

View File

@ -0,0 +1,3 @@
pytest's ``setup.py`` file is removed.
If you relied on this file, e.g. to install pytest using ``setup.py install``,
please see `Why you shouldn't invoke setup.py directly <https://blog.ganssle.io/articles/2021/10/setup-py-deprecated.html#summary>`_ for alternatives.

View File

@ -0,0 +1,4 @@
Improved the very verbose diff for every standard library container types: the indentation is now consistent and the markers are on their own separate lines, which should reduce the diffs shown to users.
Previously, the default python pretty printer was used to generate the output, which puts opening and closing
markers on the same line as the first/last entry, in addition to not having consistent indentation.

View File

@ -1,4 +1,4 @@
:func:`pytest.warns <warns>` now re-emits unmatched warnings when the context
:func:`~pytest.warns` now re-emits unmatched warnings when the context
closes -- previously it would consume all warnings, hiding those that were not
matched by the function.

View File

@ -22,7 +22,7 @@ b) transitional: the old and new API don't conflict
We will only start the removal of deprecated functionality in major releases (e.g. if we deprecate something in 3.0 we will start to remove it in 4.0), and keep it around for at least two minor releases (e.g. if we deprecate something in 3.9 and 4.0 is the next release, we start to remove it in 5.0, not in 4.0).
A deprecated feature scheduled to be removed in major version X will use the warning class `PytestRemovedInXWarning` (a subclass of :class:`~pytest.PytestDeprecationwarning`).
A deprecated feature scheduled to be removed in major version X will use the warning class `PytestRemovedInXWarning` (a subclass of :class:`~pytest.PytestDeprecationWarning`).
When the deprecation expires (e.g. 4.0 is released), we won't remove the deprecated functionality immediately, but will use the standard warning filters to turn `PytestRemovedInXWarning` (e.g. `PytestRemovedIn4Warning`) into **errors** by default. This approach makes it explicit that removal is imminent, and still gives you time to turn the deprecated feature into a warning instead of an error so it can be dealt with in your own time. In the next minor release (e.g. 4.1), the feature will be effectively removed.

View File

@ -413,7 +413,7 @@ Improvements
- `#8508 <https://github.com/pytest-dev/pytest/issues/8508>`_: Introduce multiline display for warning matching via :py:func:`pytest.warns` and
enhance match comparison for :py:func:`_pytest._code.ExceptionInfo.match` as returned by :py:func:`pytest.raises`.
enhance match comparison for :py:func:`pytest.ExceptionInfo.match` as returned by :py:func:`pytest.raises`.
- `#8646 <https://github.com/pytest-dev/pytest/issues/8646>`_: Improve :py:func:`pytest.raises`. Previously passing an empty tuple would give a confusing
@ -422,7 +422,7 @@ Improvements
- `#9741 <https://github.com/pytest-dev/pytest/issues/9741>`_: On Python 3.11, use the standard library's :mod:`tomllib` to parse TOML.
:mod:`tomli` is no longer a dependency on Python 3.11.
`tomli` is no longer a dependency on Python 3.11.
- `#9742 <https://github.com/pytest-dev/pytest/issues/9742>`_: Display assertion message without escaped newline characters with ``-vv``.
@ -457,7 +457,7 @@ Bug Fixes
When inheriting marks from super-classes, marks from the sub-classes are now ordered before marks from the super-classes, in MRO order. Previously it was the reverse.
When inheriting marks from super-classes, the `pytestmark` attribute of the sub-class now only contains the marks directly applied to it. Previously, it also contained marks from its super-classes. Please note that this attribute should not normally be accessed directly; use :func:`pytest.Node.iter_markers` instead.
When inheriting marks from super-classes, the `pytestmark` attribute of the sub-class now only contains the marks directly applied to it. Previously, it also contained marks from its super-classes. Please note that this attribute should not normally be accessed directly; use :func:`Node.iter_markers <_pytest.nodes.Node.iter_markers>` instead.
- `#9159 <https://github.com/pytest-dev/pytest/issues/9159>`_: Showing inner exceptions by forcing native display in ``ExceptionGroups`` even when using display options other than ``--tb=native``. A temporary step before full implementation of pytest-native display for inner exceptions in ``ExceptionGroups``.
@ -710,7 +710,7 @@ Bug Fixes
- `#9355 <https://github.com/pytest-dev/pytest/issues/9355>`_: Fixed error message prints function decorators when using assert in Python 3.8 and above.
- `#9396 <https://github.com/pytest-dev/pytest/issues/9396>`_: Ensure :attr:`pytest.Config.inifile` is available during the :func:`pytest_cmdline_main <_pytest.hookspec.pytest_cmdline_main>` hook (regression during ``7.0.0rc1``).
- `#9396 <https://github.com/pytest-dev/pytest/issues/9396>`_: Ensure `pytest.Config.inifile` is available during the :hook:`pytest_cmdline_main` hook (regression during ``7.0.0rc1``).
@ -855,7 +855,7 @@ Deprecations
- ``parser.addoption(..., type="int/string/float/complex")`` - use ``type=int`` etc. instead.
- `#8447 <https://github.com/pytest-dev/pytest/issues/8447>`_: Defining a custom pytest node type which is both an :class:`pytest.Item <Item>` and a :class:`pytest.Collector <Collector>` (e.g. :class:`pytest.File <File>`) now issues a warning.
- `#8447 <https://github.com/pytest-dev/pytest/issues/8447>`_: Defining a custom pytest node type which is both an :class:`~pytest.Item` and a :class:`~pytest.Collector` (e.g. :class:`~pytest.File`) now issues a warning.
It was never sanely supported and triggers hard to debug errors.
See :ref:`the deprecation note <diamond-inheritance-deprecated>` for full details.
@ -897,7 +897,7 @@ Features
- `#7132 <https://github.com/pytest-dev/pytest/issues/7132>`_: Added two environment variables :envvar:`PYTEST_THEME` and :envvar:`PYTEST_THEME_MODE` to let the users customize the pygments theme used.
- `#7259 <https://github.com/pytest-dev/pytest/issues/7259>`_: Added :meth:`cache.mkdir() <pytest.Cache.mkdir>`, which is similar to the existing :meth:`cache.makedir() <pytest.Cache.makedir>`,
- `#7259 <https://github.com/pytest-dev/pytest/issues/7259>`_: Added :meth:`cache.mkdir() <pytest.Cache.mkdir>`, which is similar to the existing ``cache.makedir()``,
but returns a :class:`pathlib.Path` instead of a legacy ``py.path.local``.
Added a ``paths`` type to :meth:`parser.addini() <pytest.Parser.addini>`,
@ -923,7 +923,7 @@ Features
- ``pytest.HookRecorder`` for the :class:`HookRecorder <pytest.HookRecorder>` type returned from :class:`~pytest.Pytester`.
- ``pytest.RecordedHookCall`` for the :class:`RecordedHookCall <pytest.HookRecorder>` type returned from :class:`~pytest.HookRecorder`.
- ``pytest.RunResult`` for the :class:`RunResult <pytest.RunResult>` type returned from :class:`~pytest.Pytester`.
- ``pytest.LineMatcher`` for the :class:`LineMatcher <pytest.RunResult>` type used in :class:`~pytest.RunResult` and others.
- ``pytest.LineMatcher`` for the :class:`LineMatcher <pytest.LineMatcher>` type used in :class:`~pytest.RunResult` and others.
- ``pytest.TestReport`` for the :class:`TestReport <pytest.TestReport>` type used in various hooks.
- ``pytest.CollectReport`` for the :class:`CollectReport <pytest.CollectReport>` type used in various hooks.
@ -956,7 +956,7 @@ Features
- `#8251 <https://github.com/pytest-dev/pytest/issues/8251>`_: Implement ``Node.path`` as a ``pathlib.Path``. Both the old ``fspath`` and this new attribute gets set no matter whether ``path`` or ``fspath`` (deprecated) is passed to the constructor. It is a replacement for the ``fspath`` attribute (which represents the same path as ``py.path.local``). While ``fspath`` is not deprecated yet
due to the ongoing migration of methods like :meth:`~_pytest.Item.reportinfo`, we expect to deprecate it in a future release.
due to the ongoing migration of methods like :meth:`~pytest.Item.reportinfo`, we expect to deprecate it in a future release.
.. note::
The name of the :class:`~_pytest.nodes.Node` arguments and attributes (the
@ -988,7 +988,7 @@ Features
See :ref:`plugin-stash` for details.
- `#8953 <https://github.com/pytest-dev/pytest/issues/8953>`_: :class:`RunResult <_pytest.pytester.RunResult>` method :meth:`assert_outcomes <_pytest.pytester.RunResult.assert_outcomes>` now accepts a
- `#8953 <https://github.com/pytest-dev/pytest/issues/8953>`_: :class:`~pytest.RunResult` method :meth:`~pytest.RunResult.assert_outcomes` now accepts a
``warnings`` argument to assert the total number of warnings captured.
@ -1000,7 +1000,7 @@ Features
used.
- `#9113 <https://github.com/pytest-dev/pytest/issues/9113>`_: :class:`RunResult <_pytest.pytester.RunResult>` method :meth:`assert_outcomes <_pytest.pytester.RunResult.assert_outcomes>` now accepts a
- `#9113 <https://github.com/pytest-dev/pytest/issues/9113>`_: :class:`~pytest.RunResult` method :meth:`~pytest.RunResult.assert_outcomes` now accepts a
``deselected`` argument to assert the total number of deselected tests.
@ -1013,7 +1013,7 @@ Improvements
- `#7480 <https://github.com/pytest-dev/pytest/issues/7480>`_: A deprecation scheduled to be removed in a major version X (e.g. pytest 7, 8, 9, ...) now uses warning category `PytestRemovedInXWarning`,
a subclass of :class:`~pytest.PytestDeprecationWarning`,
instead of :class:`PytestDeprecationWarning` directly.
instead of :class:`~pytest.PytestDeprecationWarning` directly.
See :ref:`backwards-compatibility` for more details.
@ -1052,7 +1052,7 @@ Improvements
- `#8803 <https://github.com/pytest-dev/pytest/issues/8803>`_: It is now possible to add colors to custom log levels on cli log.
By using :func:`add_color_level <_pytest.logging.add_color_level>` from a ``pytest_configure`` hook, colors can be added::
By using ``add_color_level`` from a :hook:`pytest_configure` hook, colors can be added::
logging_plugin = config.pluginmanager.get_plugin('logging-plugin')
logging_plugin.log_cli_handler.formatter.add_color_level(logging.INFO, 'cyan')
@ -1117,7 +1117,7 @@ Bug Fixes
- `#8503 <https://github.com/pytest-dev/pytest/issues/8503>`_: :meth:`pytest.MonkeyPatch.syspath_prepend` no longer fails when
``setuptools`` is not installed.
It now only calls :func:`pkg_resources.fixup_namespace_packages` if
It now only calls ``pkg_resources.fixup_namespace_packages`` if
``pkg_resources`` was previously imported, because it is not needed otherwise.
@ -1344,7 +1344,7 @@ Features
This is part of the movement to use :class:`pathlib.Path` objects internally, in order to remove the dependency to ``py`` in the future.
Internally, the old :class:`Testdir <_pytest.pytester.Testdir>` is now a thin wrapper around :class:`Pytester <_pytest.pytester.Pytester>`, preserving the old interface.
Internally, the old :class:`~pytest.Testdir` is now a thin wrapper around :class:`~pytest.Pytester`, preserving the old interface.
- :issue:`7695`: A new hook was added, `pytest_markeval_namespace` which should return a dictionary.
@ -1382,7 +1382,7 @@ Features
Improvements
------------
- :issue:`1265`: Added an ``__str__`` implementation to the :class:`~pytest.pytester.LineMatcher` class which is returned from ``pytester.run_pytest().stdout`` and similar. It returns the entire output, like the existing ``str()`` method.
- :issue:`1265`: Added an ``__str__`` implementation to the :class:`~pytest.LineMatcher` class which is returned from ``pytester.run_pytest().stdout`` and similar. It returns the entire output, like the existing ``str()`` method.
- :issue:`2044`: Verbose mode now shows the reason that a test was skipped in the test's terminal line after the "SKIPPED", "XFAIL" or "XPASS".
@ -1446,7 +1446,7 @@ Bug Fixes
- :issue:`7911`: Directories created by by :fixture:`tmp_path` and :fixture:`tmpdir` are now considered stale after 3 days without modification (previous value was 3 hours) to avoid deleting directories still in use in long running test suites.
- :issue:`7913`: Fixed a crash or hang in :meth:`pytester.spawn <_pytest.pytester.Pytester.spawn>` when the :mod:`readline` module is involved.
- :issue:`7913`: Fixed a crash or hang in :meth:`pytester.spawn <pytest.Pytester.spawn>` when the :mod:`readline` module is involved.
- :issue:`7951`: Fixed handling of recursive symlinks when collecting tests.
@ -1563,7 +1563,7 @@ Deprecations
if you use this and want a replacement.
- :issue:`7255`: The :hook:`pytest_warning_captured` hook is deprecated in favor
- :issue:`7255`: The ``pytest_warning_captured`` hook is deprecated in favor
of :hook:`pytest_warning_recorded`, and will be removed in a future version.
@ -1591,8 +1591,8 @@ Improvements
- :issue:`7572`: When a plugin listed in ``required_plugins`` is missing or an unknown config key is used with ``--strict-config``, a simple error message is now shown instead of a stacktrace.
- :issue:`7685`: Added two new attributes :attr:`rootpath <_pytest.config.Config.rootpath>` and :attr:`inipath <_pytest.config.Config.inipath>` to :class:`Config <_pytest.config.Config>`.
These attributes are :class:`pathlib.Path` versions of the existing :attr:`rootdir <_pytest.config.Config.rootdir>` and :attr:`inifile <_pytest.config.Config.inifile>` attributes,
- :issue:`7685`: Added two new attributes :attr:`rootpath <pytest.Config.rootpath>` and :attr:`inipath <pytest.Config.inipath>` to :class:`~pytest.Config`.
These attributes are :class:`pathlib.Path` versions of the existing :attr:`rootdir <pytest.Config.rootdir>` and :attr:`inifile <pytest.Config.inifile>` attributes,
and should be preferred over them when possible.
@ -1663,7 +1663,7 @@ Trivial/Internal Changes
- :issue:`7587`: The dependency on the ``more-itertools`` package has been removed.
- :issue:`7631`: The result type of :meth:`capfd.readouterr() <_pytest.capture.CaptureFixture.readouterr>` (and similar) is no longer a namedtuple,
- :issue:`7631`: The result type of :meth:`capfd.readouterr() <pytest.CaptureFixture.readouterr>` (and similar) is no longer a namedtuple,
but should behave like one in all respects. This was done for technical reasons.
@ -2041,10 +2041,10 @@ Improvements
- :issue:`7128`: `pytest --version` now displays just the pytest version, while `pytest --version --version` displays more verbose information including plugins. This is more consistent with how other tools show `--version`.
- :issue:`7133`: :meth:`caplog.set_level() <_pytest.logging.LogCaptureFixture.set_level>` will now override any :confval:`log_level` set via the CLI or configuration file.
- :issue:`7133`: :meth:`caplog.set_level() <pytest.LogCaptureFixture.set_level>` will now override any :confval:`log_level` set via the CLI or configuration file.
- :issue:`7159`: :meth:`caplog.set_level() <_pytest.logging.LogCaptureFixture.set_level>` and :meth:`caplog.at_level() <_pytest.logging.LogCaptureFixture.at_level>` no longer affect
- :issue:`7159`: :meth:`caplog.set_level() <pytest.LogCaptureFixture.set_level>` and :meth:`caplog.at_level() <pytest.LogCaptureFixture.at_level>` no longer affect
the level of logs that are shown in the *Captured log report* report section.
@ -2390,7 +2390,7 @@ Improvements
- :issue:`6384`: Make `--showlocals` work also with `--tb=short`.
- :issue:`6653`: Add support for matching lines consecutively with :attr:`LineMatcher <_pytest.pytester.LineMatcher>`'s :func:`~_pytest.pytester.LineMatcher.fnmatch_lines` and :func:`~_pytest.pytester.LineMatcher.re_match_lines`.
- :issue:`6653`: Add support for matching lines consecutively with :class:`~pytest.LineMatcher`'s :func:`~pytest.LineMatcher.fnmatch_lines` and :func:`~pytest.LineMatcher.re_match_lines`.
- :issue:`6658`: Code is now highlighted in tracebacks when ``pygments`` is installed.
@ -2458,7 +2458,7 @@ Bug Fixes
- :issue:`6597`: Fix node ids which contain a parametrized empty-string variable.
- :issue:`6646`: Assertion rewriting hooks are (re)stored for the current item, which fixes them being still used after e.g. pytester's :func:`testdir.runpytest <_pytest.pytester.Testdir.runpytest>` etc.
- :issue:`6646`: Assertion rewriting hooks are (re)stored for the current item, which fixes them being still used after e.g. pytester's :func:`testdir.runpytest <pytest.Testdir.runpytest>` etc.
- :issue:`6660`: :py:func:`pytest.exit` is handled when emitted from the :hook:`pytest_sessionfinish` hook. This includes quitting from a debugger.
@ -2524,7 +2524,7 @@ Bug Fixes
``multiprocessing`` module.
- :issue:`6436`: :class:`FixtureDef <_pytest.fixtures.FixtureDef>` objects now properly register their finalizers with autouse and
- :issue:`6436`: :class:`~pytest.FixtureDef` objects now properly register their finalizers with autouse and
parameterized fixtures that execute before them in the fixture stack so they are torn
down at the right times, and in the right order.
@ -2580,7 +2580,7 @@ Improvements
Bug Fixes
---------
- :issue:`5914`: pytester: fix :py:func:`~_pytest.pytester.LineMatcher.no_fnmatch_line` when used after positive matching.
- :issue:`5914`: pytester: fix :py:func:`~pytest.LineMatcher.no_fnmatch_line` when used after positive matching.
- :issue:`6082`: Fix line detection for doctest samples inside :py:class:`python:property` docstrings, as a workaround to :bpo:`17446`.
@ -2644,8 +2644,8 @@ Features
rather than implicitly.
- :issue:`5914`: :fixture:`testdir` learned two new functions, :py:func:`~_pytest.pytester.LineMatcher.no_fnmatch_line` and
:py:func:`~_pytest.pytester.LineMatcher.no_re_match_line`.
- :issue:`5914`: :fixture:`testdir` learned two new functions, :py:func:`~pytest.LineMatcher.no_fnmatch_line` and
:py:func:`~pytest.LineMatcher.no_re_match_line`.
The functions are used to ensure the captured text *does not* match the given
pattern.
@ -6497,7 +6497,7 @@ Changes
* fix :issue:`2013`: turn RecordedWarning into ``namedtuple``,
to give it a comprehensible repr while preventing unwarranted modification.
* fix :issue:`2208`: ensure an iteration limit for _pytest.compat.get_real_func.
* fix :issue:`2208`: ensure an iteration limit for ``_pytest.compat.get_real_func``.
Thanks :user:`RonnyPfannschmidt` for the report and PR.
* Hooks are now verified after collection is complete, rather than right after loading installed plugins. This

View File

@ -177,7 +177,7 @@ arguments they only pass on to the superclass.
resolved in future versions as we slowly get rid of the :pypi:`py`
dependency (see :issue:`9283` for a longer discussion).
Due to the ongoing migration of methods like :meth:`~_pytest.Item.reportinfo`
Due to the ongoing migration of methods like :meth:`~pytest.Item.reportinfo`
which still is expected to return a ``py.path.local`` object, nodes still have
both ``fspath`` (``py.path.local``) and ``path`` (``pathlib.Path``) attributes,
no matter what argument was used in the constructor. We expect to deprecate the
@ -336,7 +336,7 @@ Diamond inheritance between :class:`pytest.Collector` and :class:`pytest.Item`
.. deprecated:: 7.0
Defining a custom pytest node type which is both an :class:`pytest.Item <Item>` and a :class:`pytest.Collector <Collector>` (e.g. :class:`pytest.File <File>`) now issues a warning.
Defining a custom pytest node type which is both an :class:`~pytest.Item` and a :class:`~pytest.Collector` (e.g. :class:`~pytest.File`) now issues a warning.
It was never sanely supported and triggers hard to debug errors.
Some plugins providing linting/code analysis have been using this as a hack.
@ -348,8 +348,8 @@ Instead, a separate collector node should be used, which collects the item. See
.. _uncooperative-constructors-deprecated:
Constructors of custom :class:`pytest.Node` subclasses should take ``**kwargs``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Constructors of custom :class:`~_pytest.nodes.Node` subclasses should take ``**kwargs``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 7.0

View File

@ -4,8 +4,6 @@
Parametrizing tests
=================================================
.. currentmodule:: _pytest.python
``pytest`` allows to easily parametrize test functions.
For basic docs, see :ref:`parametrize-basics`.
@ -185,7 +183,7 @@ A quick port of "testscenarios"
Here is a quick port to run tests configured with :pypi:`testscenarios`,
an add-on from Robert Collins for the standard unittest framework. We
only have to work a bit to construct the correct arguments for pytest's
:py:func:`Metafunc.parametrize`:
:py:func:`Metafunc.parametrize <pytest.Metafunc.parametrize>`:
.. code-block:: python

View File

@ -162,7 +162,7 @@ A note about fixture cleanup
----------------------------
pytest does not do any special processing for :data:`SIGTERM <signal.SIGTERM>` and
:data:`SIGQUIT <signal.SIGQUIT>` signals (:data:`SIGINT <signal.SIGINT>` is handled naturally
``SIGQUIT`` signals (:data:`SIGINT <signal.SIGINT>` is handled naturally
by the Python runtime via :class:`KeyboardInterrupt`), so fixtures that manage external resources which are important
to be cleared when the Python process is terminated (by those signals) might leak resources.

View File

@ -11,8 +11,6 @@ funcarg mechanism, see :ref:`historical funcargs and pytest.funcargs`.
If you are new to pytest, then you can simply ignore this
section and read the other sections.
.. currentmodule:: _pytest
Shortcomings of the previous ``pytest_funcarg__`` mechanism
--------------------------------------------------------------

View File

@ -112,7 +112,7 @@ More details can be found in the :pull:`original PR <3317>`.
.. note::
in a future major release of pytest we will introduce class based markers,
at which point markers will no longer be limited to instances of :py:class:`~_pytest.mark.Mark`.
at which point markers will no longer be limited to instances of :py:class:`~pytest.Mark`.
cache plugin integrated into the core

View File

@ -382,8 +382,6 @@ warnings: a WarningsRecorder instance. To view the recorded warnings, you can
iterate over this instance, call ``len`` on it to get the number of recorded
warnings, or index into it to get a particular recorded warning.
.. currentmodule:: _pytest.warnings
Full API: :class:`~_pytest.recwarn.WarningsRecorder`.
.. _`warns use cases`:

View File

@ -1271,7 +1271,7 @@ configured in multiple ways.
Extending the previous example, we can flag the fixture to create two
``smtp_connection`` fixture instances which will cause all tests using the fixture
to run twice. The fixture function gets access to each parameter
through the special :py:class:`request <FixtureRequest>` object:
through the special :py:class:`request <pytest.FixtureRequest>` object:
.. code-block:: python

View File

@ -241,7 +241,7 @@ through ``add_color_level()``. Example:
.. code-block:: python
@pytest.hookimpl
@pytest.hookimpl(trylast=True)
def pytest_configure(config):
logging_plugin = config.pluginmanager.get_plugin("logging-plugin")

View File

@ -59,10 +59,6 @@ The remaining hook functions will not be called in this case.
hook wrappers: executing around other hooks
-------------------------------------------------
.. currentmodule:: _pytest.core
pytest plugins can implement hook wrappers which wrap the execution
of other hook implementations. A hook wrapper is a generator function
which yields exactly once. When pytest invokes hooks it first executes
@ -165,6 +161,7 @@ Here is the order of execution:
It's possible to use ``tryfirst`` and ``trylast`` also on hook wrappers
in which case it will influence the ordering of hook wrappers among each other.
.. _`declaringhooks`:
Declaring new hooks
------------------------
@ -174,13 +171,11 @@ Declaring new hooks
This is a quick overview on how to add new hooks and how they work in general, but a more complete
overview can be found in `the pluggy documentation <https://pluggy.readthedocs.io/en/latest/>`__.
.. currentmodule:: _pytest.hookspec
Plugins and ``conftest.py`` files may declare new hooks that can then be
implemented by other plugins in order to alter behaviour or interact with
the new plugin:
.. autofunction:: pytest_addhooks
.. autofunction:: _pytest.hookspec.pytest_addhooks
:noindex:
Hooks are usually declared as do-nothing functions that contain only

View File

@ -11,9 +11,6 @@ Fixtures reference
.. seealso:: :ref:`about-fixtures`
.. seealso:: :ref:`how-to-fixtures`
.. currentmodule:: _pytest.python
.. _`Dependency injection`: https://en.wikipedia.org/wiki/Dependency_injection
@ -76,15 +73,13 @@ Built-in fixtures
:class:`pathlib.Path` objects.
:fixture:`tmpdir`
Provide a :class:`py.path.local` object to a temporary
Provide a `py.path.local <https://py.readthedocs.io/en/latest/path.html>`_ object to a temporary
directory which is unique to each test function;
replaced by :fixture:`tmp_path`.
.. _`py.path.local`: https://py.readthedocs.io/en/latest/path.html
:fixture:`tmpdir_factory`
Make session-scoped temporary directories and return
:class:`py.path.local` objects;
``py.path.local`` objects;
replaced by :fixture:`tmp_path_factory`.

View File

@ -27,7 +27,7 @@ please refer to `the update script <https://github.com/pytest-dev/pytest/blob/ma
creating a PDF, because otherwise the table gets far too wide for the
page.
This list contains 1346 plugins.
This list contains 1351 plugins.
.. only:: not latex
@ -78,7 +78,7 @@ This list contains 1346 plugins.
:pypi:`pytest-antilru` Bust functools.lru_cache when running pytest to avoid test pollution Jul 05, 2022 5 - Production/Stable pytest
:pypi:`pytest-anyio` The pytest anyio plugin is built into anyio. You don't need this package. Jun 29, 2021 N/A pytest
:pypi:`pytest-anything` Pytest fixtures to assert anything and something Oct 13, 2022 N/A pytest
:pypi:`pytest-aoc` Downloads puzzle inputs for Advent of Code and synthesizes PyTest fixtures Sep 19, 2023 5 - Production/Stable pytest ; extra == 'test'
:pypi:`pytest-aoc` Downloads puzzle inputs for Advent of Code and synthesizes PyTest fixtures Dec 02, 2023 5 - Production/Stable pytest ; extra == 'test'
:pypi:`pytest-aoreporter` pytest report Jun 27, 2022 N/A N/A
:pypi:`pytest-api` An ASGI middleware to populate OpenAPI Specification examples from pytest functions May 12, 2022 N/A pytest (>=7.1.1,<8.0.0)
:pypi:`pytest-api-soup` Validate multiple endpoints with unit testing using a single source of truth. Aug 27, 2022 N/A N/A
@ -89,7 +89,7 @@ This list contains 1346 plugins.
:pypi:`pytest-approvaltests-geo` Extension for ApprovalTests.Python specific to geo data verification Sep 06, 2023 5 - Production/Stable pytest
:pypi:`pytest-archon` Rule your architecture like a real developer Jul 11, 2023 5 - Production/Stable pytest (>=7.2)
:pypi:`pytest-argus` pyest results colection plugin Jun 24, 2021 5 - Production/Stable pytest (>=6.2.4)
:pypi:`pytest-arraydiff` pytest plugin to help with comparing array output from tests Nov 15, 2023 4 - Beta pytest >=4.6
:pypi:`pytest-arraydiff` pytest plugin to help with comparing array output from tests Nov 27, 2023 4 - Beta pytest >=4.6
:pypi:`pytest-asgi-server` Convenient ASGI client/server fixtures for Pytest Dec 12, 2020 N/A pytest (>=5.4.1)
:pypi:`pytest-aspec` A rspec format reporter for pytest Oct 23, 2023 4 - Beta N/A
:pypi:`pytest-asptest` test Answer Set Programming programs Apr 28, 2018 4 - Beta N/A
@ -105,12 +105,12 @@ This list contains 1346 plugins.
: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-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A
:pypi:`pytest-asyncio` Pytest support for asyncio Nov 16, 2023 4 - Beta pytest (>=7.0.0)
:pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Aug 06, 2023 N/A N/A
:pypi:`pytest-asyncio` Pytest support for asyncio Nov 27, 2023 4 - Beta pytest (>=7.0.0)
:pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Nov 30, 2023 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)
:pypi:`pytest-atf-allure` 基于allure-pytest进行自定义 Oct 22, 2023 N/A pytest (>=7.4.2,<8.0.0)
:pypi:`pytest-atf-allure` 基于allure-pytest进行自定义 Nov 29, 2023 N/A pytest (>=7.4.2,<8.0.0)
:pypi:`pytest-atomic` Skip rest of tests if previous test failed. Nov 24, 2018 4 - Beta N/A
:pypi:`pytest-attrib` pytest plugin to select tests based on attributes similar to the nose-attrib plugin May 24, 2016 4 - Beta N/A
:pypi:`pytest-austin` Austin plugin for pytest Oct 11, 2020 4 - Beta N/A
@ -207,7 +207,7 @@ This list contains 1346 plugins.
:pypi:`pytest-check-mk` pytest plugin to test Check_MK checks Nov 19, 2015 4 - Beta pytest
:pypi:`pytest-check-requirements` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A
: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 Nov 02, 2023 N/A pytest >=7.0.0
:pypi:`pytest-choose` Provide the pytest with the ability to collect use cases based on rules in text files Nov 30, 2023 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-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
@ -379,7 +379,7 @@ This list contains 1346 plugins.
:pypi:`pytest-doctest-import` A simple pytest plugin to import names and add them to the doctest namespace. Nov 13, 2018 4 - Beta pytest (>=3.3.0)
:pypi:`pytest-doctestplus` Pytest plugin with advanced doctest features. Aug 11, 2023 3 - Alpha pytest >=4.6
:pypi:`pytest-dogu-report` pytest plugin for dogu report Jul 07, 2023 N/A N/A
:pypi:`pytest-dogu-sdk` pytest plugin for the Dogu Aug 04, 2023 N/A N/A
:pypi:`pytest-dogu-sdk` pytest plugin for the Dogu Nov 20, 2023 N/A N/A
:pypi:`pytest-dolphin` Some extra stuff that we use ininternally Nov 30, 2016 4 - Beta pytest (==3.0.4)
:pypi:`pytest-donde` record pytest session characteristics per test item (coverage and duration) into a persistent file and use them in your own plugin or script. Oct 01, 2023 4 - Beta pytest >=7.3.1
:pypi:`pytest-doorstop` A pytest plugin for adding test results into doorstop items. Jun 09, 2020 4 - Beta pytest (>=3.5.0)
@ -410,14 +410,14 @@ This list contains 1346 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. Nov 07, 2023 5 - Production/Stable pytest>=7.0
:pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Nov 07, 2023 5 - Production/Stable N/A
:pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Nov 07, 2023 5 - Production/Stable N/A
:pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Nov 07, 2023 5 - Production/Stable N/A
:pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Nov 07, 2023 5 - Production/Stable N/A
:pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Nov 07, 2023 5 - Production/Stable N/A
:pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Nov 07, 2023 5 - Production/Stable N/A
:pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Nov 07, 2023 5 - Production/Stable N/A
:pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Nov 27, 2023 5 - Production/Stable pytest>=7.0
:pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Nov 27, 2023 5 - Production/Stable N/A
:pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Nov 27, 2023 5 - Production/Stable N/A
:pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Nov 27, 2023 5 - Production/Stable N/A
:pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Nov 27, 2023 5 - Production/Stable N/A
:pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Nov 27, 2023 5 - Production/Stable N/A
:pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Nov 27, 2023 5 - Production/Stable N/A
:pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Nov 27, 2023 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)
@ -427,7 +427,7 @@ This list contains 1346 plugins.
:pypi:`pytest-encoding` set your encoding and logger Aug 11, 2023 N/A pytest
:pypi:`pytest-enhanced-reports` Enhanced test reports for pytest Dec 15, 2022 N/A N/A
:pypi:`pytest-enhancements` Improvements for pytest (rejected upstream) Oct 30, 2019 4 - Beta N/A
:pypi:`pytest-env` pytest plugin that allows you to add environment variables. Oct 30, 2023 5 - Production/Stable pytest>=7.4.3
:pypi:`pytest-env` pytest plugin that allows you to add environment variables. Nov 28, 2023 5 - Production/Stable pytest>=7.4.3
:pypi:`pytest-envfiles` A py.test plugin that parses environment files before running tests Oct 08, 2015 3 - Alpha N/A
:pypi:`pytest-env-info` Push information about the running pytest into envvars Nov 25, 2017 4 - Beta pytest (>=3.1.1)
:pypi:`pytest-envraw` py.test plugin that allows you to add environment variables. Aug 27, 2020 4 - Beta pytest (>=2.6.0)
@ -527,15 +527,16 @@ This list contains 1346 plugins.
:pypi:`pytest-funparam` An alternative way to parametrize test cases. Dec 02, 2021 4 - Beta pytest >=4.6.0
: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 Nov 15, 2023 1 - Planning pytest >=7.1.2
:pypi:`pytest-fzf` fzf-based test selector for pytest Nov 28, 2023 4 - Beta pytest >=6.0.0
: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. Nov 22, 2023 3 - Alpha pytest; extra == 'test'
: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. Nov 08, 2023 N/A N/A
:pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Nov 20, 2023 N/A N/A
: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
@ -570,12 +571,13 @@ This list contains 1346 plugins.
:pypi:`pytest-hidecaptured` Hide captured output May 04, 2018 4 - Beta pytest (>=2.8.5)
:pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest
:pypi:`pytest-historic-hook` Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report Apr 08, 2020 N/A pytest
:pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Nov 20, 2023 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 Nov 11, 2023 3 - Alpha pytest ==7.4.3
:pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Dec 01, 2023 3 - Alpha pytest ==7.4.3
: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` Jun 23, 2023 N/A N/A
:pypi:`pytest-hot-reloading` Dec 01, 2023 N/A N/A
:pypi:`pytest-hot-test` A plugin that tracks test changes Dec 10, 2022 4 - Beta pytest (>=3.5.0)
:pypi:`pytest-houdini` pytest plugin for testing code in Houdini. Nov 10, 2023 N/A pytest
:pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0)
@ -611,7 +613,7 @@ This list contains 1346 plugins.
:pypi:`pytest-ignore-flaky` ignore failures from flaky tests (pytest plugin) Oct 11, 2023 5 - Production/Stable pytest >=6.0
:pypi:`pytest-ignore-test-results` A pytest plugin to ignore test results. Aug 17, 2023 2 - Pre-Alpha pytest>=7.0
:pypi:`pytest-image-diff` Mar 09, 2023 3 - Alpha pytest
:pypi:`pytest-image-snapshot` A pytest plugin for image snapshot management and comparison. Nov 16, 2023 4 - Beta pytest >=3.5.0
:pypi:`pytest-image-snapshot` A pytest plugin for image snapshot management and comparison. Dec 01, 2023 4 - Beta pytest >=3.5.0
:pypi:`pytest-incremental` an incremental test runner (pytest plugin) Apr 24, 2021 5 - Production/Stable N/A
:pypi:`pytest-influxdb` Plugin for influxdb and pytest integration. Apr 20, 2021 N/A N/A
:pypi:`pytest-info-collector` pytest plugin to collect information from tests May 26, 2019 3 - Alpha N/A
@ -620,9 +622,9 @@ This list contains 1346 plugins.
:pypi:`pytest-infrastructure` pytest stack validation prior to testing executing Apr 12, 2020 4 - Beta N/A
:pypi:`pytest-ini` Reuse pytest.ini to store env variables Apr 26, 2022 N/A N/A
:pypi:`pytest-inline` A pytest plugin for writing inline tests. Oct 19, 2023 4 - Beta pytest >=7.0.0
:pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Aug 03, 2023 5 - Production/Stable N/A
:pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Nov 29, 2023 5 - Production/Stable N/A
:pypi:`pytest-inmanta-extensions` Inmanta tests package Oct 13, 2023 5 - Production/Stable N/A
:pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules May 17, 2023 5 - Production/Stable N/A
:pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Nov 29, 2023 5 - Production/Stable N/A
:pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Jun 16, 2022 4 - Beta N/A
:pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A
:pypi:`pytest-insta` A practical snapshot testing plugin for pytest Nov 02, 2022 N/A pytest (>=7.2.0,<8.0.0)
@ -632,7 +634,7 @@ This list contains 1346 plugins.
:pypi:`pytest-integration-mark` Automatic integration test marking and excluding plugin for pytest May 22, 2023 N/A pytest (>=5.2)
:pypi:`pytest-interactive` A pytest plugin for console based interactive test selection just after the collection phase Nov 30, 2017 3 - Alpha N/A
:pypi:`pytest-intercept-remote` Pytest plugin for intercepting outgoing connection requests during pytest run. May 24, 2021 4 - Beta pytest (>=4.6)
:pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Sep 14, 2023 4 - Beta pytest
:pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Nov 29, 2023 4 - Beta pytest
:pypi:`pytest-invenio` Pytest fixtures for Invenio. Oct 31, 2023 5 - Production/Stable pytest <7.2.0,>=6
:pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0)
:pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A
@ -697,7 +699,7 @@ This list contains 1346 plugins.
:pypi:`pytest-lisa` Pytest plugin for organizing tests. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0)
:pypi:`pytest-listener` A simple network listener May 28, 2019 5 - Production/Stable pytest
:pypi:`pytest-litf` A pytest plugin that stream output in LITF format Jan 18, 2021 4 - Beta pytest (>=3.1.1)
:pypi:`pytest-litter` Pytest plugin which verifies that tests do not modify file trees. Aug 08, 2023 4 - Beta pytest >=6.1
:pypi:`pytest-litter` Pytest plugin which verifies that tests do not modify file trees. Nov 23, 2023 4 - Beta pytest >=6.1
:pypi:`pytest-live` Live results for pytest Mar 08, 2020 N/A pytest
:pypi:`pytest-local-badge` Generate local badges (shields) reporting your test suite status. Jan 15, 2023 N/A pytest (>=6.1.0)
:pypi:`pytest-localftpserver` A PyTest plugin which provides an FTP fixture for your tests Oct 14, 2023 5 - Production/Stable pytest
@ -747,7 +749,7 @@ This list contains 1346 plugins.
: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 May 27, 2023 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 Sep 27, 2023 N/A pytest
:pypi:`pytest-mh` Pytest multihost plugin Nov 21, 2023 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)
@ -838,7 +840,7 @@ This list contains 1346 plugins.
:pypi:`pytest-optional` include/exclude values of fixtures in pytest Oct 07, 2015 N/A N/A
:pypi:`pytest-optional-tests` Easy declaration of optional tests (i.e., that are not run by default) Jul 09, 2019 4 - Beta pytest (>=4.5.0)
:pypi:`pytest-orchestration` A pytest plugin for orchestrating tests Jul 18, 2019 N/A N/A
:pypi:`pytest-order` pytest plugin to run your tests in a specific order Mar 10, 2023 4 - Beta pytest (>=5.0) ; python_version < "3.10"
:pypi:`pytest-order` pytest plugin to run your tests in a specific order Nov 18, 2023 4 - Beta pytest >=5.0 ; python_version < "3.10"
: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
@ -863,6 +865,7 @@ This list contains 1346 plugins.
:pypi:`pytest-paste-config` Allow setting the path to a paste config file Sep 18, 2013 3 - Alpha N/A
:pypi:`pytest-patch` An automagic \`patch\` fixture that can patch objects directly or by name. Apr 29, 2023 3 - Alpha pytest (>=7.0.0)
:pypi:`pytest-patches` A contextmanager pytest fixture for handling multiple mock patches Aug 30, 2021 4 - Beta pytest (>=3.5.0)
:pypi:`pytest-patterns` pytest plugin to make testing complicated long string output easy to write and easy to debug Nov 17, 2023 4 - Beta N/A
:pypi:`pytest-pdb` pytest plugin which adds pdb helper commands related to pytest. Jul 31, 2018 N/A N/A
:pypi:`pytest-peach` pytest plugin for fuzzing with Peach API Security Apr 12, 2019 4 - Beta pytest (>=2.8.7)
:pypi:`pytest-pep257` py.test plugin for pep257 Jul 09, 2016 N/A N/A
@ -939,7 +942,7 @@ This list contains 1346 plugins.
:pypi:`pytest-pydocstyle` pytest plugin to run pydocstyle Jan 05, 2023 3 - Alpha N/A
:pypi:`pytest-pylint` pytest plugin to check source code with pylint Oct 06, 2023 5 - Production/Stable pytest >=7.0
:pypi:`pytest-pymysql-autorecord` Record PyMySQL queries and mock with the stored data. Sep 02, 2022 N/A N/A
:pypi:`pytest-pyodide` Pytest plugin for testing applications that use Pyodide Nov 04, 2023 N/A pytest
:pypi:`pytest-pyodide` Pytest plugin for testing applications that use Pyodide Nov 18, 2023 N/A pytest
:pypi:`pytest-pypi` Easily test your HTTP library against a local copy of pypi Mar 04, 2018 3 - Alpha N/A
:pypi:`pytest-pypom-navigation` Core engine for cookiecutter-qa and pytest-play packages Feb 18, 2019 4 - Beta pytest (>=3.0.7)
:pypi:`pytest-pyppeteer` A plugin to run pyppeteer in pytest Apr 28, 2022 N/A pytest (>=6.2.5,<7.0.0)
@ -957,7 +960,7 @@ This list contains 1346 plugins.
:pypi:`pytest-qaseio` Pytest plugin for Qase.io integration Sep 12, 2023 4 - Beta pytest (>=7.2.2,<8.0.0)
:pypi:`pytest-qasync` Pytest support for qasync. Jul 12, 2021 4 - Beta pytest (>=5.4.0)
:pypi:`pytest-qatouch` Pytest plugin for uploading test results to your QA Touch Testrun. Feb 14, 2023 4 - Beta pytest (>=6.2.0)
:pypi:`pytest-qgis` A pytest plugin for testing QGIS python plugins Jun 30, 2023 5 - Production/Stable pytest (>=6.2.5)
:pypi:`pytest-qgis` A pytest plugin for testing QGIS python plugins Nov 29, 2023 5 - Production/Stable pytest >=6.0
:pypi:`pytest-qml` Run QML Tests with pytest Dec 02, 2020 4 - Beta pytest (>=6.0.0)
:pypi:`pytest-qr` pytest plugin to generate test result QR codes Nov 25, 2021 4 - Beta N/A
:pypi:`pytest-qt` pytest support for PyQt and PySide applications Oct 25, 2022 5 - Production/Stable pytest (>=3.0.0)
@ -978,8 +981,8 @@ This list contains 1346 plugins.
: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 Dec 03, 2022 5 - Production/Stable pytest (>=3.0.0)
:pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable N/A
:pypi:`pytest-reana` Pytest fixtures for REANA. Sep 26, 2023 3 - Alpha N/A
:pypi:`pytest-recorder` Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. Mar 30, 2023 N/A 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
:pypi:`pytest-recording` A pytest plugin that allows you recording of network interactions via VCR.py Jul 31, 2023 4 - Beta pytest>=3.5.0
:pypi:`pytest-recordings` Provides pytest plugins for reporting request/response traffic, screenshots, and more to ReportPortal Aug 13, 2020 N/A N/A
:pypi:`pytest-redis` Redis fixtures and fixture factories for Pytest. Apr 19, 2023 5 - Production/Stable pytest (>=6.2)
@ -1020,10 +1023,10 @@ This list contains 1346 plugins.
:pypi:`pytest-reraise` Make multi-threaded pytest test cases fail when they should Sep 20, 2022 5 - Production/Stable pytest (>=4.6)
:pypi:`pytest-rerun` Re-run only changed files in specified branch Jul 08, 2019 N/A pytest (>=3.6)
:pypi:`pytest-rerun-all` Rerun testsuite for a certain time or iterations Nov 16, 2023 3 - Alpha pytest (>=7.0.0)
:pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Jul 05, 2023 5 - Production/Stable pytest (>=6.2)
: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. Aug 31, 2023 4 - Beta pytest
:pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Oct 05, 2023 N/A pytest ~=4.6 ; python_version == "2.7"
:pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Nov 22, 2023 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
@ -1064,22 +1067,22 @@ This list contains 1346 plugins.
:pypi:`pytest-saccharin` pytest-saccharin is a updated fork of pytest-sugar, a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly). Oct 31, 2022 3 - Alpha N/A
:pypi:`pytest-salt` Pytest Salt Plugin Jan 27, 2020 4 - Beta N/A
:pypi:`pytest-salt-containers` A Pytest plugin that builds and creates docker containers Nov 09, 2016 4 - Beta N/A
:pypi:`pytest-salt-factories` Pytest Salt Plugin Sep 27, 2023 4 - Beta pytest (>=6.0.0)
:pypi:`pytest-salt-factories` Pytest Salt Plugin Nov 25, 2023 4 - Beta pytest (>=6.0.0)
:pypi:`pytest-salt-from-filenames` Simple PyTest Plugin For Salt's Test Suite Specifically Jan 29, 2019 4 - Beta pytest (>=4.1)
:pypi:`pytest-salt-runtests-bridge` Simple PyTest Plugin For Salt's Test Suite Specifically Dec 05, 2019 4 - Beta pytest (>=4.1)
: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. Nov 17, 2023 5 - Production/Stable N/A
:pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Dec 01, 2023 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-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 May 28, 2023 5 - Production/Stable pytest>=6.0.0
:pypi:`pytest-selenium` pytest plugin for Selenium Nov 20, 2023 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. Nov 17, 2023 5 - Production/Stable N/A
:pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Dec 01, 2023 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
@ -1111,6 +1114,7 @@ This list contains 1346 plugins.
:pypi:`pytest-skipper` A plugin that selects only tests with changes in execution path Mar 26, 2017 3 - Alpha pytest (>=3.0.6)
:pypi:`pytest-skippy` Automatically skip tests that don't need to run! Jan 27, 2018 3 - Alpha pytest (>=2.3.4)
:pypi:`pytest-skip-slow` A pytest plugin to skip \`@pytest.mark.slow\` tests by default. Feb 09, 2023 N/A pytest>=6.2.0
:pypi:`pytest-skipuntil` A simple pytest plugin to skip flapping test with deadline Nov 25, 2023 4 - Beta pytest >=3.8.0
:pypi:`pytest-slack` Pytest to Slack reporting plugin Dec 15, 2020 5 - Production/Stable N/A
:pypi:`pytest-slow` A pytest plugin to skip \`@pytest.mark.slow\` tests by default. Sep 28, 2021 N/A N/A
:pypi:`pytest-slowest-first` Sort tests by their last duration, slowest first Dec 11, 2022 4 - Beta N/A
@ -1139,7 +1143,7 @@ This list contains 1346 plugins.
:pypi:`pytest-spark` pytest plugin to run the tests with support of pyspark. Feb 23, 2020 4 - Beta pytest
:pypi:`pytest-spawner` py.test plugin to spawn process and communicate with them. Jul 31, 2015 4 - Beta N/A
:pypi:`pytest-spec` Library pytest-spec is a pytest plugin to display test execution output like a SPECIFICATION. May 04, 2021 N/A N/A
:pypi:`pytest-spec2md` Library pytest-spec2md is a pytest plugin to create a markdown specification while running pytest. Sep 15, 2023 N/A pytest (>7.0)
:pypi:`pytest-spec2md` Library pytest-spec2md is a pytest plugin to create a markdown specification while running pytest. Nov 21, 2023 N/A pytest (>7.0)
:pypi:`pytest-speed` Modern benchmarking library for python with pytest integration. Jan 22, 2023 3 - Alpha pytest>=7
:pypi:`pytest-sphinx` Doctest plugin for pytest with support for Sphinx-specific doctest-directives Sep 06, 2022 4 - Beta pytest (>=7.0.0)
:pypi:`pytest-spiratest` Exports unit tests as test runs in SpiraTest/Team/Plan Feb 08, 2022 N/A N/A
@ -1150,8 +1154,8 @@ This list contains 1346 plugins.
:pypi:`pytest-splitio` Split.io SDK integration for e2e tests Sep 22, 2020 N/A pytest (<7,>=5.0)
: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 Oct 23, 2023 N/A pytest (>5.4.0,<8)
:pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Nov 15, 2023 N/A N/A
:pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Nov 25, 2023 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-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
@ -1178,6 +1182,7 @@ This list contains 1346 plugins.
:pypi:`pytest-stub` Stub packages, modules and attributes. Apr 28, 2020 5 - Production/Stable N/A
:pypi:`pytest-stubprocess` Provide stub implementations for subprocesses in Python tests Sep 17, 2018 3 - Alpha pytest (>=3.5.0)
:pypi:`pytest-study` A pytest plugin to organize long run tests (named studies) without interfering the regular tests Sep 26, 2017 3 - Alpha pytest (>=2.0)
:pypi:`pytest-subinterpreter` Run pytest in a subinterpreter Nov 25, 2023 N/A pytest>=7.0.0
:pypi:`pytest-subprocess` A plugin to fake subprocess for pytest Jan 28, 2023 5 - Production/Stable pytest (>=4.0.0)
:pypi:`pytest-subtesthack` A hack to explicitly set up and tear down fixtures. Jul 16, 2022 N/A N/A
:pypi:`pytest-subtests` unittest subTest() support and subtests fixture May 15, 2023 4 - Beta pytest (>=7.0)
@ -1217,7 +1222,7 @@ This list contains 1346 plugins.
: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)
:pypi:`pytest-testmon` selects tests affected by changed files and methods Nov 07, 2023 4 - Beta pytest <8,>=5
:pypi:`pytest-testmon` selects tests affected by changed files and methods Nov 23, 2023 4 - Beta pytest <8,>=5
:pypi:`pytest-testmon-dev` selects tests affected by changed files and methods Mar 30, 2023 4 - Beta pytest (<8,>=5)
:pypi:`pytest-testmon-oc` nOly selects tests affected by changed files and methods Jun 01, 2022 4 - Beta pytest (<8,>=5)
:pypi:`pytest-testmon-skip-libraries` selects tests affected by changed files and methods Mar 03, 2023 4 - Beta pytest (<8,>=5)
@ -1290,7 +1295,7 @@ This list contains 1346 plugins.
:pypi:`pytest-twisted` A twisted plugin for pytest. Oct 16, 2022 5 - Production/Stable pytest (>=2.3)
:pypi:`pytest-typechecker` Run type checkers on specified test files Feb 04, 2022 N/A pytest (>=6.2.5,<7.0.0)
:pypi:`pytest-typhoon-config` A Typhoon HIL plugin that facilitates test parameter configuration at runtime Apr 07, 2022 5 - Production/Stable N/A
:pypi:`pytest-typhoon-polarion` Typhoontest plugin for Siemens Polarion Nov 17, 2023 4 - Beta N/A
:pypi:`pytest-typhoon-polarion` Typhoontest plugin for Siemens Polarion Dec 01, 2023 4 - Beta N/A
:pypi:`pytest-typhoon-xray` Typhoon HIL plugin for pytest Aug 15, 2023 4 - Beta N/A
:pypi:`pytest-tytest` Typhoon HIL plugin for pytest May 25, 2020 4 - Beta pytest (>=5.4.2)
:pypi:`pytest-ubersmith` Easily mock calls to ubersmith at the \`requests\` level. Apr 13, 2015 N/A N/A
@ -1315,8 +1320,8 @@ This list contains 1346 plugins.
: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-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 Aug 04, 2020 4 - Beta pytest
:pypi:`pytest-ver` Pytest module with Verification Protocol, Verification Report and Trace Matrix Nov 18, 2023 4 - Beta pytest
:pypi:`pytest-venv` py.test fixture for creating a virtual environment Nov 23, 2023 4 - Beta pytest
:pypi:`pytest-ver` Pytest module with Verification Protocol, Verification Report and Trace Matrix Nov 23, 2023 4 - Beta pytest
:pypi:`pytest-verbose-parametrize` More descriptive output for parametrized py.test tests May 28, 2019 5 - Production/Stable pytest
:pypi:`pytest-vimqf` A simple pytest plugin that will shrink pytest output when specified, to fit vim quickfix window. Feb 08, 2021 4 - Beta pytest (>=6.2.2,<7.0.0)
:pypi:`pytest-virtualenv` Virtualenv fixture for py.test May 28, 2019 5 - Production/Stable pytest
@ -1346,7 +1351,7 @@ This list contains 1346 plugins.
:pypi:`pytest-wiremock` A pytest plugin for programmatically using wiremock in integration tests Mar 27, 2022 N/A pytest (>=7.1.1,<8.0.0)
:pypi:`pytest-with-docker` pytest with docker helpers. Nov 09, 2021 N/A pytest
:pypi:`pytest-workflow` A pytest plugin for configuring workflow/pipeline tests using YAML files Jan 13, 2023 5 - Production/Stable pytest (>=7.0.0)
:pypi:`pytest-xdist` pytest xdist plugin for distributed testing, most importantly across multiple CPUs Nov 11, 2023 5 - Production/Stable pytest >=6.2.0
:pypi:`pytest-xdist` pytest xdist plugin for distributed testing, most importantly across multiple CPUs Nov 21, 2023 5 - Production/Stable pytest >=6.2.0
:pypi:`pytest-xdist-debug-for-graingert` pytest xdist plugin for distributed testing and loop-on-failing modes Jul 24, 2019 5 - Production/Stable pytest (>=4.4.0)
:pypi:`pytest-xdist-forked` forked from pytest-xdist Feb 10, 2020 5 - Production/Stable pytest (>=4.4.0)
:pypi:`pytest-xdist-tracker` pytest plugin helps to reproduce failures for particular xdist node Nov 18, 2021 3 - Alpha pytest (>=3.5.1)
@ -1365,7 +1370,7 @@ This list contains 1346 plugins.
:pypi:`pytest-xvfb` A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests. May 29, 2023 4 - Beta pytest (>=2.8.1)
:pypi:`pytest-xvirt` A pytest plugin to virtualize test. For example to transparently running them on a remote box. Oct 01, 2023 4 - Beta pytest >=7.1.0
:pypi:`pytest-yaml` This plugin is used to load yaml output to your test using pytest framework. Oct 05, 2018 N/A pytest
:pypi:`pytest-yaml-sanmu` pytest plugin for generating test cases by yaml Jul 03, 2023 N/A pytest>=7.4.0
:pypi:`pytest-yaml-sanmu` pytest plugin for generating test cases by yaml Nov 30, 2023 N/A pytest>=7.4.0
:pypi:`pytest-yamltree` Create or check file/directory trees described by YAML Mar 02, 2020 4 - Beta pytest (>=3.1.1)
:pypi:`pytest-yamlwsgi` Run tests against wsgi apps defined in yaml May 11, 2010 N/A N/A
:pypi:`pytest-yaml-yoyo` http/https API run by yaml Jun 19, 2023 N/A pytest (>=7.2.0)
@ -1694,7 +1699,7 @@ This list contains 1346 plugins.
Pytest fixtures to assert anything and something
:pypi:`pytest-aoc`
*last release*: Sep 19, 2023,
*last release*: Dec 02, 2023,
*status*: 5 - Production/Stable,
*requires*: pytest ; extra == 'test'
@ -1771,7 +1776,7 @@ This list contains 1346 plugins.
pyest results colection plugin
:pypi:`pytest-arraydiff`
*last release*: Nov 15, 2023,
*last release*: Nov 27, 2023,
*status*: 4 - Beta,
*requires*: pytest >=4.6
@ -1883,14 +1888,14 @@ This list contains 1346 plugins.
Pytest fixtures for async generators
:pypi:`pytest-asyncio`
*last release*: Nov 16, 2023,
*last release*: Nov 27, 2023,
*status*: 4 - Beta,
*requires*: pytest (>=7.0.0)
Pytest support for asyncio
:pypi:`pytest-asyncio-cooperative`
*last release*: Aug 06, 2023,
*last release*: Nov 30, 2023,
*status*: N/A,
*requires*: N/A
@ -1918,7 +1923,7 @@ This list contains 1346 plugins.
Database testing fixtures using the SQLAlchemy asyncio API
:pypi:`pytest-atf-allure`
*last release*: Oct 22, 2023,
*last release*: Nov 29, 2023,
*status*: N/A,
*requires*: pytest (>=7.4.2,<8.0.0)
@ -2597,7 +2602,7 @@ This list contains 1346 plugins.
A pytest plugin to send a report and printing summary of tests.
:pypi:`pytest-choose`
*last release*: Nov 02, 2023,
*last release*: Nov 30, 2023,
*status*: N/A,
*requires*: pytest >=7.0.0
@ -3801,7 +3806,7 @@ This list contains 1346 plugins.
pytest plugin for dogu report
:pypi:`pytest-dogu-sdk`
*last release*: Aug 04, 2023,
*last release*: Nov 20, 2023,
*status*: N/A,
*requires*: N/A
@ -4018,56 +4023,56 @@ This list contains 1346 plugins.
Send execution result email
:pypi:`pytest-embedded`
*last release*: Nov 07, 2023,
*last release*: Nov 27, 2023,
*status*: 5 - Production/Stable,
*requires*: pytest>=7.0
A pytest plugin that designed for embedded testing.
:pypi:`pytest-embedded-arduino`
*last release*: Nov 07, 2023,
*last release*: Nov 27, 2023,
*status*: 5 - Production/Stable,
*requires*: N/A
Make pytest-embedded plugin work with Arduino.
:pypi:`pytest-embedded-idf`
*last release*: Nov 07, 2023,
*last release*: Nov 27, 2023,
*status*: 5 - Production/Stable,
*requires*: N/A
Make pytest-embedded plugin work with ESP-IDF.
:pypi:`pytest-embedded-jtag`
*last release*: Nov 07, 2023,
*last release*: Nov 27, 2023,
*status*: 5 - Production/Stable,
*requires*: N/A
Make pytest-embedded plugin work with JTAG.
:pypi:`pytest-embedded-qemu`
*last release*: Nov 07, 2023,
*last release*: Nov 27, 2023,
*status*: 5 - Production/Stable,
*requires*: N/A
Make pytest-embedded plugin work with QEMU.
:pypi:`pytest-embedded-serial`
*last release*: Nov 07, 2023,
*last release*: Nov 27, 2023,
*status*: 5 - Production/Stable,
*requires*: N/A
Make pytest-embedded plugin work with Serial.
:pypi:`pytest-embedded-serial-esp`
*last release*: Nov 07, 2023,
*last release*: Nov 27, 2023,
*status*: 5 - Production/Stable,
*requires*: N/A
Make pytest-embedded plugin work with Espressif target boards.
:pypi:`pytest-embedded-wokwi`
*last release*: Nov 07, 2023,
*last release*: Nov 27, 2023,
*status*: 5 - Production/Stable,
*requires*: N/A
@ -4137,7 +4142,7 @@ This list contains 1346 plugins.
Improvements for pytest (rejected upstream)
:pypi:`pytest-env`
*last release*: Oct 30, 2023,
*last release*: Nov 28, 2023,
*status*: 5 - Production/Stable,
*requires*: pytest>=7.4.3
@ -4837,9 +4842,9 @@ This list contains 1346 plugins.
:pypi:`pytest-fzf`
*last release*: Nov 15, 2023,
*status*: 1 - Planning,
*requires*: pytest >=7.1.2
*last release*: Nov 28, 2023,
*status*: 4 - Beta,
*requires*: pytest >=6.0.0
fzf-based test selector for pytest
@ -4864,6 +4869,13 @@ This list contains 1346 plugins.
Uses gcov to measure test coverage of a C library
:pypi:`pytest-gee`
*last release*: Nov 22, 2023,
*status*: 3 - Alpha,
*requires*: pytest; extra == 'test'
The Python plugin for your GEE based packages.
:pypi:`pytest-gevent`
*last release*: Feb 25, 2020,
*status*: N/A,
@ -4893,7 +4905,7 @@ This list contains 1346 plugins.
For finding/executing Ghost Inspector tests
:pypi:`pytest-girder`
*last release*: Nov 08, 2023,
*last release*: Nov 20, 2023,
*status*: N/A,
*requires*: N/A
@ -5137,6 +5149,13 @@ This list contains 1346 plugins.
Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report
:pypi:`pytest-history`
*last release*: Nov 20, 2023,
*status*: N/A,
*requires*: pytest (>=7.4.3,<8.0.0)
Pytest plugin to keep a history of your pytest runs
:pypi:`pytest-home`
*last release*: Oct 09, 2023,
*status*: 5 - Production/Stable,
@ -5152,7 +5171,7 @@ This list contains 1346 plugins.
A pytest plugin for use with homeassistant custom components.
:pypi:`pytest-homeassistant-custom-component`
*last release*: Nov 11, 2023,
*last release*: Dec 01, 2023,
*status*: 3 - Alpha,
*requires*: pytest ==7.4.3
@ -5173,7 +5192,7 @@ This list contains 1346 plugins.
Report on tests that honor constraints, and guard against regressions
:pypi:`pytest-hot-reloading`
*last release*: Jun 23, 2023,
*last release*: Dec 01, 2023,
*status*: N/A,
*requires*: N/A
@ -5425,7 +5444,7 @@ This list contains 1346 plugins.
:pypi:`pytest-image-snapshot`
*last release*: Nov 16, 2023,
*last release*: Dec 01, 2023,
*status*: 4 - Beta,
*requires*: pytest >=3.5.0
@ -5488,7 +5507,7 @@ This list contains 1346 plugins.
A pytest plugin for writing inline tests.
:pypi:`pytest-inmanta`
*last release*: Aug 03, 2023,
*last release*: Nov 29, 2023,
*status*: 5 - Production/Stable,
*requires*: N/A
@ -5502,7 +5521,7 @@ This list contains 1346 plugins.
Inmanta tests package
:pypi:`pytest-inmanta-lsm`
*last release*: May 17, 2023,
*last release*: Nov 29, 2023,
*status*: 5 - Production/Stable,
*requires*: N/A
@ -5572,7 +5591,7 @@ This list contains 1346 plugins.
Pytest plugin for intercepting outgoing connection requests during pytest run.
:pypi:`pytest-interface-tester`
*last release*: Sep 14, 2023,
*last release*: Nov 29, 2023,
*status*: 4 - Beta,
*requires*: pytest
@ -6027,7 +6046,7 @@ This list contains 1346 plugins.
A pytest plugin that stream output in LITF format
:pypi:`pytest-litter`
*last release*: Aug 08, 2023,
*last release*: Nov 23, 2023,
*status*: 4 - Beta,
*requires*: pytest >=6.1
@ -6377,7 +6396,7 @@ This list contains 1346 plugins.
Custom metrics report for pytest
:pypi:`pytest-mh`
*last release*: Sep 27, 2023,
*last release*: Nov 21, 2023,
*status*: N/A,
*requires*: pytest
@ -7014,9 +7033,9 @@ This list contains 1346 plugins.
A pytest plugin for orchestrating tests
:pypi:`pytest-order`
*last release*: Mar 10, 2023,
*last release*: Nov 18, 2023,
*status*: 4 - Beta,
*requires*: pytest (>=5.0) ; python_version < "3.10"
*requires*: pytest >=5.0 ; python_version < "3.10"
pytest plugin to run your tests in a specific order
@ -7188,6 +7207,13 @@ This list contains 1346 plugins.
A contextmanager pytest fixture for handling multiple mock patches
:pypi:`pytest-patterns`
*last release*: Nov 17, 2023,
*status*: 4 - Beta,
*requires*: N/A
pytest plugin to make testing complicated long string output easy to write and easy to debug
:pypi:`pytest-pdb`
*last release*: Jul 31, 2018,
*status*: N/A,
@ -7721,7 +7747,7 @@ This list contains 1346 plugins.
Record PyMySQL queries and mock with the stored data.
:pypi:`pytest-pyodide`
*last release*: Nov 04, 2023,
*last release*: Nov 18, 2023,
*status*: N/A,
*requires*: pytest
@ -7847,9 +7873,9 @@ This list contains 1346 plugins.
Pytest plugin for uploading test results to your QA Touch Testrun.
:pypi:`pytest-qgis`
*last release*: Jun 30, 2023,
*last release*: Nov 29, 2023,
*status*: 5 - Production/Stable,
*requires*: pytest (>=6.2.5)
*requires*: pytest >=6.0
A pytest plugin for testing QGIS python plugins
@ -7994,14 +8020,14 @@ This list contains 1346 plugins.
Test your README.md file
:pypi:`pytest-reana`
*last release*: Sep 26, 2023,
*last release*: Nov 30, 2023,
*status*: 3 - Alpha,
*requires*: N/A
Pytest fixtures for REANA.
:pypi:`pytest-recorder`
*last release*: Mar 30, 2023,
*last release*: Nov 21, 2023,
*status*: N/A,
*requires*: N/A
@ -8288,9 +8314,9 @@ This list contains 1346 plugins.
Rerun testsuite for a certain time or iterations
:pypi:`pytest-rerunfailures`
*last release*: Jul 05, 2023,
*last release*: Nov 22, 2023,
*status*: 5 - Production/Stable,
*requires*: pytest (>=6.2)
*requires*: pytest >=7
pytest plugin to re-run tests to eliminate flaky failures
@ -8309,7 +8335,7 @@ This list contains 1346 plugins.
Pytest fixture for recording and replaying serial port traffic.
:pypi:`pytest-resilient-circuits`
*last release*: Oct 05, 2023,
*last release*: Nov 22, 2023,
*status*: N/A,
*requires*: pytest ~=4.6 ; python_version == "2.7"
@ -8596,7 +8622,7 @@ This list contains 1346 plugins.
A Pytest plugin that builds and creates docker containers
:pypi:`pytest-salt-factories`
*last release*: Sep 27, 2023,
*last release*: Nov 25, 2023,
*status*: 4 - Beta,
*requires*: pytest (>=6.0.0)
@ -8638,7 +8664,7 @@ This list contains 1346 plugins.
:pypi:`pytest-sbase`
*last release*: Nov 17, 2023,
*last release*: Dec 01, 2023,
*status*: 5 - Production/Stable,
*requires*: N/A
@ -8687,7 +8713,7 @@ This list contains 1346 plugins.
A pytest plugin which allows to (de-)select tests from a file.
:pypi:`pytest-selenium`
*last release*: May 28, 2023,
*last release*: Nov 20, 2023,
*status*: 5 - Production/Stable,
*requires*: pytest>=6.0.0
@ -8701,7 +8727,7 @@ This list contains 1346 plugins.
pytest plugin to automatically capture screenshots upon selenium webdriver events
:pypi:`pytest-seleniumbase`
*last release*: Nov 17, 2023,
*last release*: Dec 01, 2023,
*status*: 5 - Production/Stable,
*requires*: N/A
@ -8924,6 +8950,13 @@ This list contains 1346 plugins.
A pytest plugin to skip \`@pytest.mark.slow\` tests by default.
:pypi:`pytest-skipuntil`
*last release*: Nov 25, 2023,
*status*: 4 - Beta,
*requires*: pytest >=3.8.0
A simple pytest plugin to skip flapping test with deadline
:pypi:`pytest-slack`
*last release*: Dec 15, 2020,
*status*: 5 - Production/Stable,
@ -9121,7 +9154,7 @@ This list contains 1346 plugins.
Library pytest-spec is a pytest plugin to display test execution output like a SPECIFICATION.
:pypi:`pytest-spec2md`
*last release*: Sep 15, 2023,
*last release*: Nov 21, 2023,
*status*: N/A,
*requires*: pytest (>7.0)
@ -9198,14 +9231,14 @@ This list contains 1346 plugins.
:pypi:`pytest-splunk-addon`
*last release*: Oct 23, 2023,
*last release*: Nov 25, 2023,
*status*: N/A,
*requires*: pytest (>5.4.0,<8)
A Dynamic test tool for Splunk Apps and Add-ons
:pypi:`pytest-splunk-addon-ui-smartx`
*last release*: Nov 15, 2023,
*last release*: Dec 01, 2023,
*status*: N/A,
*requires*: N/A
@ -9393,6 +9426,13 @@ This list contains 1346 plugins.
A pytest plugin to organize long run tests (named studies) without interfering the regular tests
:pypi:`pytest-subinterpreter`
*last release*: Nov 25, 2023,
*status*: N/A,
*requires*: pytest>=7.0.0
Run pytest in a subinterpreter
:pypi:`pytest-subprocess`
*last release*: Jan 28, 2023,
*status*: 5 - Production/Stable,
@ -9667,7 +9707,7 @@ This list contains 1346 plugins.
pytest reporting plugin for testlink
:pypi:`pytest-testmon`
*last release*: Nov 07, 2023,
*last release*: Nov 23, 2023,
*status*: 4 - Beta,
*requires*: pytest <8,>=5
@ -10178,7 +10218,7 @@ This list contains 1346 plugins.
A Typhoon HIL plugin that facilitates test parameter configuration at runtime
:pypi:`pytest-typhoon-polarion`
*last release*: Nov 17, 2023,
*last release*: Dec 01, 2023,
*status*: 4 - Beta,
*requires*: N/A
@ -10353,14 +10393,14 @@ This list contains 1346 plugins.
:pypi:`pytest-venv`
*last release*: Aug 04, 2020,
*last release*: Nov 23, 2023,
*status*: 4 - Beta,
*requires*: pytest
py.test fixture for creating a virtual environment
:pypi:`pytest-ver`
*last release*: Nov 18, 2023,
*last release*: Nov 23, 2023,
*status*: 4 - Beta,
*requires*: pytest
@ -10570,7 +10610,7 @@ This list contains 1346 plugins.
A pytest plugin for configuring workflow/pipeline tests using YAML files
:pypi:`pytest-xdist`
*last release*: Nov 11, 2023,
*last release*: Nov 21, 2023,
*status*: 5 - Production/Stable,
*requires*: pytest >=6.2.0
@ -10703,7 +10743,7 @@ This list contains 1346 plugins.
This plugin is used to load yaml output to your test using pytest framework.
:pypi:`pytest-yaml-sanmu`
*last release*: Jul 03, 2023,
*last release*: Nov 30, 2023,
*status*: N/A,
*requires*: pytest>=7.4.0

View File

@ -612,10 +612,30 @@ Hooks
**Tutorial**: :ref:`writing-plugins`
.. currentmodule:: _pytest.hookspec
Reference to all hooks which can be implemented by :ref:`conftest.py files <localplugin>` and :ref:`plugins <plugins>`.
@pytest.hookimpl
~~~~~~~~~~~~~~~~
.. function:: pytest.hookimpl
:decorator:
pytest's decorator for marking functions as hook implementations.
See :ref:`writinghooks` and :func:`pluggy.HookimplMarker`.
@pytest.hookspec
~~~~~~~~~~~~~~~~
.. function:: pytest.hookspec
:decorator:
pytest's decorator for marking functions as hook specifications.
See :ref:`declaringhooks` and :func:`pluggy.HookspecMarker`.
.. currentmodule:: _pytest.hookspec
Bootstrapping hooks
~~~~~~~~~~~~~~~~~~~

View File

@ -1,6 +1,5 @@
[build-system]
requires = [
# sync with setup.py until we discard non-pep-517/518
"setuptools>=45.0",
"setuptools-scm[toml]>=6.2.3",
]

View File

@ -1,4 +0,0 @@
from setuptools import setup
if __name__ == "__main__":
setup()

View File

@ -15,14 +15,17 @@
import collections as _collections
import dataclasses as _dataclasses
import re
import sys as _sys
import types as _types
from io import StringIO as _StringIO
from typing import Any
from typing import Callable
from typing import Dict
from typing import IO
from typing import Iterator
from typing import List
from typing import Optional
from typing import Set
from typing import Tuple
class _safe_key:
@ -58,15 +61,13 @@ def _safe_tuple(t):
class PrettyPrinter:
def __init__(
self,
indent=1,
width=80,
depth=None,
stream=None,
indent: int = 4,
width: int = 80,
depth: Optional[int] = None,
*,
compact=False,
sort_dicts=True,
underscore_numbers=False,
):
sort_dicts: bool = True,
underscore_numbers: bool = False,
) -> None:
"""Handle pretty printing operations onto a stream using a set of
configured parameters.
@ -79,13 +80,6 @@ class PrettyPrinter:
depth
The maximum depth to print out nested structures.
stream
The desired output stream. If omitted (or false), the standard
output stream available at construction will be used.
compact
If true, several items will be combined in one line.
sort_dicts
If true, dict keys are sorted.
@ -101,32 +95,33 @@ class PrettyPrinter:
self._depth = depth
self._indent_per_level = indent
self._width = width
if stream is not None:
self._stream = stream
else:
self._stream = _sys.stdout
self._compact = bool(compact)
self._sort_dicts = sort_dicts
self._underscore_numbers = underscore_numbers
def pformat(self, object: Any) -> str:
sio = _StringIO()
self._format(object, sio, 0, 0, {}, 0)
self._format(object, sio, 0, 0, set(), 0)
return sio.getvalue()
def _format(self, object, stream, indent, allowance, context, level):
def _format(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
objid = id(object)
if objid in context:
stream.write(_recursion(object))
self._recursive = True
self._readable = False
return
p = self._dispatch.get(type(object).__repr__, None)
if p is not None:
context[objid] = 1
context.add(objid)
p(self, object, stream, indent, allowance, context, level + 1)
del context[objid]
context.remove(objid)
elif (
_dataclasses.is_dataclass(object)
and not isinstance(object, type)
@ -136,17 +131,24 @@ class PrettyPrinter:
hasattr(object.__repr__, "__wrapped__")
and "__create_fn__" in object.__repr__.__wrapped__.__qualname__
):
context[objid] = 1
context.add(objid)
self._pprint_dataclass(
object, stream, indent, allowance, context, level + 1
)
del context[objid]
context.remove(objid)
else:
stream.write(self._repr(object, context, level))
def _pprint_dataclass(self, object, stream, indent, allowance, context, level):
def _pprint_dataclass(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
cls_name = object.__class__.__name__
indent += len(cls_name) + 1
items = [
(f.name, getattr(object, f.name))
for f in _dataclasses.fields(object)
@ -158,63 +160,87 @@ class PrettyPrinter:
_dispatch: Dict[
Callable[..., str],
Callable[["PrettyPrinter", Any, IO[str], int, int, Dict[int, int], int], str],
Callable[["PrettyPrinter", Any, IO[str], int, int, Set[int], int], None],
] = {}
def _pprint_dict(self, object, stream, indent, allowance, context, level):
def _pprint_dict(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
write = stream.write
write("{")
if self._indent_per_level > 1:
write((self._indent_per_level - 1) * " ")
length = len(object)
if length:
if self._sort_dicts:
items = sorted(object.items(), key=_safe_tuple)
else:
items = object.items()
self._format_dict_items(
items, stream, indent, allowance + 1, context, level
)
if self._sort_dicts:
items = sorted(object.items(), key=_safe_tuple)
else:
items = object.items()
self._format_dict_items(items, stream, indent, allowance, context, level)
write("}")
_dispatch[dict.__repr__] = _pprint_dict
def _pprint_ordered_dict(self, object, stream, indent, allowance, context, level):
def _pprint_ordered_dict(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
if not len(object):
stream.write(repr(object))
return
cls = object.__class__
stream.write(cls.__name__ + "(")
self._format(
list(object.items()),
stream,
indent + len(cls.__name__) + 1,
allowance + 1,
context,
level,
)
self._pprint_dict(object, stream, indent, allowance, context, level)
stream.write(")")
_dispatch[_collections.OrderedDict.__repr__] = _pprint_ordered_dict
def _pprint_list(self, object, stream, indent, allowance, context, level):
def _pprint_list(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
stream.write("[")
self._format_items(object, stream, indent, allowance + 1, context, level)
self._format_items(object, stream, indent, allowance, context, level)
stream.write("]")
_dispatch[list.__repr__] = _pprint_list
def _pprint_tuple(self, object, stream, indent, allowance, context, level):
def _pprint_tuple(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
stream.write("(")
endchar = ",)" if len(object) == 1 else ")"
self._format_items(
object, stream, indent, allowance + len(endchar), context, level
)
stream.write(endchar)
self._format_items(object, stream, indent, allowance, context, level)
stream.write(")")
_dispatch[tuple.__repr__] = _pprint_tuple
def _pprint_set(self, object, stream, indent, allowance, context, level):
def _pprint_set(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
if not len(object):
stream.write(repr(object))
return
@ -225,17 +251,22 @@ class PrettyPrinter:
else:
stream.write(typ.__name__ + "({")
endchar = "})"
indent += len(typ.__name__) + 1
object = sorted(object, key=_safe_key)
self._format_items(
object, stream, indent, allowance + len(endchar), context, level
)
self._format_items(object, stream, indent, allowance, context, level)
stream.write(endchar)
_dispatch[set.__repr__] = _pprint_set
_dispatch[frozenset.__repr__] = _pprint_set
def _pprint_str(self, object, stream, indent, allowance, context, level):
def _pprint_str(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
write = stream.write
if not len(object):
write(repr(object))
@ -286,7 +317,15 @@ class PrettyPrinter:
_dispatch[str.__repr__] = _pprint_str
def _pprint_bytes(self, object, stream, indent, allowance, context, level):
def _pprint_bytes(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
write = stream.write
if len(object) <= 4:
write(repr(object))
@ -307,7 +346,15 @@ class PrettyPrinter:
_dispatch[bytes.__repr__] = _pprint_bytes
def _pprint_bytearray(self, object, stream, indent, allowance, context, level):
def _pprint_bytearray(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
write = stream.write
write("bytearray(")
self._pprint_bytes(
@ -317,23 +364,36 @@ class PrettyPrinter:
_dispatch[bytearray.__repr__] = _pprint_bytearray
def _pprint_mappingproxy(self, object, stream, indent, allowance, context, level):
def _pprint_mappingproxy(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
stream.write("mappingproxy(")
self._format(object.copy(), stream, indent + 13, allowance + 1, context, level)
self._format(object.copy(), stream, indent, allowance, context, level)
stream.write(")")
_dispatch[_types.MappingProxyType.__repr__] = _pprint_mappingproxy
def _pprint_simplenamespace(
self, object, stream, indent, allowance, context, level
):
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
if type(object) is _types.SimpleNamespace:
# The SimpleNamespace repr is "namespace" instead of the class
# name, so we do the same here. For subclasses; use the class name.
cls_name = "namespace"
else:
cls_name = object.__class__.__name__
indent += len(cls_name) + 1
items = object.__dict__.items()
stream.write(cls_name + "(")
self._format_namespace_items(items, stream, indent, allowance, context, level)
@ -341,33 +401,47 @@ class PrettyPrinter:
_dispatch[_types.SimpleNamespace.__repr__] = _pprint_simplenamespace
def _format_dict_items(self, items, stream, indent, allowance, context, level):
write = stream.write
indent += self._indent_per_level
delimnl = ",\n" + " " * indent
last_index = len(items) - 1
for i, (key, ent) in enumerate(items):
last = i == last_index
rep = self._repr(key, context, level)
write(rep)
write(": ")
self._format(
ent,
stream,
indent + len(rep) + 2,
allowance if last else 1,
context,
level,
)
if not last:
write(delimnl)
def _format_dict_items(
self,
items: List[Tuple[Any, Any]],
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
if not items:
return
def _format_namespace_items(self, items, stream, indent, allowance, context, level):
write = stream.write
delimnl = ",\n" + " " * indent
last_index = len(items) - 1
for i, (key, ent) in enumerate(items):
last = i == last_index
item_indent = indent + self._indent_per_level
delimnl = "\n" + " " * item_indent
for key, ent in items:
write(delimnl)
write(self._repr(key, context, level))
write(": ")
self._format(ent, stream, item_indent, 1, context, level)
write(",")
write("\n" + " " * indent)
def _format_namespace_items(
self,
items: List[Tuple[Any, Any]],
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
if not items:
return
write = stream.write
item_indent = indent + self._indent_per_level
delimnl = "\n" + " " * item_indent
for key, ent in items:
write(delimnl)
write(key)
write("=")
if id(ent) in context:
@ -378,174 +452,185 @@ class PrettyPrinter:
self._format(
ent,
stream,
indent + len(key) + 1,
allowance if last else 1,
item_indent + len(key) + 1,
1,
context,
level,
)
if not last:
write(delimnl)
def _format_items(self, items, stream, indent, allowance, context, level):
write = stream.write
indent += self._indent_per_level
if self._indent_per_level > 1:
write((self._indent_per_level - 1) * " ")
delimnl = ",\n" + " " * indent
delim = ""
width = max_width = self._width - indent + 1
it = iter(items)
try:
next_ent = next(it)
except StopIteration:
write(",")
write("\n" + " " * indent)
def _format_items(
self,
items: List[Any],
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
if not items:
return
last = False
while not last:
ent = next_ent
try:
next_ent = next(it)
except StopIteration:
last = True
max_width -= allowance
width -= allowance
if self._compact:
rep = self._repr(ent, context, level)
w = len(rep) + 2
if width < w:
width = max_width
if delim:
delim = delimnl
if width >= w:
width -= w
write(delim)
delim = ", "
write(rep)
continue
write(delim)
delim = delimnl
self._format(ent, stream, indent, allowance if last else 1, context, level)
def _repr(self, object, context, level):
repr, readable, recursive = self.format(
object, context.copy(), self._depth, level
)
if not readable:
self._readable = False
if recursive:
self._recursive = True
return repr
write = stream.write
item_indent = indent + self._indent_per_level
delimnl = "\n" + " " * item_indent
def format(self, object, context, maxlevels, level):
"""Format object for a specific context, returning a string
and flags indicating whether the representation is 'readable'
and whether the object represents a recursive construct.
"""
for item in items:
write(delimnl)
self._format(item, stream, item_indent, 1, context, level)
write(",")
write("\n" + " " * indent)
def _repr(self, object: Any, context: Set[int], level: int) -> str:
return self.format(object, context.copy(), self._depth, level)
def format(
self, object: Any, context: Set[int], maxlevels: Optional[int], level: int
) -> str:
return self._safe_repr(object, context, maxlevels, level)
def _pprint_default_dict(self, object, stream, indent, allowance, context, level):
if not len(object):
stream.write(repr(object))
return
def _pprint_default_dict(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
rdf = self._repr(object.default_factory, context, level)
cls = object.__class__
indent += len(cls.__name__) + 1
stream.write(f"{cls.__name__}({rdf},\n{' ' * indent}")
self._pprint_dict(object, stream, indent, allowance + 1, context, level)
stream.write(f"{object.__class__.__name__}({rdf}, ")
self._pprint_dict(object, stream, indent, allowance, context, level)
stream.write(")")
_dispatch[_collections.defaultdict.__repr__] = _pprint_default_dict
def _pprint_counter(self, object, stream, indent, allowance, context, level):
if not len(object):
stream.write(repr(object))
return
cls = object.__class__
stream.write(cls.__name__ + "({")
if self._indent_per_level > 1:
stream.write((self._indent_per_level - 1) * " ")
items = object.most_common()
self._format_dict_items(
items, stream, indent + len(cls.__name__) + 1, allowance + 2, context, level
)
stream.write("})")
def _pprint_counter(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
stream.write(object.__class__.__name__ + "(")
if object:
stream.write("{")
items = object.most_common()
self._format_dict_items(items, stream, indent, allowance, context, level)
stream.write("}")
stream.write(")")
_dispatch[_collections.Counter.__repr__] = _pprint_counter
def _pprint_chain_map(self, object, stream, indent, allowance, context, level):
if not len(object.maps):
def _pprint_chain_map(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
if not len(object.maps) or (len(object.maps) == 1 and not len(object.maps[0])):
stream.write(repr(object))
return
cls = object.__class__
stream.write(cls.__name__ + "(")
indent += len(cls.__name__) + 1
for i, m in enumerate(object.maps):
if i == len(object.maps) - 1:
self._format(m, stream, indent, allowance + 1, context, level)
stream.write(")")
else:
self._format(m, stream, indent, 1, context, level)
stream.write(",\n" + " " * indent)
stream.write(object.__class__.__name__ + "(")
self._format_items(object.maps, stream, indent, allowance, context, level)
stream.write(")")
_dispatch[_collections.ChainMap.__repr__] = _pprint_chain_map
def _pprint_deque(self, object, stream, indent, allowance, context, level):
if not len(object):
stream.write(repr(object))
return
cls = object.__class__
stream.write(cls.__name__ + "(")
indent += len(cls.__name__) + 1
def _pprint_deque(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
stream.write(object.__class__.__name__ + "(")
if object.maxlen is not None:
stream.write("maxlen=%d, " % object.maxlen)
stream.write("[")
if object.maxlen is None:
self._format_items(object, stream, indent, allowance + 2, context, level)
stream.write("])")
else:
self._format_items(object, stream, indent, 2, context, level)
rml = self._repr(object.maxlen, context, level)
stream.write(f"],\n{' ' * indent}maxlen={rml})")
self._format_items(object, stream, indent, allowance + 1, context, level)
stream.write("])")
_dispatch[_collections.deque.__repr__] = _pprint_deque
def _pprint_user_dict(self, object, stream, indent, allowance, context, level):
def _pprint_user_dict(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
self._format(object.data, stream, indent, allowance, context, level - 1)
_dispatch[_collections.UserDict.__repr__] = _pprint_user_dict
def _pprint_user_list(self, object, stream, indent, allowance, context, level):
def _pprint_user_list(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
self._format(object.data, stream, indent, allowance, context, level - 1)
_dispatch[_collections.UserList.__repr__] = _pprint_user_list
def _pprint_user_string(self, object, stream, indent, allowance, context, level):
def _pprint_user_string(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
self._format(object.data, stream, indent, allowance, context, level - 1)
_dispatch[_collections.UserString.__repr__] = _pprint_user_string
def _safe_repr(self, object, context, maxlevels, level):
# Return triple (repr_string, isreadable, isrecursive).
def _safe_repr(
self, object: Any, context: Set[int], maxlevels: Optional[int], level: int
) -> str:
typ = type(object)
if typ in _builtin_scalars:
return repr(object), True, False
return repr(object)
r = getattr(typ, "__repr__", None)
if issubclass(typ, int) and r is int.__repr__:
if self._underscore_numbers:
return f"{object:_d}", True, False
return f"{object:_d}"
else:
return repr(object), True, False
return repr(object)
if issubclass(typ, dict) and r is dict.__repr__:
if not object:
return "{}", True, False
return "{}"
objid = id(object)
if maxlevels and level >= maxlevels:
return "{...}", False, objid in context
return "{...}"
if objid in context:
return _recursion(object), False, True
context[objid] = 1
readable = True
recursive = False
return _recursion(object)
context.add(objid)
components: List[str] = []
append = components.append
level += 1
@ -554,61 +639,51 @@ class PrettyPrinter:
else:
items = object.items()
for k, v in items:
krepr, kreadable, krecur = self.format(k, context, maxlevels, level)
vrepr, vreadable, vrecur = self.format(v, context, maxlevels, level)
krepr = self.format(k, context, maxlevels, level)
vrepr = self.format(v, context, maxlevels, level)
append(f"{krepr}: {vrepr}")
readable = readable and kreadable and vreadable
if krecur or vrecur:
recursive = True
del context[objid]
return "{%s}" % ", ".join(components), readable, recursive
context.remove(objid)
return "{%s}" % ", ".join(components)
if (issubclass(typ, list) and r is list.__repr__) or (
issubclass(typ, tuple) and r is tuple.__repr__
):
if issubclass(typ, list):
if not object:
return "[]", True, False
return "[]"
format = "[%s]"
elif len(object) == 1:
format = "(%s,)"
else:
if not object:
return "()", True, False
return "()"
format = "(%s)"
objid = id(object)
if maxlevels and level >= maxlevels:
return format % "...", False, objid in context
return format % "..."
if objid in context:
return _recursion(object), False, True
context[objid] = 1
readable = True
recursive = False
return _recursion(object)
context.add(objid)
components = []
append = components.append
level += 1
for o in object:
orepr, oreadable, orecur = self.format(o, context, maxlevels, level)
orepr = self.format(o, context, maxlevels, level)
append(orepr)
if not oreadable:
readable = False
if orecur:
recursive = True
del context[objid]
return format % ", ".join(components), readable, recursive
context.remove(objid)
return format % ", ".join(components)
rep = repr(object)
return rep, (rep and not rep.startswith("<")), False
return repr(object)
_builtin_scalars = frozenset({str, bytes, bytearray, float, complex, bool, type(None)})
def _recursion(object):
def _recursion(object: Any) -> str:
return f"<Recursion on {type(object).__name__} with id={id(object)}>"
def _wrap_bytes_repr(object, width, allowance):
def _wrap_bytes_repr(object: Any, width: int, allowance: int) -> Iterator[str]:
current = b""
last = len(object) // 4 * 4
for i in range(0, len(object), 4):

View File

@ -231,6 +231,8 @@ def assertrepr_compare(
if not explanation:
return None
if explanation[0] != "":
explanation = [""] + explanation
return [summary] + explanation
@ -319,18 +321,6 @@ def _diff_text(left: str, right: str, verbose: int = 0) -> List[str]:
return explanation
def _surrounding_parens_on_own_lines(lines: List[str]) -> None:
"""Move opening/closing parenthesis/bracket to own lines."""
opening = lines[0][:1]
if opening in ["(", "[", "{"]:
lines[0] = " " + lines[0][1:]
lines[:] = [opening] + lines
closing = lines[-1][-1:]
if closing in [")", "]", "}"]:
lines[-1] = lines[-1][:-1] + ","
lines[:] = lines + [closing]
def _compare_eq_iterable(
left: Iterable[Any],
right: Iterable[Any],
@ -346,23 +336,15 @@ def _compare_eq_iterable(
left_formatting, right_formatting = _format_for_empty_and_non_empty(left, right)
lines_left = len(left_formatting)
lines_right = len(right_formatting)
else:
left_formatting = pprint.pformat(left).splitlines()
right_formatting = pprint.pformat(right).splitlines()
lines_left = len(left_formatting)
lines_right = len(right_formatting)
if lines_left != lines_right:
printer = PrettyPrinter()
left_formatting = printer.pformat(left).splitlines()
right_formatting = printer.pformat(right).splitlines()
if lines_left > 1 or lines_right > 1:
if lines_left > 1 or lines_right > 1:
_surrounding_parens_on_own_lines(left_formatting)
_surrounding_parens_on_own_lines(right_formatting)
else:
left_formatting = PrettyPrinter().pformat(left).splitlines()
right_formatting = PrettyPrinter().pformat(right).splitlines()
explanation = ["Full diff:"]
explanation = ["", "Full diff:"]
# "right" is the expected base against which we compare "left",
# see https://github.com/pytest-dev/pytest/issues/3333
explanation.extend(

View File

@ -588,7 +588,7 @@ if sys.version_info >= (3, 11) or TYPE_CHECKING:
@final
class CaptureResult(NamedTuple, Generic[AnyStr]):
"""The result of :method:`CaptureFixture.readouterr`."""
"""The result of :method:`caplog.readouterr() <pytest.CaptureFixture.readouterr>`."""
out: AnyStr
err: AnyStr
@ -598,7 +598,7 @@ else:
class CaptureResult(
collections.namedtuple("CaptureResult", ["out", "err"]), Generic[AnyStr]
):
"""The result of :method:`CaptureFixture.readouterr`."""
"""The result of :method:`caplog.readouterr() <pytest.CaptureFixture.readouterr>`."""
__slots__ = ()

View File

@ -98,7 +98,7 @@ class Parser:
:param opts:
Option names, can be short or long options.
:param attrs:
Same attributes as the argparse library's :py:func:`add_argument()
Same attributes as the argparse library's :meth:`add_argument()
<argparse.ArgumentParser.add_argument>` function accepts.
After command line parsing, options are available on the pytest config
@ -400,7 +400,7 @@ class OptionGroup:
:param opts:
Option names, can be short or long options.
:param attrs:
Same attributes as the argparse library's :py:func:`add_argument()
Same attributes as the argparse library's :meth:`add_argument()
<argparse.ArgumentParser.add_argument>` function accepts.
"""
conflict = set(opts).intersection(

View File

@ -9,8 +9,8 @@ from _pytest.nodes import Item
from _pytest.stash import StashKey
fault_handler_original_stderr_fd_key = StashKey[int]()
fault_handler_stderr_fd_key = StashKey[int]()
fault_handler_originally_enabled_key = StashKey[bool]()
def pytest_addoption(parser: Parser) -> None:
@ -24,8 +24,15 @@ def pytest_addoption(parser: Parser) -> None:
def pytest_configure(config: Config) -> None:
import faulthandler
config.stash[fault_handler_stderr_fd_key] = os.dup(get_stderr_fileno())
config.stash[fault_handler_originally_enabled_key] = faulthandler.is_enabled()
# at teardown we want to restore the original faulthandler fileno
# but faulthandler has no api to return the original fileno
# so here we stash the stderr fileno to be used at teardown
# sys.stderr and sys.__stderr__ may be closed or patched during the session
# so we can't rely on their values being good at that point (#11572).
stderr_fileno = get_stderr_fileno()
if faulthandler.is_enabled():
config.stash[fault_handler_original_stderr_fd_key] = stderr_fileno
config.stash[fault_handler_stderr_fd_key] = os.dup(stderr_fileno)
faulthandler.enable(file=config.stash[fault_handler_stderr_fd_key])
@ -37,9 +44,10 @@ def pytest_unconfigure(config: Config) -> None:
if fault_handler_stderr_fd_key in config.stash:
os.close(config.stash[fault_handler_stderr_fd_key])
del config.stash[fault_handler_stderr_fd_key]
if config.stash.get(fault_handler_originally_enabled_key, False):
# Re-enable the faulthandler if it was originally enabled.
faulthandler.enable(file=get_stderr_fileno())
# Re-enable the faulthandler if it was originally enabled.
if fault_handler_original_stderr_fd_key in config.stash:
faulthandler.enable(config.stash[fault_handler_original_stderr_fd_key])
del config.stash[fault_handler_original_stderr_fd_key]
def get_stderr_fileno() -> int:

View File

@ -96,8 +96,8 @@ def pytest_addoption(parser: "Parser", pluginmanager: "PytestPluginManager") ->
<pytest.Parser.addini>`.
:param pytest.PytestPluginManager pluginmanager:
The pytest plugin manager, which can be used to install :py:func:`hookspec`'s
or :py:func:`hookimpl`'s and allow one plugin to call another plugin's hooks
The pytest plugin manager, which can be used to install :py:func:`~pytest.hookspec`'s
or :py:func:`~pytest.hookimpl`'s and allow one plugin to call another plugin's hooks
to change how command line options are added.
Options can later be accessed through the

View File

@ -88,7 +88,6 @@ class Testdir:
return self._pytester.chdir()
def finalize(self) -> None:
"""See :meth:`Pytester._finalize`."""
return self._pytester._finalize()
def makefile(self, ext, *args, **kwargs) -> LEGACY_PATH:
@ -269,7 +268,7 @@ class LegacyTestdirPlugin:
@final
@dataclasses.dataclass
class TempdirFactory:
"""Backward compatibility wrapper that implements :class:`py.path.local`
"""Backward compatibility wrapper that implements ``py.path.local``
for :class:`TempPathFactory`.
.. note::
@ -288,11 +287,11 @@ class TempdirFactory:
self._tmppath_factory = tmppath_factory
def mktemp(self, basename: str, numbered: bool = True) -> LEGACY_PATH:
"""Same as :meth:`TempPathFactory.mktemp`, but returns a :class:`py.path.local` object."""
"""Same as :meth:`TempPathFactory.mktemp`, but returns a ``py.path.local`` object."""
return legacy_path(self._tmppath_factory.mktemp(basename, numbered).resolve())
def getbasetemp(self) -> LEGACY_PATH:
"""Same as :meth:`TempPathFactory.getbasetemp`, but returns a :class:`py.path.local` object."""
"""Same as :meth:`TempPathFactory.getbasetemp`, but returns a ``py.path.local`` object."""
return legacy_path(self._tmppath_factory.getbasetemp().resolve())

View File

@ -522,7 +522,7 @@ class LogCaptureFixture:
The levels of the loggers changed by this function will be
restored to their initial values at the end of the test.
Will enable the requested logging level if it was disabled via :meth:`logging.disable`.
Will enable the requested logging level if it was disabled via :func:`logging.disable`.
:param level: The level.
:param logger: The logger to update. If not given, the root logger.
@ -546,7 +546,7 @@ class LogCaptureFixture:
the end of the 'with' statement the level is restored to its original
value.
Will enable the requested logging level if it was disabled via :meth:`logging.disable`.
Will enable the requested logging level if it was disabled via :func:`logging.disable`.
:param level: The level.
:param logger: The logger to update. If not given, the root logger.
@ -564,6 +564,22 @@ class LogCaptureFixture:
self.handler.setLevel(handler_orig_level)
logging.disable(original_disable_level)
@contextmanager
def filtering(self, filter_: logging.Filter) -> Generator[None, None, None]:
"""Context manager that temporarily adds the given filter to the caplog's
:meth:`handler` for the 'with' statement block, and removes that filter at the
end of the block.
:param filter_: A custom :class:`logging.Filter` object.
.. versionadded:: 7.5
"""
self.handler.addFilter(filter_)
try:
yield
finally:
self.handler.removeFilter(filter_)
@fixture
def caplog(request: FixtureRequest) -> Generator[LogCaptureFixture, None, None]:

View File

@ -121,13 +121,18 @@ def pytest_configure(config: Config) -> None:
class LsofFdLeakChecker:
def get_open_files(self) -> List[Tuple[str, str]]:
if sys.version_info >= (3, 11):
# New in Python 3.11, ignores utf-8 mode
encoding = locale.getencoding()
else:
encoding = locale.getpreferredencoding(False)
out = subprocess.run(
("lsof", "-Ffn0", "-p", str(os.getpid())),
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL,
check=True,
text=True,
encoding=locale.getpreferredencoding(False),
encoding=encoding,
).stdout
def isopen(line: str) -> bool:
@ -1039,7 +1044,7 @@ class Pytester:
The calling test instance (class containing the test method) must
provide a ``.getrunner()`` method which should return a runner which
can run the test protocol for a single item, e.g.
:py:func:`_pytest.runner.runtestprotocol`.
``_pytest.runner.runtestprotocol``.
"""
# used from runner functional tests
item = self.getitem(source)
@ -1390,7 +1395,7 @@ class Pytester:
:param stdin:
Optional standard input.
- If it is :py:attr:`CLOSE_STDIN` (Default), then this method calls
- If it is ``CLOSE_STDIN`` (Default), then this method calls
:py:class:`subprocess.Popen` with ``stdin=subprocess.PIPE``, and
the standard input is closed immediately after the new command is
started.

View File

@ -825,8 +825,6 @@ def raises( # noqa: F811
When using :py:func:`pytest.raises` as a function, you can use:
``pytest.raises(Exc, func, match="passed on").match("my pattern")``.)
.. currentmodule:: _pytest._code
Use ``pytest.raises`` as a context manager, which will capture the exception of the given
type, or any of its subclasses::

View File

@ -31,6 +31,17 @@ def set_column_width(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setenv("COLUMNS", "80")
@pytest.fixture(autouse=True)
def reset_colors(monkeypatch: pytest.MonkeyPatch) -> None:
"""
Reset all color-related variables to prevent them from affecting internal pytest output
in tests that depend on it.
"""
monkeypatch.delenv("PY_COLORS", raising=False)
monkeypatch.delenv("NO_COLOR", raising=False)
monkeypatch.delenv("FORCE_COLOR", raising=False)
@pytest.hookimpl(wrapper=True, tryfirst=True)
def pytest_collection_modifyitems(items) -> Generator[None, None, None]:
"""Prefer faster tests.

View File

@ -40,15 +40,19 @@ class DataclassWithTwoItems:
pytest.param(
DataclassWithOneItem(foo="bar"),
"""
DataclassWithOneItem(foo='bar')
DataclassWithOneItem(
foo='bar',
)
""",
id="dataclass-one-item",
),
pytest.param(
DataclassWithTwoItems(foo="foo", bar="bar"),
"""
DataclassWithTwoItems(foo='foo',
bar='bar')
DataclassWithTwoItems(
foo='foo',
bar='bar',
)
""",
id="dataclass-two-items",
),
@ -60,15 +64,19 @@ class DataclassWithTwoItems:
pytest.param(
{"one": 1},
"""
{'one': 1}
{
'one': 1,
}
""",
id="dict-one-item",
),
pytest.param(
{"one": 1, "two": 2},
"""
{'one': 1,
'two': 2}
{
'one': 1,
'two': 2,
}
""",
id="dict-two-items",
),
@ -76,18 +84,19 @@ class DataclassWithTwoItems:
pytest.param(
OrderedDict({"one": 1}),
"""
OrderedDict([('one',
1)])
OrderedDict({
'one': 1,
})
""",
id="ordereddict-one-item",
),
pytest.param(
OrderedDict({"one": 1, "two": 2}),
"""
OrderedDict([('one',
1),
('two',
2)])
OrderedDict({
'one': 1,
'two': 2,
})
""",
id="ordereddict-two-items",
),
@ -99,15 +108,19 @@ class DataclassWithTwoItems:
pytest.param(
[1],
"""
[1]
[
1,
]
""",
id="list-one-item",
),
pytest.param(
[1, 2],
"""
[1,
2]
[
1,
2,
]
""",
id="list-two-items",
),
@ -119,15 +132,19 @@ class DataclassWithTwoItems:
pytest.param(
(1,),
"""
(1,)
(
1,
)
""",
id="tuple-one-item",
),
pytest.param(
(1, 2),
"""
(1,
2)
(
1,
2,
)
""",
id="tuple-two-items",
),
@ -139,15 +156,19 @@ class DataclassWithTwoItems:
pytest.param(
{1},
"""
{1}
{
1,
}
""",
id="set-one-item",
),
pytest.param(
{1, 2},
"""
{1,
2}
{
1,
2,
}
""",
id="set-two-items",
),
@ -159,15 +180,19 @@ class DataclassWithTwoItems:
pytest.param(
MappingProxyType({"one": 1}),
"""
mappingproxy({'one': 1})
mappingproxy({
'one': 1,
})
""",
id="mappingproxy-one-item",
),
pytest.param(
MappingProxyType({"one": 1, "two": 2}),
"""
mappingproxy({'one': 1,
'two': 2})
mappingproxy({
'one': 1,
'two': 2,
})
""",
id="mappingproxy-two-items",
),
@ -179,15 +204,19 @@ class DataclassWithTwoItems:
pytest.param(
SimpleNamespace(one=1),
"""
namespace(one=1)
namespace(
one=1,
)
""",
id="simplenamespace-one-item",
),
pytest.param(
SimpleNamespace(one=1, two=2),
"""
namespace(one=1,
two=2)
namespace(
one=1,
two=2,
)
""",
id="simplenamespace-two-items",
),
@ -197,17 +226,19 @@ class DataclassWithTwoItems:
pytest.param(
defaultdict(str, {"one": "1"}),
"""
defaultdict(<class 'str'>,
{'one': '1'})
defaultdict(<class 'str'>, {
'one': '1',
})
""",
id="defaultdict-one-item",
),
pytest.param(
defaultdict(str, {"one": "1", "two": "2"}),
"""
defaultdict(<class 'str'>,
{'one': '1',
'two': '2'})
defaultdict(<class 'str'>, {
'one': '1',
'two': '2',
})
""",
id="defaultdict-two-items",
),
@ -219,15 +250,19 @@ class DataclassWithTwoItems:
pytest.param(
Counter("1"),
"""
Counter({'1': 1})
Counter({
'1': 1,
})
""",
id="counter-one-item",
),
pytest.param(
Counter("121"),
"""
Counter({'1': 2,
'2': 1})
Counter({
'1': 2,
'2': 1,
})
""",
id="counter-two-items",
),
@ -235,16 +270,26 @@ class DataclassWithTwoItems:
pytest.param(
ChainMap({"one": 1, "two": 2}),
"""
ChainMap({'one': 1,
'two': 2})
ChainMap(
{
'one': 1,
'two': 2,
},
)
""",
id="chainmap-one-item",
),
pytest.param(
ChainMap({"one": 1}, {"two": 2}),
"""
ChainMap({'one': 1},
{'two': 2})
ChainMap(
{
'one': 1,
},
{
'two': 2,
},
)
""",
id="chainmap-two-items",
),
@ -256,24 +301,29 @@ class DataclassWithTwoItems:
pytest.param(
deque([1]),
"""
deque([1])
deque([
1,
])
""",
id="deque-one-item",
),
pytest.param(
deque([1, 2]),
"""
deque([1,
2])
deque([
1,
2,
])
""",
id="deque-two-items",
),
pytest.param(
deque([1, 2], maxlen=3),
"""
deque([1,
2],
maxlen=3)
deque(maxlen=3, [
1,
2,
])
""",
id="deque-maxlen",
),
@ -293,34 +343,60 @@ class DataclassWithTwoItems:
"tuple": (1, 2),
},
"""
{'chainmap': ChainMap({'one': 1},
{'two': 2}),
'counter': Counter({'2': 2,
'1': 1}),
'dataclass': DataclassWithTwoItems(foo='foo',
bar='bar'),
'defaultdict': defaultdict(<class 'str'>,
{'one': '1',
'two': '2'}),
'deque': deque([1,
2],
maxlen=3),
'dict': {'one': 1,
'two': 2},
'list': [1,
2],
'mappingproxy': mappingproxy({'one': 1,
'two': 2}),
'ordereddict': OrderedDict([('one',
1),
('two',
2)]),
'set': {1,
2},
'simplenamespace': namespace(one=1,
two=2),
'tuple': (1,
2)}
{
'chainmap': ChainMap(
{
'one': 1,
},
{
'two': 2,
},
),
'counter': Counter({
'2': 2,
'1': 1,
}),
'dataclass': DataclassWithTwoItems(
foo='foo',
bar='bar',
),
'defaultdict': defaultdict(<class 'str'>, {
'one': '1',
'two': '2',
}),
'deque': deque(maxlen=3, [
1,
2,
]),
'dict': {
'one': 1,
'two': 2,
},
'list': [
1,
2,
],
'mappingproxy': mappingproxy({
'one': 1,
'two': 2,
}),
'ordereddict': OrderedDict({
'one': 1,
'two': 2,
}),
'set': {
1,
2,
},
'simplenamespace': namespace(
one=1,
two=2,
),
'tuple': (
1,
2,
),
}
""",
id="deep-example",
),

View File

@ -144,7 +144,7 @@ def test_change_level_undos_handler_level(pytester: Pytester) -> None:
result.assert_outcomes(passed=3)
def test_with_statement(caplog: pytest.LogCaptureFixture) -> None:
def test_with_statement_at_level(caplog: pytest.LogCaptureFixture) -> None:
with caplog.at_level(logging.INFO):
logger.debug("handler DEBUG level")
logger.info("handler INFO level")
@ -159,7 +159,9 @@ def test_with_statement(caplog: pytest.LogCaptureFixture) -> None:
assert "CRITICAL" in caplog.text
def test_with_statement_logging_disabled(caplog: pytest.LogCaptureFixture) -> None:
def test_with_statement_at_level_logging_disabled(
caplog: pytest.LogCaptureFixture,
) -> None:
logging.disable(logging.CRITICAL)
assert logging.root.manager.disable == logging.CRITICAL
with caplog.at_level(logging.WARNING):
@ -185,6 +187,22 @@ def test_with_statement_logging_disabled(caplog: pytest.LogCaptureFixture) -> No
assert logging.root.manager.disable == logging.CRITICAL
def test_with_statement_filtering(caplog: pytest.LogCaptureFixture) -> None:
class TestFilter(logging.Filter):
def filter(self, record: logging.LogRecord) -> bool:
record.msg = "filtered handler call"
return True
with caplog.at_level(logging.INFO):
with caplog.filtering(TestFilter()):
logger.info("handler call")
logger.info("handler call")
filtered_tuple, unfiltered_tuple = caplog.record_tuples
assert filtered_tuple == ("test_fixture", 20, "filtered handler call")
assert unfiltered_tuple == ("test_fixture", 20, "handler call")
@pytest.mark.parametrize(
"level_str,expected_disable_level",
[

View File

@ -1,13 +1,13 @@
anyio[curio,trio]==4.0.0
anyio[curio,trio]==4.1.0
django==4.2.7
pytest-asyncio==0.21.1
pytest-bdd==7.0.0
pytest-asyncio==0.23.1
pytest-bdd==7.0.1
pytest-cov==4.1.0
pytest-django==4.7.0
pytest-flakes==4.0.5
pytest-html==4.1.1
pytest-mock==3.12.0
pytest-rerunfailures==12.0
pytest-rerunfailures==13.0
pytest-sugar==0.9.7
pytest-trio==0.7.0
pytest-twisted==1.14.0

View File

@ -99,6 +99,7 @@ class TestApprox:
2.0,
1.0,
[
"",
" comparison failed",
f" Obtained: {SOME_FLOAT}",
f" Expected: {SOME_FLOAT} ± {SOME_FLOAT}",
@ -113,6 +114,7 @@ class TestApprox:
"c": 3000000.0,
},
[
r"",
r" comparison failed. Mismatched elements: 2 / 3:",
rf" Max absolute difference: {SOME_FLOAT}",
rf" Max relative difference: {SOME_FLOAT}",
@ -130,6 +132,7 @@ class TestApprox:
"c": None,
},
[
r"",
r" comparison failed. Mismatched elements: 2 / 3:",
r" Max absolute difference: -inf",
r" Max relative difference: -inf",
@ -143,6 +146,7 @@ class TestApprox:
[1.0, 2.0, 3.0, 4.0],
[1.0, 3.0, 3.0, 5.0],
[
r"",
r" comparison failed. Mismatched elements: 2 / 4:",
rf" Max absolute difference: {SOME_FLOAT}",
rf" Max relative difference: {SOME_FLOAT}",
@ -156,6 +160,7 @@ class TestApprox:
(1, 2.2, 4),
(1, 3.2, 4),
[
r"",
r" comparison failed. Mismatched elements: 1 / 3:",
rf" Max absolute difference: {SOME_FLOAT}",
rf" Max relative difference: {SOME_FLOAT}",
@ -169,6 +174,7 @@ class TestApprox:
[0.0],
[1.0],
[
r"",
r" comparison failed. Mismatched elements: 1 / 1:",
rf" Max absolute difference: {SOME_FLOAT}",
r" Max relative difference: inf",
@ -187,6 +193,7 @@ class TestApprox:
a,
b,
[
r"",
r" comparison failed. Mismatched elements: 1 / 20:",
rf" Max absolute difference: {SOME_FLOAT}",
rf" Max relative difference: {SOME_FLOAT}",
@ -209,6 +216,7 @@ class TestApprox:
]
),
[
r"",
r" comparison failed. Mismatched elements: 3 / 8:",
rf" Max absolute difference: {SOME_FLOAT}",
rf" Max relative difference: {SOME_FLOAT}",
@ -224,6 +232,7 @@ class TestApprox:
np.array([0.0]),
np.array([1.0]),
[
r"",
r" comparison failed. Mismatched elements: 1 / 1:",
rf" Max absolute difference: {SOME_FLOAT}",
r" Max relative difference: inf",
@ -241,6 +250,7 @@ class TestApprox:
message = "\n".join(str(e.value).split("\n")[1:])
assert message == "\n".join(
[
" ",
" Impossible to compare arrays with different shapes.",
" Shapes: (2, 1) and (2, 2)",
]
@ -251,6 +261,7 @@ class TestApprox:
message = "\n".join(str(e.value).split("\n")[1:])
assert message == "\n".join(
[
" ",
" Impossible to compare lists with different sizes.",
" Lengths: 2 and 3",
]
@ -264,6 +275,7 @@ class TestApprox:
2.0,
1.0,
[
"",
" comparison failed",
f" Obtained: {SOME_FLOAT}",
f" Expected: {SOME_FLOAT} ± {SOME_FLOAT}",
@ -277,15 +289,15 @@ class TestApprox:
a,
b,
[
r" comparison failed. Mismatched elements: 20 / 20:",
rf" Max absolute difference: {SOME_FLOAT}",
rf" Max relative difference: {SOME_FLOAT}",
r" Index \| Obtained\s+\| Expected",
rf" \(0,\)\s+\| {SOME_FLOAT} \| {SOME_FLOAT} ± {SOME_FLOAT}",
rf" \(1,\)\s+\| {SOME_FLOAT} \| {SOME_FLOAT} ± {SOME_FLOAT}",
rf" \(2,\)\s+\| {SOME_FLOAT} \| {SOME_FLOAT} ± {SOME_FLOAT}...",
"",
rf"\s*...Full output truncated \({SOME_INT} lines hidden\), use '-vv' to show",
r"^ $",
r"^ comparison failed. Mismatched elements: 20 / 20:$",
rf"^ Max absolute difference: {SOME_FLOAT}$",
rf"^ Max relative difference: {SOME_FLOAT}$",
r"^ Index \| Obtained\s+\| Expected\s+$",
rf"^ \(0,\)\s+\| {SOME_FLOAT} \| {SOME_FLOAT} ± {SOME_FLOAT}e-{SOME_INT}$",
rf"^ \(1,\)\s+\| {SOME_FLOAT} \| {SOME_FLOAT} ± {SOME_FLOAT}e-{SOME_INT}\.\.\.$",
"^ $",
rf"^ ...Full output truncated \({SOME_INT} lines hidden\), use '-vv' to show$",
],
verbosity_level=0,
)
@ -294,6 +306,7 @@ class TestApprox:
a,
b,
[
r" ",
r" comparison failed. Mismatched elements: 20 / 20:",
rf" Max absolute difference: {SOME_FLOAT}",
rf" Max relative difference: {SOME_FLOAT}",
@ -652,6 +665,7 @@ class TestApprox:
{"foo": 42.0},
{"foo": 0.0},
[
r"",
r" comparison failed. Mismatched elements: 1 / 1:",
rf" Max absolute difference: {SOME_FLOAT}",
r" Max relative difference: inf",

View File

@ -392,6 +392,7 @@ class TestAssert_reprcompare:
def test_text_diff(self) -> None:
assert callequal("spam", "eggs") == [
"'spam' == 'eggs'",
"",
"- eggs",
"+ spam",
]
@ -473,7 +474,7 @@ class TestAssert_reprcompare:
def test_text_skipping(self) -> None:
lines = callequal("a" * 50 + "spam", "a" * 50 + "eggs")
assert lines is not None
assert "Skipping" in lines[1]
assert "Skipping" in lines[2]
for line in lines:
assert "a" * 50 not in line
@ -497,6 +498,7 @@ class TestAssert_reprcompare:
assert diff == [
"b'spam' == b'eggs'",
"",
"At index 0 diff: b's' != b'e'",
"Use -v to get more diff",
]
@ -506,7 +508,9 @@ class TestAssert_reprcompare:
diff = callequal(b"spam", b"eggs", verbose=1)
assert diff == [
"b'spam' == b'eggs'",
"",
"At index 0 diff: b's' != b'e'",
"",
"Full diff:",
"- b'eggs'",
"+ b'spam'",
@ -525,11 +529,14 @@ class TestAssert_reprcompare:
[0, 2],
"""
Full diff:
- [0, 2]
[
0,
- 2,
? ^
+ [0, 1]
+ 1,
? ^
""",
]
""",
id="lists",
),
pytest.param(
@ -537,10 +544,12 @@ class TestAssert_reprcompare:
{0: 2},
"""
Full diff:
- {0: 2}
? ^
+ {0: 1}
? ^
{
- 0: 2,
? ^
+ 0: 1,
? ^
}
""",
id="dicts",
),
@ -549,10 +558,13 @@ class TestAssert_reprcompare:
{0, 2},
"""
Full diff:
- {0, 2}
{
0,
- 2,
? ^
+ {0, 1}
+ 1,
? ^
}
""",
id="sets",
),
@ -575,6 +587,7 @@ class TestAssert_reprcompare:
expl = callequal([1, 2], [10, 2], verbose=-1)
assert expl == [
"[1, 2] == [10, 2]",
"",
"At index 0 diff: 1 != 10",
"Use -v to get more diff",
]
@ -613,26 +626,30 @@ class TestAssert_reprcompare:
diff = callequal(l1, l2, verbose=True)
assert diff == [
"['a', 'b', 'c'] == ['a', 'b', 'c...dddddddddddd']",
"",
"Right contains one more item: '" + long_d + "'",
"",
"Full diff:",
" [",
" 'a',",
" 'b',",
" 'c',",
"- '" + long_d + "',",
" 'a',",
" 'b',",
" 'c',",
"- '" + long_d + "',",
" ]",
]
diff = callequal(l2, l1, verbose=True)
assert diff == [
"['a', 'b', 'c...dddddddddddd'] == ['a', 'b', 'c']",
"",
"Left contains one more item: '" + long_d + "'",
"",
"Full diff:",
" [",
" 'a',",
" 'b',",
" 'c',",
"+ '" + long_d + "',",
" 'a',",
" 'b',",
" 'c',",
"+ '" + long_d + "',",
" ]",
]
@ -645,13 +662,15 @@ class TestAssert_reprcompare:
diff = callequal(l1, l2, verbose=True)
assert diff == [
"['aaaaaaaaaaa...cccccccccccc'] == ['bbbbbbbbbbb...aaaaaaaaaaaa']",
"",
"At index 0 diff: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' != 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'",
"",
"Full diff:",
" [",
"+ 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',",
" 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',",
" 'cccccccccccccccccccccccccccccc',",
"- 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',",
"+ 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',",
" 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',",
" 'cccccccccccccccccccccccccccccc',",
"- 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',",
" ]",
]
@ -662,19 +681,21 @@ class TestAssert_reprcompare:
diff = callequal(l1, l2, verbose=True)
assert diff == [
"['a', 'aaaaaa...aaaaaaa', ...] == ['should not get wrapped']",
"",
"At index 0 diff: 'a' != 'should not get wrapped'",
"Left contains 7 more items, first extra item: 'aaaaaaaaaa'",
"",
"Full diff:",
" [",
"- 'should not get wrapped',",
"+ 'a',",
"+ 'aaaaaaaaaa',",
"+ 'aaaaaaaaaa',",
"+ 'aaaaaaaaaa',",
"+ 'aaaaaaaaaa',",
"+ 'aaaaaaaaaa',",
"+ 'aaaaaaaaaa',",
"+ 'aaaaaaaaaa',",
"- 'should not get wrapped',",
"+ 'a',",
"+ 'aaaaaaaaaa',",
"+ 'aaaaaaaaaa',",
"+ 'aaaaaaaaaa',",
"+ 'aaaaaaaaaa',",
"+ 'aaaaaaaaaa',",
"+ 'aaaaaaaaaa',",
"+ 'aaaaaaaaaa',",
" ]",
]
@ -685,31 +706,45 @@ class TestAssert_reprcompare:
diff = callequal(d1, d2, verbose=True)
assert diff == [
"{'common': 1,...1, 'env2': 2}} == {'common': 1,...: {'env1': 1}}",
"",
"Omitting 1 identical items, use -vv to show",
"Differing items:",
"{'env': {'env1': 1, 'env2': 2}} != {'env': {'env1': 1}}",
"",
"Full diff:",
"- {'common': 1, 'env': {'env1': 1}}",
"+ {'common': 1, 'env': {'env1': 1, 'env2': 2}}",
"? +++++++++++",
" {",
" 'common': 1,",
" 'env': {",
" 'env1': 1,",
"+ 'env2': 2,",
" },",
" }",
]
long_a = "a" * 80
sub = {"long_a": long_a, "sub1": {"long_a": "substring that gets wrapped " * 2}}
sub = {"long_a": long_a, "sub1": {"long_a": "substring that gets wrapped " * 3}}
d1 = {"env": {"sub": sub}}
d2 = {"env": {"sub": sub}, "new": 1}
diff = callequal(d1, d2, verbose=True)
assert diff == [
"{'env': {'sub... wrapped '}}}} == {'env': {'sub...}}}, 'new': 1}",
"",
"Omitting 1 identical items, use -vv to show",
"Right contains 1 more item:",
"{'new': 1}",
"",
"Full diff:",
" {",
" 'env': {'sub': {'long_a': '" + long_a + "',",
" 'sub1': {'long_a': 'substring that gets wrapped substring '",
" 'that gets wrapped '}}},",
"- 'new': 1,",
" 'env': {",
" 'sub': {",
f" 'long_a': '{long_a}',",
" 'sub1': {",
" 'long_a': 'substring that gets wrapped substring that gets wrapped '",
" 'substring that gets wrapped ',",
" },",
" },",
" },",
"- 'new': 1,",
" }",
]
@ -721,7 +756,7 @@ class TestAssert_reprcompare:
def test_dict_omitting(self) -> None:
lines = callequal({"a": 0, "b": 1}, {"a": 1, "b": 1})
assert lines is not None
assert lines[1].startswith("Omitting 1 identical item")
assert lines[2].startswith("Omitting 1 identical item")
assert "Common items" not in lines
for line in lines[1:]:
assert "b" not in line
@ -730,60 +765,109 @@ class TestAssert_reprcompare:
"""Ensure differing items are visible for verbosity=1 (#1512)."""
lines = callequal({"a": 0, "b": 1}, {"a": 1, "b": 1}, verbose=1)
assert lines is not None
assert lines[1].startswith("Omitting 1 identical item")
assert lines[2].startswith("Differing items")
assert lines[3] == "{'a': 0} != {'a': 1}"
assert lines[1] == ""
assert lines[2].startswith("Omitting 1 identical item")
assert lines[3].startswith("Differing items")
assert lines[4] == "{'a': 0} != {'a': 1}"
assert "Common items" not in lines
def test_dict_omitting_with_verbosity_2(self) -> None:
lines = callequal({"a": 0, "b": 1}, {"a": 1, "b": 1}, verbose=2)
assert lines is not None
assert lines[1].startswith("Common items:")
assert "Omitting" not in lines[1]
assert lines[2] == "{'b': 1}"
assert lines[2].startswith("Common items:")
assert "Omitting" not in lines[2]
assert lines[3] == "{'b': 1}"
def test_dict_different_items(self) -> None:
lines = callequal({"a": 0}, {"b": 1, "c": 2}, verbose=2)
assert lines == [
"{'a': 0} == {'b': 1, 'c': 2}",
"",
"Left contains 1 more item:",
"{'a': 0}",
"Right contains 2 more items:",
"{'b': 1, 'c': 2}",
"",
"Full diff:",
"- {'b': 1, 'c': 2}",
"+ {'a': 0}",
" {",
"- 'b': 1,",
"? ^ ^",
"+ 'a': 0,",
"? ^ ^",
"- 'c': 2,",
" }",
]
lines = callequal({"b": 1, "c": 2}, {"a": 0}, verbose=2)
assert lines == [
"{'b': 1, 'c': 2} == {'a': 0}",
"",
"Left contains 2 more items:",
"{'b': 1, 'c': 2}",
"Right contains 1 more item:",
"{'a': 0}",
"",
"Full diff:",
"- {'a': 0}",
"+ {'b': 1, 'c': 2}",
" {",
"- 'a': 0,",
"? ^ ^",
"+ 'b': 1,",
"? ^ ^",
"+ 'c': 2,",
" }",
]
def test_sequence_different_items(self) -> None:
lines = callequal((1, 2), (3, 4, 5), verbose=2)
assert lines == [
"(1, 2) == (3, 4, 5)",
"",
"At index 0 diff: 1 != 3",
"Right contains one more item: 5",
"",
"Full diff:",
"- (3, 4, 5)",
"+ (1, 2)",
" (",
"- 3,",
"? ^",
"+ 1,",
"? ^",
"- 4,",
"? ^",
"+ 2,",
"? ^",
"- 5,",
" )",
]
lines = callequal((1, 2, 3), (4,), verbose=2)
assert lines == [
"(1, 2, 3) == (4,)",
"",
"At index 0 diff: 1 != 4",
"Left contains 2 more items, first extra item: 2",
"",
"Full diff:",
"- (4,)",
"+ (1, 2, 3)",
" (",
"- 4,",
"? ^",
"+ 1,",
"? ^",
"+ 2,",
"+ 3,",
" )",
]
lines = callequal((1, 2, 3), (1, 20, 3), verbose=2)
assert lines == [
"(1, 2, 3) == (1, 20, 3)",
"",
"At index 1 diff: 2 != 20",
"",
"Full diff:",
" (",
" 1,",
"- 20,",
"? -",
"+ 2,",
" 3,",
" )",
]
def test_set(self) -> None:
@ -841,7 +925,7 @@ class TestAssert_reprcompare:
assert expl is not None
assert expl[0].startswith("{} == <[ValueError")
assert "raised in repr" in expl[0]
assert expl[1:] == [
assert expl[2:] == [
"(pytest_assertion plugin: representation of details failed:"
" {}:{}: ValueError: 42.".format(
__file__, A.__repr__.__code__.co_firstlineno + 1
@ -867,6 +951,7 @@ class TestAssert_reprcompare:
def test_unicode(self) -> None:
assert callequal("£€", "£") == [
"'£€' == '£'",
"",
"- £",
"+ £€",
]
@ -882,7 +967,7 @@ class TestAssert_reprcompare:
return "\xff"
expl = callequal(A(), "1")
assert expl == ["ÿ == '1'", "- 1"]
assert expl == ["ÿ == '1'", "", "- 1"]
def test_format_nonascii_explanation(self) -> None:
assert util.format_explanation("λ")
@ -905,6 +990,7 @@ class TestAssert_reprcompare:
expl = callequal(left, right)
assert expl == [
r"'hyv\xe4' == 'hyva\u0308'",
"",
f"- {str(right)}",
f"+ {str(left)}",
]
@ -912,6 +998,7 @@ class TestAssert_reprcompare:
expl = callequal(left, right, verbose=2)
assert expl == [
r"'hyv\xe4' == 'hyva\u0308'",
"",
f"- {str(right)}",
f"+ {str(left)}",
]
@ -1200,6 +1287,7 @@ class TestAssert_reprcompare_namedtuple:
# Because the types are different, uses the generic sequence matcher.
assert lines == [
"NT1(a=1, b='b') == NT2(a=2, b='b')",
"",
"At index 0 diff: 1 != 2",
"Use -v to get more diff",
]
@ -1387,7 +1475,7 @@ class TestTruncateExplanation:
line_count = 7
line_len = 100
expected_truncated_lines = 1
expected_truncated_lines = 2
pytester.makepyfile(
r"""
def test_many_lines():
@ -1407,8 +1495,7 @@ class TestTruncateExplanation:
[
"*+ 1*",
"*+ 3*",
"*+ 5*",
"*truncated (%d line hidden)*use*-vv*" % expected_truncated_lines,
"*truncated (%d lines hidden)*use*-vv*" % expected_truncated_lines,
]
)
@ -1451,6 +1538,7 @@ def test_rewritten(pytester: Pytester) -> None:
def test_reprcompare_notin() -> None:
assert callop("not in", "foo", "aaafoobbb") == [
"'foo' not in 'aaafoobbb'",
"",
"'foo' is contained here:",
" aaafoobbb",
"? +++",
@ -1460,6 +1548,7 @@ def test_reprcompare_notin() -> None:
def test_reprcompare_whitespaces() -> None:
assert callequal("\r\n", "\n") == [
r"'\r\n' == '\n'",
"",
r"Strings contain only whitespace, escaping them using repr()",
r"- '\n'",
r"+ '\r\n'",
@ -1918,8 +2007,8 @@ def test_reprcompare_verbose_long() -> None:
assert [0, 1] == [0, 2]
""",
[
"{bold}{red}E {light-red}- [0, 2]{hl-reset}{endline}{reset}",
"{bold}{red}E {light-green}+ [0, 1]{hl-reset}{endline}{reset}",
"{bold}{red}E {light-red}- 2,{hl-reset}{endline}{reset}",
"{bold}{red}E {light-green}+ 1,{hl-reset}{endline}{reset}",
],
),
(
@ -1931,8 +2020,8 @@ def test_reprcompare_verbose_long() -> None:
""",
[
"{bold}{red}E {light-gray} {hl-reset} {{{endline}{reset}",
"{bold}{red}E {light-gray} {hl-reset} 'number-is-1': 1,{endline}{reset}",
"{bold}{red}E {light-green}+ 'number-is-5': 5,{hl-reset}{endline}{reset}",
"{bold}{red}E {light-gray} {hl-reset} 'number-is-1': 1,{endline}{reset}",
"{bold}{red}E {light-green}+ 'number-is-5': 5,{hl-reset}{endline}{reset}",
],
),
),
@ -1991,14 +2080,32 @@ def test_fine_grained_assertion_verbosity(pytester: Pytester):
f"{p.name} .FFF [100%]",
"E At index 2 diff: 'grapes' != 'orange'",
"E Full diff:",
"E - ['banana', 'apple', 'orange', 'melon', 'kiwi']",
"E ? ^ ^^",
"E + ['banana', 'apple', 'grapes', 'melon', 'kiwi']",
"E ? ^ ^ +",
"E [",
"E 'banana',",
"E 'apple',",
"E - 'orange',",
"E ? ^ ^^",
"E + 'grapes',",
"E ? ^ ^ +",
"E 'melon',",
"E 'kiwi',",
"E ]",
"E Full diff:",
"E - {'0': 0, '10': 10, '20': 20, '30': 30, '40': 40}",
"E ? - - - - - - - -",
"E + {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4}",
"E {",
"E '0': 0,",
"E - '10': 10,",
"E ? - -",
"E + '1': 1,",
"E - '20': 20,",
"E ? - -",
"E + '2': 2,",
"E - '30': 30,",
"E ? - -",
"E + '3': 3,",
"E - '40': 40,",
"E ? - -",
"E + '4': 4,",
"E }",
f"E AssertionError: assert 'hello world' in '{long_text}'",
]
)

View File

@ -1959,16 +1959,6 @@ def test_invocation_args(pytester: Pytester) -> None:
],
)
def test_config_blocked_default_plugins(pytester: Pytester, plugin: str) -> None:
if plugin == "debugging":
# Fixed in xdist (after 1.27.0).
# https://github.com/pytest-dev/pytest-xdist/pull/422
try:
import xdist # noqa: F401
except ImportError:
pass
else:
pytest.skip("does not work with xdist currently")
p = pytester.makepyfile("def test(): pass")
result = pytester.runpytest(str(p), "-pno:%s" % plugin)

View File

@ -21,10 +21,14 @@ TESTCASES = [
E assert [1, 4, 3] == [1, 2, 3]
E At index 1 diff: 4 != 2
E Full diff:
E - [1, 2, 3]
E [
E 1,
E - 2,
E ? ^
E + [1, 4, 3]
E + 4,
E ? ^
E 3,
E ]
""",
id="Compare lists, one item differs",
),
@ -40,9 +44,11 @@ TESTCASES = [
E assert [1, 2, 3] == [1, 2]
E Left contains one more item: 3
E Full diff:
E - [1, 2]
E + [1, 2, 3]
E ? +++
E [
E 1,
E 2,
E + 3,
E ]
""",
id="Compare lists, one extra item",
),
@ -59,9 +65,11 @@ TESTCASES = [
E At index 1 diff: 3 != 2
E Right contains one more item: 3
E Full diff:
E - [1, 2, 3]
E ? ---
E + [1, 3]
E [
E 1,
E - 2,
E 3,
E ]
""",
id="Compare lists, one item missing",
),
@ -77,10 +85,14 @@ TESTCASES = [
E assert (1, 4, 3) == (1, 2, 3)
E At index 1 diff: 4 != 2
E Full diff:
E - (1, 2, 3)
E (
E 1,
E - 2,
E ? ^
E + (1, 4, 3)
E + 4,
E ? ^
E 3,
E )
""",
id="Compare tuples",
),
@ -99,10 +111,12 @@ TESTCASES = [
E Extra items in the right set:
E 2
E Full diff:
E - {1, 2, 3}
E ? ^ ^
E + {1, 3, 4}
E ? ^ ^
E {
E 1,
E - 2,
E 3,
E + 4,
E }
""",
id="Compare sets",
),
@ -123,10 +137,13 @@ TESTCASES = [
E Right contains 1 more item:
E {2: 'eggs'}
E Full diff:
E - {1: 'spam', 2: 'eggs'}
E ? ^
E + {1: 'spam', 3: 'eggs'}
E ? ^
E {
E 1: 'spam',
E - 2: 'eggs',
E ? ^
E + 3: 'eggs',
E ? ^
E }
""",
id="Compare dicts with differing keys",
),
@ -145,10 +162,11 @@ TESTCASES = [
E Differing items:
E {2: 'eggs'} != {2: 'bacon'}
E Full diff:
E - {1: 'spam', 2: 'bacon'}
E ? ^^^^^
E + {1: 'spam', 2: 'eggs'}
E ? ^^^^
E {
E 1: 'spam',
E - 2: 'bacon',
E + 2: 'eggs',
E }
""",
id="Compare dicts with differing values",
),
@ -169,10 +187,11 @@ TESTCASES = [
E Right contains 1 more item:
E {3: 'bacon'}
E Full diff:
E - {1: 'spam', 3: 'bacon'}
E ? ^ ^^^^^
E + {1: 'spam', 2: 'eggs'}
E ? ^ ^^^^
E {
E 1: 'spam',
E - 3: 'bacon',
E + 2: 'eggs',
E }
""",
id="Compare dicts with differing items",
),

View File

@ -290,10 +290,10 @@ class TestParser:
def test_argcomplete(pytester: Pytester, monkeypatch: MonkeyPatch) -> None:
try:
if sys.version_info >= (3, 11):
# New in Python 3.11, ignores utf-8 mode
encoding = locale.getencoding() # type: ignore[attr-defined]
except AttributeError:
encoding = locale.getencoding()
else:
encoding = locale.getpreferredencoding(False)
try:
bash_version = subprocess.run(

View File

@ -1802,7 +1802,7 @@ def test_terminal_no_summary_warnings_header_once(pytester: Pytester) -> None:
@pytest.fixture(scope="session")
def tr() -> TerminalReporter:
config = _pytest.config._prepareconfig()
config = _pytest.config._prepareconfig([])
return TerminalReporter(config)