Merge branch 'main' into patch-1

This commit is contained in:
Philipp A 2022-08-19 14:08:43 +02:00 committed by GitHub
commit b3c1377693
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 799 additions and 300 deletions

View File

@ -114,6 +114,7 @@ jobs:
python: "3.11-dev" python: "3.11-dev"
os: ubuntu-latest os: ubuntu-latest
tox_env: "py311" tox_env: "py311"
use_coverage: true
- name: "ubuntu-pypy3" - name: "ubuntu-pypy3"
python: "pypy-3.7" python: "pypy-3.7"
os: ubuntu-latest os: ubuntu-latest

View File

@ -68,6 +68,9 @@ repos:
- packaging - packaging
- tomli - tomli
- types-pkg_resources - types-pkg_resources
# for mypy running on python>=3.11 since exceptiongroup is only a dependency
# on <3.11
- exceptiongroup>=1.0.0rc8
- repo: local - repo: local
hooks: hooks:
- id: rst - id: rst

View File

@ -168,6 +168,7 @@ Jeff Rackauckas
Jeff Widman Jeff Widman
Jenni Rinker Jenni Rinker
John Eddie Ayson John Eddie Ayson
John Litborn
John Towler John Towler
Jon Parise Jon Parise
Jon Sonesen Jon Sonesen
@ -313,6 +314,7 @@ Seth Junot
Shantanu Jain Shantanu Jain
Shubham Adep Shubham Adep
Simon Gomizelj Simon Gomizelj
Simon Holesch
Simon Kerr Simon Kerr
Skylar Downes Skylar Downes
Srinivas Reddy Thatiparthy Srinivas Reddy Thatiparthy

View File

@ -0,0 +1 @@
Invalid XML characters in setup or teardown error messages are now properly escaped for JUnit XML reports.

View File

@ -0,0 +1,5 @@
``@pytest.mark.parametrize()`` (and similar functions) now accepts any ``Sequence[str]`` for the argument names,
instead of just ``list[str]`` and ``tuple[str, ...]``.
(Note that ``str``, which is itself a ``Sequence[str]``, is still treated as a
comma-delimited name list, as before).

View File

@ -0,0 +1 @@
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``.

1
changelog/9248.doc.rst Normal file
View File

@ -0,0 +1 @@
The documentation is now built using Sphinx 5.x (up from 3.x previously).

1
changelog/9291.doc.rst Normal file
View File

@ -0,0 +1 @@
Update documentation on how :func:`pytest.warns` affects :class:`DeprecationWarning`.

View File

@ -38,6 +38,7 @@ release = ".".join(version.split(".")[:2])
autodoc_member_order = "bysource" autodoc_member_order = "bysource"
autodoc_typehints = "description" autodoc_typehints = "description"
autodoc_typehints_description_target = "documented"
todo_include_todos = 1 todo_include_todos = 1
latex_engine = "lualatex" latex_engine = "lualatex"
@ -162,11 +163,11 @@ linkcheck_workers = 5
_repo = "https://github.com/pytest-dev/pytest" _repo = "https://github.com/pytest-dev/pytest"
extlinks = { extlinks = {
"bpo": ("https://bugs.python.org/issue%s", "bpo-"), "bpo": ("https://bugs.python.org/issue%s", "bpo-%s"),
"pypi": ("https://pypi.org/project/%s/", ""), "pypi": ("https://pypi.org/project/%s/", "%s"),
"issue": (f"{_repo}/issues/%s", "issue #"), "issue": (f"{_repo}/issues/%s", "issue #%s"),
"pull": (f"{_repo}/pull/%s", "pull request #"), "pull": (f"{_repo}/pull/%s", "pull request #%s"),
"user": ("https://github.com/%s", "@"), "user": ("https://github.com/%s", "@%s"),
} }
@ -419,8 +420,6 @@ def configure_logging(app: "sphinx.application.Sphinx") -> None:
def setup(app: "sphinx.application.Sphinx") -> None: def setup(app: "sphinx.application.Sphinx") -> None:
# from sphinx.ext.autodoc import cut_lines
# app.connect('autodoc-process-docstring', cut_lines(4, what=['module']))
app.add_crossref_type( app.add_crossref_type(
"fixture", "fixture",
"fixture", "fixture",

View File

@ -42,6 +42,8 @@ Running pytest now produces this output:
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
======================= 1 passed, 1 warning in 0.12s ======================= ======================= 1 passed, 1 warning in 0.12s =======================
.. _`controlling-warnings`:
Controlling warnings Controlling warnings
-------------------- --------------------
@ -176,11 +178,14 @@ using an external system.
DeprecationWarning and PendingDeprecationWarning DeprecationWarning and PendingDeprecationWarning
------------------------------------------------ ------------------------------------------------
By default pytest will display ``DeprecationWarning`` and ``PendingDeprecationWarning`` warnings from By default pytest will display ``DeprecationWarning`` and ``PendingDeprecationWarning`` warnings from
user code and third-party libraries, as recommended by :pep:`565`. user code and third-party libraries, as recommended by :pep:`565`.
This helps users keep their code modern and avoid breakages when deprecated warnings are effectively removed. This helps users keep their code modern and avoid breakages when deprecated warnings are effectively removed.
However, in the specific case where users capture any type of warnings in their test, either with
:func:`pytest.warns`, :func:`pytest.deprecated_call` or using the :ref:`recwarn <recwarn>` fixture,
no warning will be displayed at all.
Sometimes it is useful to hide some specific deprecation warnings that happen in code that you have no control over Sometimes it is useful to hide some specific deprecation warnings that happen in code that you have no control over
(such as third-party libraries), in which case you might use the warning filters options (ini or marks) to ignore (such as third-party libraries), in which case you might use the warning filters options (ini or marks) to ignore
those warnings. those warnings.
@ -197,6 +202,9 @@ For example:
This will ignore all warnings of type ``DeprecationWarning`` where the start of the message matches This will ignore all warnings of type ``DeprecationWarning`` where the start of the message matches
the regular expression ``".*U.*mode is deprecated"``. the regular expression ``".*U.*mode is deprecated"``.
See :ref:`@pytest.mark.filterwarnings <filterwarnings>` and
:ref:`Controlling warnings <controlling-warnings>` for more examples.
.. note:: .. note::
If warnings are configured at the interpreter level, using If warnings are configured at the interpreter level, using
@ -245,10 +253,10 @@ when called with a ``17`` argument.
Asserting warnings with the warns function Asserting warnings with the warns function
------------------------------------------ ------------------------------------------
You can check that code raises a particular warning using :func:`pytest.warns`, You can check that code raises a particular warning using :func:`pytest.warns`,
which works in a similar manner to :ref:`raises <assertraises>`: which works in a similar manner to :ref:`raises <assertraises>` (except that
:ref:`raises <assertraises>` does not capture all exceptions, only the
``expected_exception``):
.. code-block:: python .. code-block:: python
@ -261,8 +269,8 @@ which works in a similar manner to :ref:`raises <assertraises>`:
with pytest.warns(UserWarning): with pytest.warns(UserWarning):
warnings.warn("my warning", UserWarning) warnings.warn("my warning", UserWarning)
The test will fail if the warning in question is not raised. The keyword The test will fail if the warning in question is not raised. Use the keyword
argument ``match`` to assert that the exception matches a text or regex:: argument ``match`` to assert that the warning matches a text or regex::
>>> with warns(UserWarning, match='must be 0 or None'): >>> with warns(UserWarning, match='must be 0 or None'):
... warnings.warn("value must be 0 or None", UserWarning) ... warnings.warn("value must be 0 or None", UserWarning)
@ -359,20 +367,32 @@ Additional use cases of warnings in tests
Here are some use cases involving warnings that often come up in tests, and suggestions on how to deal with them: Here are some use cases involving warnings that often come up in tests, and suggestions on how to deal with them:
- To ensure that **at least one** warning is emitted, use: - To ensure that **at least one** of the indicated warnings is issued, use:
.. code-block:: python .. code-block:: python
with pytest.warns(): def test_warning():
with pytest.warns((RuntimeWarning, UserWarning)):
...
- To ensure that **only** certain warnings are issued, use:
.. code-block:: python
def test_warning(recwarn):
... ...
assert len(recwarn) == 1
user_warning = recwarn.pop(UserWarning)
assert issubclass(user_warning.category, UserWarning)
- To ensure that **no** warnings are emitted, use: - To ensure that **no** warnings are emitted, use:
.. code-block:: python .. code-block:: python
with warnings.catch_warnings(): def test_warning():
warnings.simplefilter("error") with warnings.catch_warnings():
... warnings.simplefilter("error")
...
- To suppress warnings, use: - To suppress warnings, use:

View File

@ -735,8 +735,81 @@ does offer some nuances for when you're in a pinch.
.. code-block:: pytest .. code-block:: pytest
$ pytest -q test_emaillib.py $ pytest -q test_emaillib.py
. [100%] . [100%]
1 passed in 0.12s 1 passed in 0.12s
Note on finalizer order
""""""""""""""""""""""""
Finalizers are executed in a first-in-last-out order.
For yield fixtures, the first teardown code to run is from the right-most fixture, i.e. the last test parameter.
.. regendoc:wipe
.. code-block:: python
import pytest
def test_bar(fix_w_yield1, fix_w_yield2):
print("test_bar")
@pytest.fixture
def fix_w_yield1():
yield
print("after_yield_1")
@pytest.fixture
def fix_w_yield2():
yield
print("after_yield_2")
.. code-block:: pytest
$ pytest test_module.py
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
collected 1 item
test_module.py test_bar
.after_yield_2
after_yield_1
For finalizers, the first fixture to run is last call to `request.addfinalizer`.
.. code-block:: python
import pytest
@pytest.fixture
def fix_w_finalizers(request):
request.addfinalizer(partial(print, "finalizer_2"))
request.addfinalizer(partial(print, "finalizer_1"))
def test_bar(fix_w_finalizers):
print("test_bar")
.. code-block:: pytest
$ pytest test_module.py
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
collected 1 item
test_module.py test_bar
.finalizer_1
finalizer_2
This is so because yield fixtures use `addfinalizer` behind the scenes: when the fixture executes, `addfinalizer` registers a function that resumes the generator, which in turn calls the teardown code.
.. _`safe teardowns`: .. _`safe teardowns`:

View File

@ -14,18 +14,16 @@ environment variable, or to modify ``sys.path`` for importing.
The ``monkeypatch`` fixture provides these helper methods for safely patching and mocking The ``monkeypatch`` fixture provides these helper methods for safely patching and mocking
functionality in tests: functionality in tests:
.. code-block:: python * :meth:`monkeypatch.setattr(obj, name, value, raising=True) <pytest.MonkeyPatch.setattr>`
* :meth:`monkeypatch.delattr(obj, name, raising=True) <pytest.MonkeyPatch.delattr>`
* :meth:`monkeypatch.setitem(mapping, name, value) <pytest.MonkeyPatch.setitem>`
* :meth:`monkeypatch.delitem(obj, name, raising=True) <pytest.MonkeyPatch.delitem>`
* :meth:`monkeypatch.setenv(name, value, prepend=None) <pytest.MonkeyPatch.setenv>`
* :meth:`monkeypatch.delenv(name, raising=True) <pytest.MonkeyPatch.delenv>`
* :meth:`monkeypatch.syspath_prepend(path) <pytest.MonkeyPatch.syspath_prepend>`
* :meth:`monkeypatch.chdir(path) <pytest.MonkeyPatch.chdir>`
* :meth:`monkeypatch.context() <pytest.MonkeyPatch.context>`
monkeypatch.setattr(obj, name, value, raising=True)
monkeypatch.setattr("somemodule.obj.name", value, raising=True)
monkeypatch.delattr(obj, name, raising=True)
monkeypatch.setitem(mapping, name, value)
monkeypatch.delitem(obj, name, raising=True)
monkeypatch.setenv(name, value, prepend=None)
monkeypatch.delenv(name, raising=True)
monkeypatch.syspath_prepend(path)
monkeypatch.chdir(path)
monkeypatch.context()
All modifications will be undone after the requesting All modifications will be undone after the requesting
test function or fixture has finished. The ``raising`` test function or fixture has finished. The ``raising``
@ -64,8 +62,8 @@ and a discussion of its motivation.
.. _`monkeypatch blog post`: https://tetamap.wordpress.com//2009/03/03/monkeypatching-in-unit-tests-done-right/ .. _`monkeypatch blog post`: https://tetamap.wordpress.com//2009/03/03/monkeypatching-in-unit-tests-done-right/
Simple example: monkeypatching functions Monkeypatching functions
---------------------------------------- ------------------------
Consider a scenario where you are working with user directories. In the context of Consider a scenario where you are working with user directories. In the context of
testing, you do not want your test to depend on the running user. ``monkeypatch`` testing, you do not want your test to depend on the running user. ``monkeypatch``

View File

@ -90,7 +90,7 @@ and can also be used to hold pytest configuration if they have a ``[pytest]`` se
setup.cfg setup.cfg
~~~~~~~~~ ~~~~~~~~~
``setup.cfg`` files are general purpose configuration files, used originally by :doc:`distutils <distutils/configfile>`, and can also be used to hold pytest configuration ``setup.cfg`` files are general purpose configuration files, used originally by :doc:`distutils <python:distutils/configfile>`, and can also be used to hold pytest configuration
if they have a ``[tool:pytest]`` section. if they have a ``[tool:pytest]`` section.
.. code-block:: ini .. code-block:: ini

View File

@ -11,7 +11,7 @@ automatically. Packages classified as inactive are excluded.
creating a PDF, because otherwise the table gets far too wide for the creating a PDF, because otherwise the table gets far too wide for the
page. page.
This list contains 1094 plugins. This list contains 1100 plugins.
.. only:: not latex .. only:: not latex
@ -201,7 +201,7 @@ This list contains 1094 plugins.
:pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jan 04, 2021 4 - Beta pytest (>=6.1.0) :pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jan 04, 2021 4 - Beta pytest (>=6.1.0)
:pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev'
:pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Mar 18, 2022 5 - Production/Stable pytest (!=5.4.0,!=5.4.1) :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Mar 18, 2022 5 - Production/Stable pytest (!=5.4.0,!=5.4.1)
:pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Jun 08, 2022 N/A N/A :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Aug 13, 2022 N/A N/A
:pypi:`pytest-cram` Run cram tests with pytest. Aug 08, 2020 N/A N/A :pypi:`pytest-cram` Run cram tests with pytest. Aug 08, 2020 N/A N/A
:pypi:`pytest-crate` Manages CrateDB instances during your integration tests May 28, 2019 3 - Alpha pytest (>=4.0) :pypi:`pytest-crate` Manages CrateDB instances during your integration tests May 28, 2019 3 - Alpha pytest (>=4.0)
:pypi:`pytest-cricri` A Cricri plugin for pytest. Jan 27, 2018 N/A pytest :pypi:`pytest-cricri` A Cricri plugin for pytest. Jan 27, 2018 N/A pytest
@ -372,7 +372,7 @@ This list contains 1094 plugins.
:pypi:`pytest-factoryboy-state` Simple factoryboy random state management Mar 22, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-factoryboy-state` Simple factoryboy random state management Mar 22, 2022 5 - Production/Stable pytest (>=5.0)
:pypi:`pytest-failed-screenshot` Test case fails,take a screenshot,save it,attach it to the allure Apr 21, 2021 N/A N/A :pypi:`pytest-failed-screenshot` Test case fails,take a screenshot,save it,attach it to the allure Apr 21, 2021 N/A N/A
:pypi:`pytest-failed-to-verify` A pytest plugin that helps better distinguishing real test failures from setup flakiness. Aug 08, 2019 5 - Production/Stable pytest (>=4.1.0) :pypi:`pytest-failed-to-verify` A pytest plugin that helps better distinguishing real test failures from setup flakiness. Aug 08, 2019 5 - Production/Stable pytest (>=4.1.0)
:pypi:`pytest-fail-slow` Fail tests that take too long to run Apr 25, 2022 4 - Beta pytest (>=6.0) :pypi:`pytest-fail-slow` Fail tests that take too long to run Aug 13, 2022 4 - Beta pytest (>=6.0)
:pypi:`pytest-faker` Faker integration with the pytest framework. Dec 19, 2016 6 - Mature N/A :pypi:`pytest-faker` Faker integration with the pytest framework. Dec 19, 2016 6 - Mature N/A
:pypi:`pytest-falcon` Pytest helpers for Falcon. Sep 07, 2016 4 - Beta N/A :pypi:`pytest-falcon` Pytest helpers for Falcon. Sep 07, 2016 4 - Beta N/A
:pypi:`pytest-falcon-client` Pytest \`client\` fixture for the Falcon Framework Mar 19, 2019 N/A N/A :pypi:`pytest-falcon-client` Pytest \`client\` fixture for the Falcon Framework Mar 19, 2019 N/A N/A
@ -407,6 +407,7 @@ This list contains 1094 plugins.
:pypi:`pytest-flakes` pytest plugin to check source code with pyflakes Dec 02, 2021 5 - Production/Stable pytest (>=5) :pypi:`pytest-flakes` pytest plugin to check source code with pyflakes Dec 02, 2021 5 - Production/Stable pytest (>=5)
:pypi:`pytest-flaptastic` Flaptastic py.test plugin Mar 17, 2019 N/A N/A :pypi:`pytest-flaptastic` Flaptastic py.test plugin Mar 17, 2019 N/A N/A
:pypi:`pytest-flask` A set of py.test fixtures to test Flask applications. Feb 27, 2021 5 - Production/Stable pytest (>=5.2) :pypi:`pytest-flask` A set of py.test fixtures to test Flask applications. Feb 27, 2021 5 - Production/Stable pytest (>=5.2)
:pypi:`pytest-flask-ligand` Pytest fixtures and helper functions to use for testing flask-ligand microservices. Aug 09, 2022 4 - Beta pytest (~=7.1)
:pypi:`pytest-flask-sqlalchemy` A pytest plugin for preserving test isolation in Flask-SQlAlchemy using database transactions. Apr 30, 2022 4 - Beta pytest (>=3.2.1) :pypi:`pytest-flask-sqlalchemy` A pytest plugin for preserving test isolation in Flask-SQlAlchemy using database transactions. Apr 30, 2022 4 - Beta pytest (>=3.2.1)
:pypi:`pytest-flask-sqlalchemy-transactions` Run tests in transactions using pytest, Flask, and SQLalchemy. Aug 02, 2018 4 - Beta pytest (>=3.2.1) :pypi:`pytest-flask-sqlalchemy-transactions` Run tests in transactions using pytest, Flask, and SQLalchemy. Aug 02, 2018 4 - Beta pytest (>=3.2.1)
:pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd Jul 12, 2022 4 - Beta pytest :pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd Jul 12, 2022 4 - Beta pytest
@ -456,7 +457,7 @@ This list contains 1094 plugins.
:pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest :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-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-homeassistant` A pytest plugin for use with homeassistant custom components. Aug 12, 2020 4 - Beta N/A :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 Aug 05, 2022 3 - Alpha pytest (==7.1.2) :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Aug 13, 2022 3 - Alpha pytest (==7.1.2)
:pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :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-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A
:pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Mar 28, 2022 N/A pytest (>=5.0) :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Mar 28, 2022 N/A pytest (>=5.0)
@ -480,7 +481,7 @@ This list contains 1094 plugins.
:pypi:`pytest-hylang` Pytest plugin to allow running tests written in hylang Mar 28, 2021 N/A pytest :pypi:`pytest-hylang` Pytest plugin to allow running tests written in hylang Mar 28, 2021 N/A pytest
:pypi:`pytest-hypo-25` help hypo module for pytest Jan 12, 2020 3 - Alpha N/A :pypi:`pytest-hypo-25` help hypo module for pytest Jan 12, 2020 3 - Alpha N/A
:pypi:`pytest-ibutsu` A plugin to sent pytest results to an Ibutsu server Aug 05, 2022 4 - Beta N/A :pypi:`pytest-ibutsu` A plugin to sent pytest results to an Ibutsu server Aug 05, 2022 4 - Beta N/A
:pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Apr 08, 2020 4 - Beta N/A :pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Aug 09, 2022 4 - Beta N/A
:pypi:`pytest-idapro` A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api Nov 03, 2018 N/A N/A :pypi:`pytest-idapro` A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api Nov 03, 2018 N/A N/A
:pypi:`pytest-idem` A pytest plugin to help with testing idem projects Jun 29, 2022 5 - Production/Stable N/A :pypi:`pytest-idem` A pytest plugin to help with testing idem projects Jun 29, 2022 5 - Production/Stable N/A
:pypi:`pytest-idempotent` Pytest plugin for testing function idempotence. Jul 25, 2022 N/A N/A :pypi:`pytest-idempotent` Pytest plugin for testing function idempotence. Jul 25, 2022 N/A N/A
@ -493,7 +494,7 @@ This list contains 1094 plugins.
:pypi:`pytest-infrastructure` pytest stack validation prior to testing executing Apr 12, 2020 4 - Beta N/A :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-ini` Reuse pytest.ini to store env variables Apr 26, 2022 N/A N/A
:pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. May 18, 2022 5 - Production/Stable N/A :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. May 18, 2022 5 - Production/Stable N/A
:pypi:`pytest-inmanta-extensions` Inmanta tests package Apr 12, 2022 5 - Production/Stable N/A :pypi:`pytest-inmanta-extensions` Inmanta tests package Aug 10, 2022 5 - Production/Stable N/A
:pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Jul 14, 2022 5 - Production/Stable N/A :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Jul 14, 2022 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-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-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A
@ -504,7 +505,7 @@ This list contains 1094 plugins.
:pypi:`pytest-integration-mark` Automatic integration test marking and excluding plugin for pytest Jul 19, 2021 N/A pytest (>=5.2,<7.0) :pypi:`pytest-integration-mark` Automatic integration test marking and excluding plugin for pytest Jul 19, 2021 N/A pytest (>=5.2,<7.0)
: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-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-intercept-remote` Pytest plugin for intercepting outgoing connection requests during pytest run. May 24, 2021 4 - Beta pytest (>=4.6)
:pypi:`pytest-invenio` Pytest fixtures for Invenio. May 05, 2022 5 - Production/Stable pytest (<7,>=6) :pypi:`pytest-invenio` "Pytest fixtures for Invenio." Aug 09, 2022 5 - Production/Stable pytest (<7,>=6)
:pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :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. Sep 02, 2014 2 - Pre-Alpha N/A :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Sep 02, 2014 2 - Pre-Alpha N/A
:pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A
@ -520,13 +521,13 @@ This list contains 1094 plugins.
:pypi:`pytest-jobserver` Limit parallel tests with posix jobserver. May 15, 2019 5 - Production/Stable pytest :pypi:`pytest-jobserver` Limit parallel tests with posix jobserver. May 15, 2019 5 - Production/Stable pytest
:pypi:`pytest-joke` Test failures are better served with humor. Oct 08, 2019 4 - Beta pytest (>=4.2.1) :pypi:`pytest-joke` Test failures are better served with humor. Oct 08, 2019 4 - Beta pytest (>=4.2.1)
:pypi:`pytest-json` Generate JSON test reports Jan 18, 2016 4 - Beta N/A :pypi:`pytest-json` Generate JSON test reports Jan 18, 2016 4 - Beta N/A
:pypi:`pytest-json-fixtures` JSON output for the --fixtures flag Aug 03, 2022 4 - Beta pytest (>=7.1.0) :pypi:`pytest-json-fixtures` JSON output for the --fixtures flag Aug 09, 2022 4 - Beta pytest (>=7.1.0)
:pypi:`pytest-jsonlint` UNKNOWN Aug 04, 2016 N/A N/A :pypi:`pytest-jsonlint` UNKNOWN Aug 04, 2016 N/A N/A
:pypi:`pytest-json-report` A pytest plugin to report test results as JSON files Mar 15, 2022 4 - Beta pytest (>=3.8.0) :pypi:`pytest-json-report` A pytest plugin to report test results as JSON files Mar 15, 2022 4 - Beta pytest (>=3.8.0)
:pypi:`pytest-kafka` Zookeeper, Kafka server, and Kafka consumer fixtures for Pytest Aug 24, 2021 N/A pytest :pypi:`pytest-kafka` Zookeeper, Kafka server, and Kafka consumer fixtures for Pytest Aug 24, 2021 N/A pytest
:pypi:`pytest-kafkavents` A plugin to send pytest events to Kafka Sep 08, 2021 4 - Beta pytest :pypi:`pytest-kafkavents` A plugin to send pytest events to Kafka Sep 08, 2021 4 - Beta pytest
:pypi:`pytest-kexi` Apr 29, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-kexi` Apr 29, 2022 N/A pytest (>=7.1.2,<8.0.0)
:pypi:`pytest-kind` Kubernetes test support with KIND for pytest Jan 24, 2021 5 - Production/Stable N/A :pypi:`pytest-kind` Kubernetes test support with KIND for pytest Aug 11, 2022 5 - Production/Stable N/A
:pypi:`pytest-kivy` Kivy GUI tests fixtures using pytest Jul 06, 2021 4 - Beta pytest (>=3.6) :pypi:`pytest-kivy` Kivy GUI tests fixtures using pytest Jul 06, 2021 4 - Beta pytest (>=3.6)
:pypi:`pytest-knows` A pytest plugin that can automaticly skip test case based on dependence info calculated by trace Aug 22, 2014 N/A N/A :pypi:`pytest-knows` A pytest plugin that can automaticly skip test case based on dependence info calculated by trace Aug 22, 2014 N/A N/A
:pypi:`pytest-konira` Run Konira DSL tests with py.test Oct 09, 2011 N/A N/A :pypi:`pytest-konira` Run Konira DSL tests with py.test Oct 09, 2011 N/A N/A
@ -547,6 +548,7 @@ This list contains 1094 plugins.
:pypi:`pytest-ligo` Jan 16, 2020 4 - Beta N/A :pypi:`pytest-ligo` Jan 16, 2020 4 - Beta N/A
:pypi:`pytest-lineno` A pytest plugin to show the line numbers of test functions Dec 04, 2020 N/A pytest :pypi:`pytest-lineno` A pytest plugin to show the line numbers of test functions Dec 04, 2020 N/A pytest
:pypi:`pytest-line-profiler` Profile code executed by pytest May 03, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-line-profiler` Profile code executed by pytest May 03, 2021 4 - Beta pytest (>=3.5.0)
:pypi:`pytest-line-profiler-apn` Profile code executed by pytest Aug 13, 2022 4 - Beta N/A
:pypi:`pytest-lisa` Pytest plugin for organizing tests. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) :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-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-litf` A pytest plugin that stream output in LITF format Jan 18, 2021 4 - Beta pytest (>=3.1.1)
@ -603,7 +605,7 @@ This list contains 1094 plugins.
:pypi:`pytest-mock-helper` Help you mock HTTP call and generate mock code Jan 24, 2018 N/A pytest :pypi:`pytest-mock-helper` Help you mock HTTP call and generate mock code Jan 24, 2018 N/A pytest
:pypi:`pytest-mockito` Base fixtures for mockito Jul 11, 2018 4 - Beta N/A :pypi:`pytest-mockito` Base fixtures for mockito Jul 11, 2018 4 - Beta N/A
:pypi:`pytest-mockredis` An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. Jan 02, 2018 2 - Pre-Alpha N/A :pypi:`pytest-mockredis` An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. Jan 02, 2018 2 - Pre-Alpha N/A
:pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Jul 20, 2022 N/A pytest (>=1.0) :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Aug 12, 2022 N/A pytest (>=1.0)
:pypi:`pytest-mock-server` Mock server plugin for pytest Jan 09, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-mock-server` Mock server plugin for pytest Jan 09, 2022 4 - Beta pytest (>=3.5.0)
:pypi:`pytest-mockservers` A set of fixtures to test your requests to HTTP/UDP servers Mar 31, 2020 N/A pytest (>=4.3.0) :pypi:`pytest-mockservers` A set of fixtures to test your requests to HTTP/UDP servers Mar 31, 2020 N/A pytest (>=4.3.0)
:pypi:`pytest-modified-env` Pytest plugin to fail a test if it leaves modified \`os.environ\` afterwards. Jan 29, 2022 4 - Beta N/A :pypi:`pytest-modified-env` Pytest plugin to fail a test if it leaves modified \`os.environ\` afterwards. Jan 29, 2022 4 - Beta N/A
@ -642,7 +644,7 @@ This list contains 1094 plugins.
:pypi:`pytest-nginx-iplweb` nginx fixture for pytest - iplweb temporary fork Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-nginx-iplweb` nginx fixture for pytest - iplweb temporary fork Mar 01, 2019 5 - Production/Stable N/A
:pypi:`pytest-ngrok` Jan 20, 2022 3 - Alpha pytest :pypi:`pytest-ngrok` Jan 20, 2022 3 - Alpha pytest
:pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0) :pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0)
:pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Jul 21, 2022 N/A pytest (==6.2.5) :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Aug 10, 2022 N/A pytest (==6.2.5)
:pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest
:pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A :pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A
:pypi:`pytest-nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Jul 07, 2021 N/A N/A :pypi:`pytest-nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Jul 07, 2021 N/A N/A
@ -751,7 +753,7 @@ This list contains 1094 plugins.
:pypi:`pytest-pydev` py.test plugin to connect to a remote debug server with PyDev or PyCharm. Nov 15, 2017 3 - Alpha N/A :pypi:`pytest-pydev` py.test plugin to connect to a remote debug server with PyDev or PyCharm. Nov 15, 2017 3 - Alpha N/A
:pypi:`pytest-pydocstyle` pytest plugin to run pydocstyle Mar 13, 2022 3 - Alpha N/A :pypi:`pytest-pydocstyle` pytest plugin to run pydocstyle Mar 13, 2022 3 - Alpha N/A
:pypi:`pytest-pylint` pytest plugin to check source code with pylint Nov 09, 2020 5 - Production/Stable pytest (>=5.4) :pypi:`pytest-pylint` pytest plugin to check source code with pylint Nov 09, 2020 5 - Production/Stable pytest (>=5.4)
:pypi:`pytest-pyodide` "Pytest plugin for testing applications that use Pyodide" Aug 04, 2022 N/A pytest :pypi:`pytest-pyodide` "Pytest plugin for testing applications that use Pyodide" Aug 10, 2022 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-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-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) :pypi:`pytest-pyppeteer` A plugin to run pyppeteer in pytest Apr 28, 2022 N/A pytest (>=6.2.5,<7.0.0)
@ -823,18 +825,20 @@ This list contains 1094 plugins.
:pypi:`pytest-rerun` Re-run only changed files in specified branch Jul 08, 2019 N/A pytest (>=3.6) :pypi:`pytest-rerun` Re-run only changed files in specified branch Jul 08, 2019 N/A pytest (>=3.6)
:pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Sep 17, 2021 5 - Production/Stable pytest (>=5.3) :pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Sep 17, 2021 5 - Production/Stable pytest (>=5.3)
: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-rerunfailures-all-logs` pytest plugin to re-run tests to eliminate flaky failures Mar 07, 2022 5 - Production/Stable N/A
:pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest. Jul 07, 2022 N/A N/A :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest. Aug 12, 2022 N/A N/A
:pypi:`pytest-resource` Load resource fixture plugin to use with pytest Nov 14, 2018 4 - Beta N/A :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-path` Provides path for uniform access to test resources in isolated directory May 01, 2021 5 - Production/Stable pytest (>=3.5.0)
:pypi:`pytest-responsemock` Simplified requests calls mocking for pytest Mar 10, 2022 5 - Production/Stable N/A :pypi:`pytest-responsemock` Simplified requests calls mocking for pytest Mar 10, 2022 5 - Production/Stable N/A
:pypi:`pytest-responses` py.test integration for responses Apr 26, 2021 N/A pytest (>=2.5) :pypi:`pytest-responses` py.test integration for responses Apr 26, 2021 N/A pytest (>=2.5)
:pypi:`pytest-rest-api` Aug 08, 2022 N/A pytest (>=7.1.2,<8.0.0)
:pypi:`pytest-restrict` Pytest plugin to restrict the test types allowed May 11, 2022 5 - Production/Stable pytest :pypi:`pytest-restrict` Pytest plugin to restrict the test types allowed May 11, 2022 5 - Production/Stable pytest
:pypi:`pytest-rethinkdb` A RethinkDB plugin for pytest. Jul 24, 2016 4 - Beta N/A :pypi:`pytest-rethinkdb` A RethinkDB plugin for pytest. Jul 24, 2016 4 - Beta N/A
:pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Aug 05, 2022 N/A pytest (>=7.0.0) :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Aug 11, 2022 N/A pytest (>=7.0.0)
:pypi:`pytest-reverse` Pytest plugin to reverse test order. May 11, 2022 5 - Production/Stable pytest :pypi:`pytest-reverse` Pytest plugin to reverse test order. May 11, 2022 5 - Production/Stable pytest
:pypi:`pytest-rich` Leverage rich for richer test session output Mar 03, 2022 4 - Beta pytest (>=7.0) :pypi:`pytest-rich` Leverage rich for richer test session output Mar 03, 2022 4 - Beta pytest (>=7.0)
:pypi:`pytest-rich-reporter` A pytest plugin using Rich for beautiful test result formatting. Feb 17, 2022 1 - Planning pytest (>=5.0.0) :pypi:`pytest-rich-reporter` A pytest plugin using Rich for beautiful test result formatting. Feb 17, 2022 1 - Planning pytest (>=5.0.0)
:pypi:`pytest-ringo` pytest plugin to test webapplications using the Ringo webframework Sep 27, 2017 3 - Alpha N/A :pypi:`pytest-ringo` pytest plugin to test webapplications using the Ringo webframework Sep 27, 2017 3 - Alpha N/A
:pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5)
:pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest
:pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Jul 29, 2021 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Jul 29, 2021 5 - Production/Stable pytest
:pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A
@ -928,6 +932,7 @@ This list contains 1094 plugins.
: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-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-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 :pypi:`pytest-sqlalchemy` pytest plugin with sqlalchemy related fixtures Mar 13, 2018 3 - Alpha N/A
:pypi:`pytest-sqlalchemy-mock` pytest sqlalchemy plugin for mock Aug 10, 2022 3 - Alpha pytest (>=2.0)
:pypi:`pytest-sql-bigquery` Yet another SQL-testing framework for BigQuery provided by pytest plugin Dec 19, 2019 N/A pytest :pypi:`pytest-sql-bigquery` Yet another SQL-testing framework for BigQuery provided by pytest plugin Dec 19, 2019 N/A pytest
:pypi:`pytest-squadcast` Pytest report plugin for Squadcast Feb 22, 2022 5 - Production/Stable pytest :pypi:`pytest-squadcast` Pytest report plugin for Squadcast Feb 22, 2022 5 - Production/Stable pytest
:pypi:`pytest-srcpaths` Add paths to sys.path Oct 15, 2021 N/A N/A :pypi:`pytest-srcpaths` Add paths to sys.path Oct 15, 2021 N/A N/A
@ -988,7 +993,7 @@ This list contains 1094 plugins.
:pypi:`pytest-testrail-client` pytest plugin for Testrail Sep 29, 2020 5 - Production/Stable N/A :pypi:`pytest-testrail-client` pytest plugin for Testrail Sep 29, 2020 5 - Production/Stable N/A
:pypi:`pytest-testrail-e2e` pytest plugin for creating TestRail runs and adding results Oct 11, 2021 N/A pytest (>=3.6) :pypi:`pytest-testrail-e2e` pytest plugin for creating TestRail runs and adding results Oct 11, 2021 N/A pytest (>=3.6)
:pypi:`pytest-testrail-integrator` Pytest plugin for sending report to testrail system. Aug 01, 2022 N/A pytest (>=6.2.5) :pypi:`pytest-testrail-integrator` Pytest plugin for sending report to testrail system. Aug 01, 2022 N/A pytest (>=6.2.5)
:pypi:`pytest-testrail-ns` pytest plugin for creating TestRail runs and adding results Jul 26, 2022 N/A pytest (>=3.6) :pypi:`pytest-testrail-ns` pytest plugin for creating TestRail runs and adding results Aug 12, 2022 N/A N/A
:pypi:`pytest-testrail-plugin` PyTest plugin for TestRail Apr 21, 2020 3 - Alpha pytest :pypi:`pytest-testrail-plugin` PyTest plugin for TestRail Apr 21, 2020 3 - Alpha pytest
:pypi:`pytest-testrail-reporter` Sep 10, 2018 N/A N/A :pypi:`pytest-testrail-reporter` Sep 10, 2018 N/A N/A
:pypi:`pytest-testreport` May 23, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-testreport` May 23, 2022 4 - Beta pytest (>=3.5.0)
@ -1014,7 +1019,7 @@ This list contains 1094 plugins.
:pypi:`pytest-tm4j-reporter` Cloud Jira Test Management (TM4J) PyTest reporter plugin Sep 01, 2020 N/A pytest :pypi:`pytest-tm4j-reporter` Cloud Jira Test Management (TM4J) PyTest reporter plugin Sep 01, 2020 N/A pytest
:pypi:`pytest-tmnet` A small example package Mar 01, 2022 N/A N/A :pypi:`pytest-tmnet` A small example package Mar 01, 2022 N/A N/A
:pypi:`pytest-tmp-files` Utilities to create temporary file hierarchies in pytest. Apr 03, 2022 N/A pytest :pypi:`pytest-tmp-files` Utilities to create temporary file hierarchies in pytest. Apr 03, 2022 N/A pytest
:pypi:`pytest-tmreport` this is a vue-element ui report for pytest Nov 17, 2021 N/A N/A :pypi:`pytest-tmreport` this is a vue-element ui report for pytest Aug 12, 2022 N/A N/A
:pypi:`pytest-todo` A small plugin for the pytest testing framework, marking TODO comments as failure May 23, 2019 4 - Beta pytest :pypi:`pytest-todo` A small plugin for the pytest testing framework, marking TODO comments as failure May 23, 2019 4 - Beta pytest
:pypi:`pytest-tomato` Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-tomato` Mar 01, 2019 5 - Production/Stable N/A
:pypi:`pytest-toolbelt` This is just a collection of utilities for pytest, but don't really belong in pytest proper. Aug 12, 2019 3 - Alpha N/A :pypi:`pytest-toolbelt` This is just a collection of utilities for pytest, but don't really belong in pytest proper. Aug 12, 2019 3 - Alpha N/A
@ -1036,7 +1041,7 @@ This list contains 1094 plugins.
:pypi:`pytest-tspwplib` A simple plugin to use with tspwplib Jan 08, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-tspwplib` A simple plugin to use with tspwplib Jan 08, 2021 4 - Beta pytest (>=3.5.0)
:pypi:`pytest-tst` Customize pytest options, output and exit code to make it compatible with tst Apr 27, 2022 N/A pytest (>=5.0.0) :pypi:`pytest-tst` Customize pytest options, output and exit code to make it compatible with tst Apr 27, 2022 N/A pytest (>=5.0.0)
:pypi:`pytest-tstcls` Test Class Base Mar 23, 2020 5 - Production/Stable N/A :pypi:`pytest-tstcls` Test Class Base Mar 23, 2020 5 - Production/Stable N/A
:pypi:`pytest-tui` Text User Interface (TUI) for Pytest, automatically launched after your test run is finished Aug 03, 2022 4 - Beta pytest (>=6.2.5) :pypi:`pytest-tui` Text User Interface (TUI) for Pytest, with optional auto-launch and HTML export Aug 13, 2022 4 - Beta pytest (>=6.2.5)
:pypi:`pytest-twilio-conversations-client-mock` Aug 02, 2022 N/A N/A :pypi:`pytest-twilio-conversations-client-mock` Aug 02, 2022 N/A N/A
:pypi:`pytest-twisted` A twisted plugin for pytest. Aug 30, 2021 5 - Production/Stable pytest (>=2.3) :pypi:`pytest-twisted` A twisted plugin for pytest. Aug 30, 2021 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-typechecker` Run type checkers on specified test files Feb 04, 2022 N/A pytest (>=6.2.5,<7.0.0)
@ -1106,6 +1111,7 @@ This list contains 1094 plugins.
:pypi:`pytest-yapf` Run yapf Jul 06, 2017 4 - Beta pytest (>=3.1.1) :pypi:`pytest-yapf` Run yapf Jul 06, 2017 4 - Beta pytest (>=3.1.1)
:pypi:`pytest-yapf3` Validate your Python file format with yapf Aug 03, 2020 5 - Production/Stable pytest (>=5.4) :pypi:`pytest-yapf3` Validate your Python file format with yapf Aug 03, 2020 5 - Production/Stable pytest (>=5.4)
:pypi:`pytest-yield` PyTest plugin to run tests concurrently, each \`yield\` switch context to other one Jan 23, 2019 N/A N/A :pypi:`pytest-yield` PyTest plugin to run tests concurrently, each \`yield\` switch context to other one Jan 23, 2019 N/A N/A
:pypi:`pytest-yls` Pytest plugin to test the YLS as a whole. Aug 08, 2022 N/A pytest (>=7.1.2,<8.0.0)
:pypi:`pytest-yuk` Display tests you are uneasy with, using 🤢/🤮 for pass/fail of tests marked with yuk. Mar 26, 2021 N/A N/A :pypi:`pytest-yuk` Display tests you are uneasy with, using 🤢/🤮 for pass/fail of tests marked with yuk. Mar 26, 2021 N/A N/A
:pypi:`pytest-zafira` A Zafira plugin for pytest Sep 18, 2019 5 - Production/Stable pytest (==4.1.1) :pypi:`pytest-zafira` A Zafira plugin for pytest Sep 18, 2019 5 - Production/Stable pytest (==4.1.1)
:pypi:`pytest-zap` OWASP ZAP plugin for py.test. May 12, 2014 4 - Beta N/A :pypi:`pytest-zap` OWASP ZAP plugin for py.test. May 12, 2014 4 - Beta N/A
@ -2399,7 +2405,7 @@ This list contains 1094 plugins.
Use pytest's runner to discover and execute C++ tests Use pytest's runner to discover and execute C++ tests
:pypi:`pytest-cppython` :pypi:`pytest-cppython`
*last release*: Jun 08, 2022, *last release*: Aug 13, 2022,
*status*: N/A, *status*: N/A,
*requires*: N/A *requires*: N/A
@ -3596,7 +3602,7 @@ This list contains 1094 plugins.
A pytest plugin that helps better distinguishing real test failures from setup flakiness. A pytest plugin that helps better distinguishing real test failures from setup flakiness.
:pypi:`pytest-fail-slow` :pypi:`pytest-fail-slow`
*last release*: Apr 25, 2022, *last release*: Aug 13, 2022,
*status*: 4 - Beta, *status*: 4 - Beta,
*requires*: pytest (>=6.0) *requires*: pytest (>=6.0)
@ -3840,6 +3846,13 @@ This list contains 1094 plugins.
A set of py.test fixtures to test Flask applications. A set of py.test fixtures to test Flask applications.
:pypi:`pytest-flask-ligand`
*last release*: Aug 09, 2022,
*status*: 4 - Beta,
*requires*: pytest (~=7.1)
Pytest fixtures and helper functions to use for testing flask-ligand microservices.
:pypi:`pytest-flask-sqlalchemy` :pypi:`pytest-flask-sqlalchemy`
*last release*: Apr 30, 2022, *last release*: Apr 30, 2022,
*status*: 4 - Beta, *status*: 4 - Beta,
@ -4184,7 +4197,7 @@ This list contains 1094 plugins.
A pytest plugin for use with homeassistant custom components. A pytest plugin for use with homeassistant custom components.
:pypi:`pytest-homeassistant-custom-component` :pypi:`pytest-homeassistant-custom-component`
*last release*: Aug 05, 2022, *last release*: Aug 13, 2022,
*status*: 3 - Alpha, *status*: 3 - Alpha,
*requires*: pytest (==7.1.2) *requires*: pytest (==7.1.2)
@ -4352,7 +4365,7 @@ This list contains 1094 plugins.
A plugin to sent pytest results to an Ibutsu server A plugin to sent pytest results to an Ibutsu server
:pypi:`pytest-icdiff` :pypi:`pytest-icdiff`
*last release*: Apr 08, 2020, *last release*: Aug 09, 2022,
*status*: 4 - Beta, *status*: 4 - Beta,
*requires*: N/A *requires*: N/A
@ -4443,7 +4456,7 @@ This list contains 1094 plugins.
A py.test plugin providing fixtures to simplify inmanta modules testing. A py.test plugin providing fixtures to simplify inmanta modules testing.
:pypi:`pytest-inmanta-extensions` :pypi:`pytest-inmanta-extensions`
*last release*: Apr 12, 2022, *last release*: Aug 10, 2022,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
*requires*: N/A *requires*: N/A
@ -4520,11 +4533,11 @@ This list contains 1094 plugins.
Pytest plugin for intercepting outgoing connection requests during pytest run. Pytest plugin for intercepting outgoing connection requests during pytest run.
:pypi:`pytest-invenio` :pypi:`pytest-invenio`
*last release*: May 05, 2022, *last release*: Aug 09, 2022,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
*requires*: pytest (<7,>=6) *requires*: pytest (<7,>=6)
Pytest fixtures for Invenio. "Pytest fixtures for Invenio."
:pypi:`pytest-involve` :pypi:`pytest-involve`
*last release*: Feb 02, 2020, *last release*: Feb 02, 2020,
@ -4632,7 +4645,7 @@ This list contains 1094 plugins.
Generate JSON test reports Generate JSON test reports
:pypi:`pytest-json-fixtures` :pypi:`pytest-json-fixtures`
*last release*: Aug 03, 2022, *last release*: Aug 09, 2022,
*status*: 4 - Beta, *status*: 4 - Beta,
*requires*: pytest (>=7.1.0) *requires*: pytest (>=7.1.0)
@ -4674,7 +4687,7 @@ This list contains 1094 plugins.
:pypi:`pytest-kind` :pypi:`pytest-kind`
*last release*: Jan 24, 2021, *last release*: Aug 11, 2022,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
*requires*: N/A *requires*: N/A
@ -4820,6 +4833,13 @@ This list contains 1094 plugins.
Profile code executed by pytest Profile code executed by pytest
:pypi:`pytest-line-profiler-apn`
*last release*: Aug 13, 2022,
*status*: 4 - Beta,
*requires*: N/A
Profile code executed by pytest
:pypi:`pytest-lisa` :pypi:`pytest-lisa`
*last release*: Jan 21, 2021, *last release*: Jan 21, 2021,
*status*: 3 - Alpha, *status*: 3 - Alpha,
@ -5213,7 +5233,7 @@ This list contains 1094 plugins.
An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database.
:pypi:`pytest-mock-resources` :pypi:`pytest-mock-resources`
*last release*: Jul 20, 2022, *last release*: Aug 12, 2022,
*status*: N/A, *status*: N/A,
*requires*: pytest (>=1.0) *requires*: pytest (>=1.0)
@ -5486,7 +5506,7 @@ This list contains 1094 plugins.
pytest ngs fixtures pytest ngs fixtures
:pypi:`pytest-nhsd-apim` :pypi:`pytest-nhsd-apim`
*last release*: Jul 21, 2022, *last release*: Aug 10, 2022,
*status*: N/A, *status*: N/A,
*requires*: pytest (==6.2.5) *requires*: pytest (==6.2.5)
@ -6249,7 +6269,7 @@ This list contains 1094 plugins.
pytest plugin to check source code with pylint pytest plugin to check source code with pylint
:pypi:`pytest-pyodide` :pypi:`pytest-pyodide`
*last release*: Aug 04, 2022, *last release*: Aug 10, 2022,
*status*: N/A, *status*: N/A,
*requires*: pytest *requires*: pytest
@ -6753,7 +6773,7 @@ This list contains 1094 plugins.
pytest plugin to re-run tests to eliminate flaky failures pytest plugin to re-run tests to eliminate flaky failures
:pypi:`pytest-resilient-circuits` :pypi:`pytest-resilient-circuits`
*last release*: Jul 07, 2022, *last release*: Aug 12, 2022,
*status*: N/A, *status*: N/A,
*requires*: N/A *requires*: N/A
@ -6787,6 +6807,13 @@ This list contains 1094 plugins.
py.test integration for responses py.test integration for responses
:pypi:`pytest-rest-api`
*last release*: Aug 08, 2022,
*status*: N/A,
*requires*: pytest (>=7.1.2,<8.0.0)
:pypi:`pytest-restrict` :pypi:`pytest-restrict`
*last release*: May 11, 2022, *last release*: May 11, 2022,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
@ -6802,7 +6829,7 @@ This list contains 1094 plugins.
A RethinkDB plugin for pytest. A RethinkDB plugin for pytest.
:pypi:`pytest-retry` :pypi:`pytest-retry`
*last release*: Aug 05, 2022, *last release*: Aug 11, 2022,
*status*: N/A, *status*: N/A,
*requires*: pytest (>=7.0.0) *requires*: pytest (>=7.0.0)
@ -6836,6 +6863,13 @@ This list contains 1094 plugins.
pytest plugin to test webapplications using the Ringo webframework pytest plugin to test webapplications using the Ringo webframework
:pypi:`pytest-rmsis`
*last release*: Aug 10, 2022,
*status*: N/A,
*requires*: pytest (>=5.3.5)
Sycronise pytest results to Jira RMsis
:pypi:`pytest-rng` :pypi:`pytest-rng`
*last release*: Aug 08, 2019, *last release*: Aug 08, 2019,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
@ -7487,6 +7521,13 @@ This list contains 1094 plugins.
pytest plugin with sqlalchemy related fixtures pytest plugin with sqlalchemy related fixtures
:pypi:`pytest-sqlalchemy-mock`
*last release*: Aug 10, 2022,
*status*: 3 - Alpha,
*requires*: pytest (>=2.0)
pytest sqlalchemy plugin for mock
:pypi:`pytest-sql-bigquery` :pypi:`pytest-sql-bigquery`
*last release*: Dec 19, 2019, *last release*: Dec 19, 2019,
*status*: N/A, *status*: N/A,
@ -7908,9 +7949,9 @@ This list contains 1094 plugins.
Pytest plugin for sending report to testrail system. Pytest plugin for sending report to testrail system.
:pypi:`pytest-testrail-ns` :pypi:`pytest-testrail-ns`
*last release*: Jul 26, 2022, *last release*: Aug 12, 2022,
*status*: N/A, *status*: N/A,
*requires*: pytest (>=3.6) *requires*: N/A
pytest plugin for creating TestRail runs and adding results pytest plugin for creating TestRail runs and adding results
@ -8090,7 +8131,7 @@ This list contains 1094 plugins.
Utilities to create temporary file hierarchies in pytest. Utilities to create temporary file hierarchies in pytest.
:pypi:`pytest-tmreport` :pypi:`pytest-tmreport`
*last release*: Nov 17, 2021, *last release*: Aug 12, 2022,
*status*: N/A, *status*: N/A,
*requires*: N/A *requires*: N/A
@ -8244,11 +8285,11 @@ This list contains 1094 plugins.
Test Class Base Test Class Base
:pypi:`pytest-tui` :pypi:`pytest-tui`
*last release*: Aug 03, 2022, *last release*: Aug 13, 2022,
*status*: 4 - Beta, *status*: 4 - Beta,
*requires*: pytest (>=6.2.5) *requires*: pytest (>=6.2.5)
Text User Interface (TUI) for Pytest, automatically launched after your test run is finished Text User Interface (TUI) for Pytest, with optional auto-launch and HTML export
:pypi:`pytest-twilio-conversations-client-mock` :pypi:`pytest-twilio-conversations-client-mock`
*last release*: Aug 02, 2022, *last release*: Aug 02, 2022,
@ -8733,6 +8774,13 @@ This list contains 1094 plugins.
PyTest plugin to run tests concurrently, each \`yield\` switch context to other one PyTest plugin to run tests concurrently, each \`yield\` switch context to other one
:pypi:`pytest-yls`
*last release*: Aug 08, 2022,
*status*: N/A,
*requires*: pytest (>=7.1.2,<8.0.0)
Pytest plugin to test the YLS as a whole.
:pypi:`pytest-yuk` :pypi:`pytest-yuk`
*last release*: Mar 26, 2021, *last release*: Mar 26, 2021,
*status*: N/A, *status*: N/A,

View File

@ -102,7 +102,7 @@ pytest.deprecated_call
**Tutorial**: :ref:`ensuring_function_triggers` **Tutorial**: :ref:`ensuring_function_triggers`
.. autofunction:: pytest.deprecated_call() .. autofunction:: pytest.deprecated_call([match])
:with: :with:
pytest.register_assert_rewrite pytest.register_assert_rewrite
@ -529,6 +529,7 @@ New code should avoid using :fixture:`testdir` in favor of :fixture:`pytester`.
.. autoclass:: pytest.Testdir() .. autoclass:: pytest.Testdir()
:members: :members:
:noindex: TimeoutExpired
.. fixture:: recwarn .. fixture:: recwarn

View File

@ -2,9 +2,6 @@ pallets-sphinx-themes
pluggy>=1.0 pluggy>=1.0
pygments-pytest>=2.2.0 pygments-pytest>=2.2.0
sphinx-removed-in>=0.2.0 sphinx-removed-in>=0.2.0
sphinx>=3.1,<4 sphinx>=5,<6
sphinxcontrib-trio sphinxcontrib-trio
sphinxcontrib-svg2pdfconverter sphinxcontrib-svg2pdfconverter
# XXX: sphinx<4 is broken with latest jinja2
jinja2<3.1

View File

@ -3,7 +3,6 @@ requires = [
# sync with setup.py until we discard non-pep-517/518 # sync with setup.py until we discard non-pep-517/518
"setuptools>=45.0", "setuptools>=45.0",
"setuptools-scm[toml]>=6.2.3", "setuptools-scm[toml]>=6.2.3",
"wheel",
] ]
build-backend = "setuptools.build_meta" build-backend = "setuptools.build_meta"

View File

@ -47,6 +47,7 @@ install_requires =
pluggy>=0.12,<2.0 pluggy>=0.12,<2.0
py>=1.8.2 py>=1.8.2
colorama;sys_platform=="win32" colorama;sys_platform=="win32"
exceptiongroup>=1.0.0rc8;python_version<"3.11"
importlib-metadata>=0.12;python_version<"3.8" importlib-metadata>=0.12;python_version<"3.8"
tomli>=1.0.0;python_version<"3.11" tomli>=1.0.0;python_version<"3.11"
python_requires = >=3.7 python_requires = >=3.7

View File

@ -56,6 +56,9 @@ if TYPE_CHECKING:
_TracebackStyle = Literal["long", "short", "line", "no", "native", "value", "auto"] _TracebackStyle = Literal["long", "short", "line", "no", "native", "value", "auto"]
if sys.version_info[:2] < (3, 11):
from exceptiongroup import BaseExceptionGroup
class Code: class Code:
"""Wrapper around Python code objects.""" """Wrapper around Python code objects."""
@ -924,7 +927,21 @@ class FormattedExcinfo:
while e is not None and id(e) not in seen: while e is not None and id(e) not in seen:
seen.add(id(e)) seen.add(id(e))
if excinfo_: if excinfo_:
reprtraceback = self.repr_traceback(excinfo_) # Fall back to native traceback as a temporary workaround until
# full support for exception groups added to ExceptionInfo.
# See https://github.com/pytest-dev/pytest/issues/9159
if isinstance(e, BaseExceptionGroup):
reprtraceback: Union[
ReprTracebackNative, ReprTraceback
] = ReprTracebackNative(
traceback.format_exception(
type(excinfo_.value),
excinfo_.value,
excinfo_.traceback[0]._rawentry,
)
)
else:
reprtraceback = self.repr_traceback(excinfo_)
reprcrash: Optional[ReprFileLocation] = ( reprcrash: Optional[ReprFileLocation] = (
excinfo_._getreprcrash() if self.style != "value" else None excinfo_._getreprcrash() if self.style != "value" else None
) )

View File

@ -53,7 +53,7 @@ def register_assert_rewrite(*names: str) -> None:
actually imported, usually in your __init__.py if you are a plugin actually imported, usually in your __init__.py if you are a plugin
using a package. using a package.
:raises TypeError: If the given module names are not strings. :param names: The module names to register.
""" """
for name in names: for name in names:
if not isinstance(name, str): if not isinstance(name, str):

View File

@ -20,6 +20,16 @@ from typing import Union
import attr import attr
import py import py
# fmt: off
# Workaround for https://github.com/sphinx-doc/sphinx/issues/10351.
# If `overload` is imported from `compat` instead of from `typing`,
# Sphinx doesn't recognize it as `overload` and the API docs for
# overloaded functions look good again. But type checkers handle
# it fine.
# fmt: on
if True:
from typing import overload as overload
if TYPE_CHECKING: if TYPE_CHECKING:
from typing_extensions import Final from typing_extensions import Final
@ -345,7 +355,6 @@ else:
if sys.version_info >= (3, 8): if sys.version_info >= (3, 8):
from functools import cached_property as cached_property from functools import cached_property as cached_property
else: else:
from typing import overload
from typing import Type from typing import Type
class cached_property(Generic[_S, _T]): class cached_property(Generic[_S, _T]):

View File

@ -66,14 +66,15 @@ class Parser:
) -> "OptionGroup": ) -> "OptionGroup":
"""Get (or create) a named option Group. """Get (or create) a named option Group.
:name: Name of the option group. :param name: Name of the option group.
:description: Long description for --help output. :param description: Long description for --help output.
:after: Name of another group, used for ordering --help output. :param after: Name of another group, used for ordering --help output.
:returns: The option group.
The returned group object has an ``addoption`` method with the same The returned group object has an ``addoption`` method with the same
signature as :func:`parser.addoption <pytest.Parser.addoption>` but signature as :func:`parser.addoption <pytest.Parser.addoption>` but
will be shown in the respective group in the output of will be shown in the respective group in the output of
``pytest. --help``. ``pytest --help``.
""" """
for group in self._groups: for group in self._groups:
if group.name == name: if group.name == name:
@ -89,10 +90,11 @@ class Parser:
def addoption(self, *opts: str, **attrs: Any) -> None: def addoption(self, *opts: str, **attrs: Any) -> None:
"""Register a command line option. """Register a command line option.
:opts: Option names, can be short or long options. :param opts:
:attrs: Same attributes which the ``add_argument()`` function of the Option names, can be short or long options.
`argparse library <https://docs.python.org/library/argparse.html>`_ :param attrs:
accepts. Same attributes as the argparse library's :py:func:`add_argument()
<argparse.ArgumentParser.add_argument>` function accepts.
After command line parsing, options are available on the pytest config After command line parsing, options are available on the pytest config
object via ``config.option.NAME`` where ``NAME`` is usually set object via ``config.option.NAME`` where ``NAME`` is usually set
@ -148,7 +150,10 @@ class Parser:
args: Sequence[Union[str, "os.PathLike[str]"]], args: Sequence[Union[str, "os.PathLike[str]"]],
namespace: Optional[argparse.Namespace] = None, namespace: Optional[argparse.Namespace] = None,
) -> argparse.Namespace: ) -> argparse.Namespace:
"""Parse and return a namespace object with known arguments at this point.""" """Parse the known arguments at this point.
:returns: An argparse namespace object.
"""
return self.parse_known_and_unknown_args(args, namespace=namespace)[0] return self.parse_known_and_unknown_args(args, namespace=namespace)[0]
def parse_known_and_unknown_args( def parse_known_and_unknown_args(
@ -156,8 +161,13 @@ class Parser:
args: Sequence[Union[str, "os.PathLike[str]"]], args: Sequence[Union[str, "os.PathLike[str]"]],
namespace: Optional[argparse.Namespace] = None, namespace: Optional[argparse.Namespace] = None,
) -> Tuple[argparse.Namespace, List[str]]: ) -> Tuple[argparse.Namespace, List[str]]:
"""Parse and return a namespace object with known arguments, and """Parse the known arguments at this point, and also return the
the remaining arguments unknown at this point.""" remaining unknown arguments.
:returns:
A tuple containing an argparse namespace object for the known
arguments, and a list of the unknown arguments.
"""
optparser = self._getparser() optparser = self._getparser()
strargs = [os.fspath(x) for x in args] strargs = [os.fspath(x) for x in args]
return optparser.parse_known_args(strargs, namespace=namespace) return optparser.parse_known_args(strargs, namespace=namespace)
@ -173,9 +183,9 @@ class Parser:
) -> None: ) -> None:
"""Register an ini-file option. """Register an ini-file option.
:name: :param name:
Name of the ini-variable. Name of the ini-variable.
:type: :param type:
Type of the variable. Can be: Type of the variable. Can be:
* ``string``: a string * ``string``: a string
@ -189,7 +199,7 @@ class Parser:
The ``paths`` variable type. The ``paths`` variable type.
Defaults to ``string`` if ``None`` or not passed. Defaults to ``string`` if ``None`` or not passed.
:default: :param default:
Default value if no ini-file option exists but is queried. Default value if no ini-file option exists but is queried.
The value of ini-variables can be retrieved via a call to The value of ini-variables can be retrieved via a call to
@ -354,24 +364,30 @@ class OptionGroup:
self.options: List[Argument] = [] self.options: List[Argument] = []
self.parser = parser self.parser = parser
def addoption(self, *optnames: str, **attrs: Any) -> None: def addoption(self, *opts: str, **attrs: Any) -> None:
"""Add an option to this group. """Add an option to this group.
If a shortened version of a long option is specified, it will If a shortened version of a long option is specified, it will
be suppressed in the help. ``addoption('--twowords', '--two-words')`` be suppressed in the help. ``addoption('--twowords', '--two-words')``
results in help showing ``--two-words`` only, but ``--twowords`` gets results in help showing ``--two-words`` only, but ``--twowords`` gets
accepted **and** the automatic destination is in ``args.twowords``. accepted **and** the automatic destination is in ``args.twowords``.
:param opts:
Option names, can be short or long options.
:param attrs:
Same attributes as the argparse library's :py:func:`add_argument()
<argparse.ArgumentParser.add_argument>` function accepts.
""" """
conflict = set(optnames).intersection( conflict = set(opts).intersection(
name for opt in self.options for name in opt.names() name for opt in self.options for name in opt.names()
) )
if conflict: if conflict:
raise ValueError("option names %s already added" % conflict) raise ValueError("option names %s already added" % conflict)
option = Argument(*optnames, **attrs) option = Argument(*opts, **attrs)
self._addoption_instance(option, shortupper=False) self._addoption_instance(option, shortupper=False)
def _addoption(self, *optnames: str, **attrs: Any) -> None: def _addoption(self, *opts: str, **attrs: Any) -> None:
option = Argument(*optnames, **attrs) option = Argument(*opts, **attrs)
self._addoption_instance(option, shortupper=True) self._addoption_instance(option, shortupper=True)
def _addoption_instance(self, option: "Argument", shortupper: bool = False) -> None: def _addoption_instance(self, option: "Argument", shortupper: bool = False) -> None:

View File

@ -20,7 +20,6 @@ from typing import List
from typing import MutableMapping from typing import MutableMapping
from typing import NoReturn from typing import NoReturn
from typing import Optional from typing import Optional
from typing import overload
from typing import Sequence from typing import Sequence
from typing import Set from typing import Set
from typing import Tuple from typing import Tuple
@ -48,6 +47,7 @@ from _pytest.compat import getimfunc
from _pytest.compat import getlocation from _pytest.compat import getlocation
from _pytest.compat import is_generator from _pytest.compat import is_generator
from _pytest.compat import NOTSET from _pytest.compat import NOTSET
from _pytest.compat import overload
from _pytest.compat import safe_getattr from _pytest.compat import safe_getattr
from _pytest.config import _PluggyPlugin from _pytest.config import _PluggyPlugin
from _pytest.config import Config from _pytest.config import Config
@ -513,8 +513,8 @@ class FixtureRequest:
return self._pyfuncitem.session # type: ignore[no-any-return] return self._pyfuncitem.session # type: ignore[no-any-return]
def addfinalizer(self, finalizer: Callable[[], object]) -> None: def addfinalizer(self, finalizer: Callable[[], object]) -> None:
"""Add finalizer/teardown function to be called after the last test """Add finalizer/teardown function to be called without arguments after
within the requesting test context finished execution.""" the last test within the requesting test context finished execution."""
# XXX usually this method is shadowed by fixturedef specific ones. # XXX usually this method is shadowed by fixturedef specific ones.
self._addfinalizer(finalizer, scope=self.scope) self._addfinalizer(finalizer, scope=self.scope)
@ -529,13 +529,16 @@ class FixtureRequest:
on all function invocations. on all function invocations.
:param marker: :param marker:
A :class:`pytest.MarkDecorator` object created by a call An object created by a call to ``pytest.mark.NAME(...)``.
to ``pytest.mark.NAME(...)``.
""" """
self.node.add_marker(marker) self.node.add_marker(marker)
def raiseerror(self, msg: Optional[str]) -> NoReturn: def raiseerror(self, msg: Optional[str]) -> NoReturn:
"""Raise a FixtureLookupError with the given message.""" """Raise a FixtureLookupError exception.
:param msg:
An optional custom error message.
"""
raise self._fixturemanager.FixtureLookupError(None, self, msg) raise self._fixturemanager.FixtureLookupError(None, self, msg)
def _fillfixtures(self) -> None: def _fillfixtures(self) -> None:
@ -557,6 +560,8 @@ class FixtureRequest:
phase, but during the test teardown phase a fixture's value may not phase, but during the test teardown phase a fixture's value may not
be available. be available.
:param argname:
The fixture name.
:raises pytest.FixtureLookupError: :raises pytest.FixtureLookupError:
If the given fixture could not be found. If the given fixture could not be found.
""" """
@ -768,8 +773,8 @@ class SubRequest(FixtureRequest):
return f"<SubRequest {self.fixturename!r} for {self._pyfuncitem!r}>" return f"<SubRequest {self.fixturename!r} for {self._pyfuncitem!r}>"
def addfinalizer(self, finalizer: Callable[[], object]) -> None: def addfinalizer(self, finalizer: Callable[[], object]) -> None:
"""Add finalizer/teardown function to be called after the last test """Add finalizer/teardown function to be called without arguments after
within the requesting test context finished execution.""" the last test within the requesting test context finished execution."""
self._fixturedef.addfinalizer(finalizer) self._fixturedef.addfinalizer(finalizer)
def _schedule_finalizers( def _schedule_finalizers(
@ -1226,7 +1231,7 @@ def fixture(
@overload @overload
def fixture( def fixture( # noqa: F811
fixture_function: None = ..., fixture_function: None = ...,
*, *,
scope: "Union[_ScopeName, Callable[[str, Config], _ScopeName]]" = ..., scope: "Union[_ScopeName, Callable[[str, Config], _ScopeName]]" = ...,
@ -1240,7 +1245,7 @@ def fixture(
... ...
def fixture( def fixture( # noqa: F811
fixture_function: Optional[FixtureFunction] = None, fixture_function: Optional[FixtureFunction] = None,
*, *,
scope: "Union[_ScopeName, Callable[[str, Config], _ScopeName]]" = "function", scope: "Union[_ScopeName, Callable[[str, Config], _ScopeName]]" = "function",

View File

@ -143,7 +143,7 @@ def pytest_configure(config: "Config") -> None:
def pytest_cmdline_parse( def pytest_cmdline_parse(
pluginmanager: "PytestPluginManager", args: List[str] pluginmanager: "PytestPluginManager", args: List[str]
) -> Optional["Config"]: ) -> Optional["Config"]:
"""Return an initialized config object, parsing the specified args. """Return an initialized :class:`~pytest.Config`, parsing the specified args.
Stops at first non-None result, see :ref:`firstresult`. Stops at first non-None result, see :ref:`firstresult`.
@ -152,8 +152,9 @@ def pytest_cmdline_parse(
``plugins`` arg when using `pytest.main`_ to perform an in-process ``plugins`` arg when using `pytest.main`_ to perform an in-process
test run. test run.
:param pytest.PytestPluginManager pluginmanager: The pytest plugin manager. :param pluginmanager: The pytest plugin manager.
:param List[str] args: List of arguments passed on the command line. :param args: List of arguments passed on the command line.
:returns: A pytest config object.
""" """
@ -167,8 +168,8 @@ def pytest_cmdline_preparse(config: "Config", args: List[str]) -> None:
.. note:: .. note::
This hook will not be called for ``conftest.py`` files, only for setuptools plugins. This hook will not be called for ``conftest.py`` files, only for setuptools plugins.
:param pytest.Config config: The pytest config object. :param config: The pytest config object.
:param List[str] args: Arguments passed on the command line. :param args: Arguments passed on the command line.
""" """
@ -179,7 +180,8 @@ def pytest_cmdline_main(config: "Config") -> Optional[Union["ExitCode", int]]:
Stops at first non-None result, see :ref:`firstresult`. Stops at first non-None result, see :ref:`firstresult`.
:param pytest.Config config: The pytest config object. :param config: The pytest config object.
:returns: The exit code.
""" """
@ -192,9 +194,9 @@ def pytest_load_initial_conftests(
.. note:: .. note::
This hook will not be called for ``conftest.py`` files, only for setuptools plugins. This hook will not be called for ``conftest.py`` files, only for setuptools plugins.
:param pytest.Config early_config: The pytest config object. :param early_config: The pytest config object.
:param List[str] args: Arguments passed on the command line. :param args: Arguments passed on the command line.
:param pytest.Parser parser: To add command line options. :param parser: To add command line options.
""" """
@ -236,7 +238,7 @@ def pytest_collection(session: "Session") -> Optional[object]:
for example the terminal plugin uses it to start displaying the collection for example the terminal plugin uses it to start displaying the collection
counter (and returns `None`). counter (and returns `None`).
:param pytest.Session session: The pytest session object. :param session: The pytest session object.
""" """
@ -246,16 +248,16 @@ def pytest_collection_modifyitems(
"""Called after collection has been performed. May filter or re-order """Called after collection has been performed. May filter or re-order
the items in-place. the items in-place.
:param pytest.Session session: The pytest session object. :param session: The pytest session object.
:param pytest.Config config: The pytest config object. :param config: The pytest config object.
:param List[pytest.Item] items: List of item objects. :param items: List of item objects.
""" """
def pytest_collection_finish(session: "Session") -> None: def pytest_collection_finish(session: "Session") -> None:
"""Called after collection has been performed and modified. """Called after collection has been performed and modified.
:param pytest.Session session: The pytest session object. :param session: The pytest session object.
""" """
@ -270,9 +272,9 @@ def pytest_ignore_collect(
Stops at first non-None result, see :ref:`firstresult`. Stops at first non-None result, see :ref:`firstresult`.
:param pathlib.Path collection_path : The path to analyze. :param collection_path: The path to analyze.
:param LEGACY_PATH path: The path to analyze (deprecated). :param path: The path to analyze (deprecated).
:param pytest.Config config: The pytest config object. :param config: The pytest config object.
.. versionchanged:: 7.0.0 .. versionchanged:: 7.0.0
The ``collection_path`` parameter was added as a :class:`pathlib.Path` The ``collection_path`` parameter was added as a :class:`pathlib.Path`
@ -284,12 +286,12 @@ def pytest_ignore_collect(
def pytest_collect_file( def pytest_collect_file(
file_path: Path, path: "LEGACY_PATH", parent: "Collector" file_path: Path, path: "LEGACY_PATH", parent: "Collector"
) -> "Optional[Collector]": ) -> "Optional[Collector]":
"""Create a Collector for the given path, or None if not relevant. """Create a :class:`~pytest.Collector` for the given path, or None if not relevant.
The new node needs to have the specified ``parent`` as a parent. The new node needs to have the specified ``parent`` as a parent.
:param pathlib.Path file_path: The path to analyze. :param file_path: The path to analyze.
:param LEGACY_PATH path: The path to collect (deprecated). :param path: The path to collect (deprecated).
.. versionchanged:: 7.0.0 .. versionchanged:: 7.0.0
The ``file_path`` parameter was added as a :class:`pathlib.Path` The ``file_path`` parameter was added as a :class:`pathlib.Path`
@ -302,21 +304,36 @@ def pytest_collect_file(
def pytest_collectstart(collector: "Collector") -> None: def pytest_collectstart(collector: "Collector") -> None:
"""Collector starts collecting.""" """Collector starts collecting.
:param collector:
The collector.
"""
def pytest_itemcollected(item: "Item") -> None: def pytest_itemcollected(item: "Item") -> None:
"""We just collected a test item.""" """We just collected a test item.
:param item:
The item.
"""
def pytest_collectreport(report: "CollectReport") -> None: def pytest_collectreport(report: "CollectReport") -> None:
"""Collector finished collecting.""" """Collector finished collecting.
:param report:
The collect report.
"""
def pytest_deselected(items: Sequence["Item"]) -> None: def pytest_deselected(items: Sequence["Item"]) -> None:
"""Called for deselected test items, e.g. by keyword. """Called for deselected test items, e.g. by keyword.
May be called multiple times. May be called multiple times.
:param items:
The items.
""" """
@ -326,6 +343,9 @@ def pytest_make_collect_report(collector: "Collector") -> "Optional[CollectRepor
a :class:`~pytest.CollectReport`. a :class:`~pytest.CollectReport`.
Stops at first non-None result, see :ref:`firstresult`. Stops at first non-None result, see :ref:`firstresult`.
:param collector:
The collector.
""" """
@ -338,16 +358,16 @@ def pytest_make_collect_report(collector: "Collector") -> "Optional[CollectRepor
def pytest_pycollect_makemodule( def pytest_pycollect_makemodule(
module_path: Path, path: "LEGACY_PATH", parent module_path: Path, path: "LEGACY_PATH", parent
) -> Optional["Module"]: ) -> Optional["Module"]:
"""Return a Module collector or None for the given path. """Return a :class:`pytest.Module` collector or None for the given path.
This hook will be called for each matching test module path. This hook will be called for each matching test module path.
The pytest_collect_file hook needs to be used if you want to The :hook:`pytest_collect_file` hook needs to be used if you want to
create test modules for files that do not match as a test module. create test modules for files that do not match as a test module.
Stops at first non-None result, see :ref:`firstresult`. Stops at first non-None result, see :ref:`firstresult`.
:param pathlib.Path module_path: The path of the module to collect. :param module_path: The path of the module to collect.
:param LEGACY_PATH path: The path of the module to collect (deprecated). :param path: The path of the module to collect (deprecated).
.. versionchanged:: 7.0.0 .. versionchanged:: 7.0.0
The ``module_path`` parameter was added as a :class:`pathlib.Path` The ``module_path`` parameter was added as a :class:`pathlib.Path`
@ -364,6 +384,15 @@ def pytest_pycollect_makeitem(
"""Return a custom item/collector for a Python object in a module, or None. """Return a custom item/collector for a Python object in a module, or None.
Stops at first non-None result, see :ref:`firstresult`. Stops at first non-None result, see :ref:`firstresult`.
:param collector:
The module/class collector.
:param name:
The name of the object in the module/class.
:param obj:
The object.
:returns:
The created items/collectors.
""" """
@ -372,11 +401,18 @@ def pytest_pyfunc_call(pyfuncitem: "Function") -> Optional[object]:
"""Call underlying test function. """Call underlying test function.
Stops at first non-None result, see :ref:`firstresult`. Stops at first non-None result, see :ref:`firstresult`.
:param pyfuncitem:
The function item.
""" """
def pytest_generate_tests(metafunc: "Metafunc") -> None: def pytest_generate_tests(metafunc: "Metafunc") -> None:
"""Generate (multiple) parametrized calls to a test function.""" """Generate (multiple) parametrized calls to a test function.
:param metafunc:
The :class:`~pytest.Metafunc` helper for the test function.
"""
@hookspec(firstresult=True) @hookspec(firstresult=True)
@ -391,7 +427,7 @@ def pytest_make_parametrize_id(
Stops at first non-None result, see :ref:`firstresult`. Stops at first non-None result, see :ref:`firstresult`.
:param pytest.Config config: The pytest config object. :param config: The pytest config object.
:param val: The parametrized value. :param val: The parametrized value.
:param str argname: The automatic parameter name produced by pytest. :param str argname: The automatic parameter name produced by pytest.
""" """
@ -416,7 +452,7 @@ def pytest_runtestloop(session: "Session") -> Optional[object]:
If at any point ``session.shouldfail`` or ``session.shouldstop`` are set, the If at any point ``session.shouldfail`` or ``session.shouldstop`` are set, the
loop is terminated after the runtest protocol for the current item is finished. loop is terminated after the runtest protocol for the current item is finished.
:param pytest.Session session: The pytest session object. :param session: The pytest session object.
Stops at first non-None result, see :ref:`firstresult`. Stops at first non-None result, see :ref:`firstresult`.
The return value is not used, but only stops further processing. The return value is not used, but only stops further processing.
@ -468,7 +504,7 @@ def pytest_runtest_logstart(
See :hook:`pytest_runtest_protocol` for a description of the runtest protocol. See :hook:`pytest_runtest_protocol` for a description of the runtest protocol.
:param str nodeid: Full node ID of the item. :param nodeid: Full node ID of the item.
:param location: A tuple of ``(filename, lineno, testname)``. :param location: A tuple of ``(filename, lineno, testname)``.
""" """
@ -480,7 +516,7 @@ def pytest_runtest_logfinish(
See :hook:`pytest_runtest_protocol` for a description of the runtest protocol. See :hook:`pytest_runtest_protocol` for a description of the runtest protocol.
:param str nodeid: Full node ID of the item. :param nodeid: Full node ID of the item.
:param location: A tuple of ``(filename, lineno, testname)``. :param location: A tuple of ``(filename, lineno, testname)``.
""" """
@ -492,6 +528,9 @@ def pytest_runtest_setup(item: "Item") -> None:
parents (which haven't been setup yet). This includes obtaining the parents (which haven't been setup yet). This includes obtaining the
values of fixtures required by the item (which haven't been obtained values of fixtures required by the item (which haven't been obtained
yet). yet).
:param item:
The item.
""" """
@ -499,6 +538,9 @@ def pytest_runtest_call(item: "Item") -> None:
"""Called to run the test for test item (the call phase). """Called to run the test for test item (the call phase).
The default implementation calls ``item.runtest()``. The default implementation calls ``item.runtest()``.
:param item:
The item.
""" """
@ -510,6 +552,8 @@ def pytest_runtest_teardown(item: "Item", nextitem: Optional["Item"]) -> None:
includes running the teardown phase of fixtures required by the item (if includes running the teardown phase of fixtures required by the item (if
they go out of scope). they go out of scope).
:param item:
The item.
:param nextitem: :param nextitem:
The scheduled-to-be-next test item (None if no further test item is The scheduled-to-be-next test item (None if no further test item is
scheduled). This argument is used to perform exact teardowns, i.e. scheduled). This argument is used to perform exact teardowns, i.e.
@ -527,6 +571,7 @@ def pytest_runtest_makereport(
See :hook:`pytest_runtest_protocol` for a description of the runtest protocol. See :hook:`pytest_runtest_protocol` for a description of the runtest protocol.
:param item: The item.
:param call: The :class:`~pytest.CallInfo` for the phase. :param call: The :class:`~pytest.CallInfo` for the phase.
Stops at first non-None result, see :ref:`firstresult`. Stops at first non-None result, see :ref:`firstresult`.
@ -547,7 +592,11 @@ def pytest_report_to_serializable(
report: Union["CollectReport", "TestReport"], report: Union["CollectReport", "TestReport"],
) -> Optional[Dict[str, Any]]: ) -> Optional[Dict[str, Any]]:
"""Serialize the given report object into a data structure suitable for """Serialize the given report object into a data structure suitable for
sending over the wire, e.g. converted to JSON.""" sending over the wire, e.g. converted to JSON.
:param config: The pytest config object.
:param report: The report.
"""
@hookspec(firstresult=True) @hookspec(firstresult=True)
@ -556,7 +605,10 @@ def pytest_report_from_serializable(
data: Dict[str, Any], data: Dict[str, Any],
) -> Optional[Union["CollectReport", "TestReport"]]: ) -> Optional[Union["CollectReport", "TestReport"]]:
"""Restore a report object previously serialized with """Restore a report object previously serialized with
:hook:`pytest_report_to_serializable`.""" :hook:`pytest_report_to_serializable`.
:param config: The pytest config object.
"""
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
@ -570,7 +622,12 @@ def pytest_fixture_setup(
) -> Optional[object]: ) -> Optional[object]:
"""Perform fixture setup execution. """Perform fixture setup execution.
:returns: The return value of the call to the fixture function. :param fixturdef:
The fixture definition object.
:param request:
The fixture request object.
:returns:
The return value of the call to the fixture function.
Stops at first non-None result, see :ref:`firstresult`. Stops at first non-None result, see :ref:`firstresult`.
@ -586,7 +643,13 @@ def pytest_fixture_post_finalizer(
) -> None: ) -> None:
"""Called after fixture teardown, but before the cache is cleared, so """Called after fixture teardown, but before the cache is cleared, so
the fixture result ``fixturedef.cached_result`` is still available (not the fixture result ``fixturedef.cached_result`` is still available (not
``None``).""" ``None``).
:param fixturdef:
The fixture definition object.
:param request:
The fixture request object.
"""
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
@ -598,7 +661,7 @@ def pytest_sessionstart(session: "Session") -> None:
"""Called after the ``Session`` object has been created and before performing collection """Called after the ``Session`` object has been created and before performing collection
and entering the run test loop. and entering the run test loop.
:param pytest.Session session: The pytest session object. :param session: The pytest session object.
""" """
@ -608,15 +671,15 @@ def pytest_sessionfinish(
) -> None: ) -> None:
"""Called after whole test run finished, right before returning the exit status to the system. """Called after whole test run finished, right before returning the exit status to the system.
:param pytest.Session session: The pytest session object. :param session: The pytest session object.
:param int exitstatus: The status which pytest will return to the system. :param exitstatus: The status which pytest will return to the system.
""" """
def pytest_unconfigure(config: "Config") -> None: def pytest_unconfigure(config: "Config") -> None:
"""Called before test process is exited. """Called before test process is exited.
:param pytest.Config config: The pytest config object. :param config: The pytest config object.
""" """
@ -635,7 +698,10 @@ def pytest_assertrepr_compare(
*in* a string will be escaped. Note that all but the first line will *in* a string will be escaped. Note that all but the first line will
be indented slightly, the intention is for the first line to be a summary. be indented slightly, the intention is for the first line to be a summary.
:param pytest.Config config: The pytest config object. :param config: The pytest config object.
:param op: The operator, e.g. `"=="`, `"!="`, `"not in"`.
:param left: The left operand.
:param right: The right operand.
""" """
@ -660,10 +726,10 @@ def pytest_assertion_pass(item: "Item", lineno: int, orig: str, expl: str) -> No
You need to **clean the .pyc** files in your project directory and interpreter libraries You need to **clean the .pyc** files in your project directory and interpreter libraries
when enabling this option, as assertions will require to be re-written. when enabling this option, as assertions will require to be re-written.
:param pytest.Item item: pytest item object of current test. :param item: pytest item object of current test.
:param int lineno: Line number of the assert statement. :param lineno: Line number of the assert statement.
:param str orig: String with the original assertion. :param orig: String with the original assertion.
:param str expl: String with the assert explanation. :param expl: String with the assert explanation.
""" """
@ -677,9 +743,9 @@ def pytest_report_header(
) -> Union[str, List[str]]: ) -> Union[str, List[str]]:
"""Return a string or list of strings to be displayed as header info for terminal reporting. """Return a string or list of strings to be displayed as header info for terminal reporting.
:param pytest.Config config: The pytest config object. :param config: The pytest config object.
:param Path start_path: The starting dir. :param start_path: The starting dir.
:param LEGACY_PATH startdir: The starting dir (deprecated). :param startdir: The starting dir (deprecated).
.. note:: .. note::
@ -714,9 +780,9 @@ def pytest_report_collectionfinish(
.. versionadded:: 3.2 .. versionadded:: 3.2
:param pytest.Config config: The pytest config object. :param config: The pytest config object.
:param Path start_path: The starting dir. :param start_path: The starting dir.
:param LEGACY_PATH startdir: The starting dir (deprecated). :param startdir: The starting dir (deprecated).
:param items: List of pytest items that are going to be executed; this list should not be modified. :param items: List of pytest items that are going to be executed; this list should not be modified.
.. note:: .. note::
@ -755,6 +821,7 @@ def pytest_report_teststatus(
:param report: The report object whose status is to be returned. :param report: The report object whose status is to be returned.
:param config: The pytest config object. :param config: The pytest config object.
:returns: The test status.
Stops at first non-None result, see :ref:`firstresult`. Stops at first non-None result, see :ref:`firstresult`.
""" """
@ -767,9 +834,9 @@ def pytest_terminal_summary(
) -> None: ) -> None:
"""Add a section to terminal summary reporting. """Add a section to terminal summary reporting.
:param _pytest.terminal.TerminalReporter terminalreporter: The internal terminal reporter object. :param terminalreporter: The internal terminal reporter object.
:param int exitstatus: The exit status that will be reported back to the OS. :param exitstatus: The exit status that will be reported back to the OS.
:param pytest.Config config: The pytest config object. :param config: The pytest config object.
.. versionadded:: 4.2 .. versionadded:: 4.2
The ``config`` parameter. The ``config`` parameter.
@ -785,21 +852,21 @@ def pytest_warning_recorded(
) -> None: ) -> None:
"""Process a warning captured by the internal pytest warnings plugin. """Process a warning captured by the internal pytest warnings plugin.
:param warnings.WarningMessage warning_message: :param warning_message:
The captured warning. This is the same object produced by :py:func:`warnings.catch_warnings`, and contains The captured warning. This is the same object produced by :py:func:`warnings.catch_warnings`, and contains
the same attributes as the parameters of :py:func:`warnings.showwarning`. the same attributes as the parameters of :py:func:`warnings.showwarning`.
:param str when: :param when:
Indicates when the warning was captured. Possible values: Indicates when the warning was captured. Possible values:
* ``"config"``: during pytest configuration/initialization stage. * ``"config"``: during pytest configuration/initialization stage.
* ``"collect"``: during test collection. * ``"collect"``: during test collection.
* ``"runtest"``: during test execution. * ``"runtest"``: during test execution.
:param str nodeid: :param nodeid:
Full id of the item. Full id of the item.
:param tuple|None location: :param location:
When available, holds information about the execution context of the captured When available, holds information about the execution context of the captured
warning (filename, linenumber, function). ``function`` evaluates to <module> warning (filename, linenumber, function). ``function`` evaluates to <module>
when the execution context is at the module level. when the execution context is at the module level.
@ -824,7 +891,7 @@ def pytest_markeval_namespace(config: "Config") -> Dict[str, Any]:
.. versionadded:: 6.2 .. versionadded:: 6.2
:param pytest.Config config: The pytest config object. :param config: The pytest config object.
:returns: A dictionary of additional globals to add. :returns: A dictionary of additional globals to add.
""" """
@ -842,13 +909,19 @@ def pytest_internalerror(
Return True to suppress the fallback handling of printing an Return True to suppress the fallback handling of printing an
INTERNALERROR message directly to sys.stderr. INTERNALERROR message directly to sys.stderr.
:param excrepr: The exception repr object.
:param excinfo: The exception info.
""" """
def pytest_keyboard_interrupt( def pytest_keyboard_interrupt(
excinfo: "ExceptionInfo[Union[KeyboardInterrupt, Exit]]", excinfo: "ExceptionInfo[Union[KeyboardInterrupt, Exit]]",
) -> None: ) -> None:
"""Called for keyboard interrupt.""" """Called for keyboard interrupt.
:param excinfo: The exception info.
"""
def pytest_exception_interact( def pytest_exception_interact(
@ -867,6 +940,13 @@ def pytest_exception_interact(
This hook is not called if the exception that was raised is an internal This hook is not called if the exception that was raised is an internal
exception like ``skip.Exception``. exception like ``skip.Exception``.
:param node:
The item or collector.
:param call:
The call information. Contains the exception.
:param report:
The collection or test report.
""" """
@ -876,8 +956,8 @@ def pytest_enter_pdb(config: "Config", pdb: "pdb.Pdb") -> None:
Can be used by plugins to take special action just before the python Can be used by plugins to take special action just before the python
debugger enters interactive mode. debugger enters interactive mode.
:param pytest.Config config: The pytest config object. :param config: The pytest config object.
:param pdb.Pdb pdb: The Pdb instance. :param pdb: The Pdb instance.
""" """
@ -887,6 +967,6 @@ def pytest_leave_pdb(config: "Config", pdb: "pdb.Pdb") -> None:
Can be used by plugins to take special action just after the python Can be used by plugins to take special action just after the python
debugger leaves interactive mode. debugger leaves interactive mode.
:param pytest.Config config: The pytest config object. :param config: The pytest config object.
:param pdb.Pdb pdb: The Pdb instance. :param pdb: The Pdb instance.
""" """

View File

@ -231,7 +231,7 @@ class _NodeReporter:
msg = f'failed on teardown with "{reason}"' msg = f'failed on teardown with "{reason}"'
else: else:
msg = f'failed on setup with "{reason}"' msg = f'failed on setup with "{reason}"'
self._add_simple("error", msg, str(report.longrepr)) self._add_simple("error", bin_xml_escape(msg), str(report.longrepr))
def append_skipped(self, report: TestReport) -> None: def append_skipped(self, report: TestReport) -> None:
if hasattr(report, "wasxfail"): if hasattr(report, "wasxfail"):
@ -354,7 +354,10 @@ def record_testsuite_property(request: FixtureRequest) -> Callable[[str, object]
record_testsuite_property("ARCH", "PPC") record_testsuite_property("ARCH", "PPC")
record_testsuite_property("STORAGE_TYPE", "CEPH") record_testsuite_property("STORAGE_TYPE", "CEPH")
``name`` must be a string, ``value`` will be converted to a string and properly xml-escaped. :param name:
The property name.
:param value:
The property value. Will be converted to a string.
.. warning:: .. warning::

View File

@ -37,6 +37,8 @@ from _pytest.terminal import TerminalReporter
if TYPE_CHECKING: if TYPE_CHECKING:
logging_StreamHandler = logging.StreamHandler[StringIO] logging_StreamHandler = logging.StreamHandler[StringIO]
from typing_extensions import Literal
else: else:
logging_StreamHandler = logging.StreamHandler logging_StreamHandler = logging.StreamHandler
@ -382,20 +384,19 @@ class LogCaptureFixture:
@property @property
def handler(self) -> LogCaptureHandler: def handler(self) -> LogCaptureHandler:
"""Get the logging handler used by the fixture. """Get the logging handler used by the fixture."""
:rtype: LogCaptureHandler
"""
return self._item.stash[caplog_handler_key] return self._item.stash[caplog_handler_key]
def get_records(self, when: str) -> List[logging.LogRecord]: def get_records(
self, when: "Literal['setup', 'call', 'teardown']"
) -> List[logging.LogRecord]:
"""Get the logging records for one of the possible test phases. """Get the logging records for one of the possible test phases.
:param str when: :param when:
Which test phase to obtain the records from. Valid values are: "setup", "call" and "teardown". Which test phase to obtain the records from.
Valid values are: "setup", "call" and "teardown".
:returns: The list of captured records at the given stage. :returns: The list of captured records at the given stage.
:rtype: List[logging.LogRecord]
.. versionadded:: 3.4 .. versionadded:: 3.4
""" """
@ -452,8 +453,8 @@ class LogCaptureFixture:
The levels of the loggers changed by this function will be The levels of the loggers changed by this function will be
restored to their initial values at the end of the test. restored to their initial values at the end of the test.
:param int level: The level. :param level: The level.
:param str logger: The logger to update. If not given, the root logger. :param logger: The logger to update. If not given, the root logger.
""" """
logger_obj = logging.getLogger(logger) logger_obj = logging.getLogger(logger)
# Save the original log-level to restore it during teardown. # Save the original log-level to restore it during teardown.
@ -471,8 +472,8 @@ class LogCaptureFixture:
the end of the 'with' statement the level is restored to its original the end of the 'with' statement the level is restored to its original
value. value.
:param int level: The level. :param level: The level.
:param str logger: The logger to update. If not given, the root logger. :param logger: The logger to update. If not given, the root logger.
""" """
logger_obj = logging.getLogger(logger) logger_obj = logging.getLogger(logger)
orig_level = logger_obj.level orig_level = logger_obj.level

View File

@ -12,7 +12,6 @@ from typing import FrozenSet
from typing import Iterator from typing import Iterator
from typing import List from typing import List
from typing import Optional from typing import Optional
from typing import overload
from typing import Sequence from typing import Sequence
from typing import Set from typing import Set
from typing import Tuple from typing import Tuple
@ -25,6 +24,7 @@ import attr
import _pytest._code import _pytest._code
from _pytest import nodes from _pytest import nodes
from _pytest.compat import final from _pytest.compat import final
from _pytest.compat import overload
from _pytest.config import Config from _pytest.config import Config
from _pytest.config import directory_arg from _pytest.config import directory_arg
from _pytest.config import ExitCode from _pytest.config import ExitCode
@ -597,12 +597,12 @@ class Session(nodes.FSCollector):
... ...
@overload @overload
def perform_collect( def perform_collect( # noqa: F811
self, args: Optional[Sequence[str]] = ..., genitems: bool = ... self, args: Optional[Sequence[str]] = ..., genitems: bool = ...
) -> Sequence[Union[nodes.Item, nodes.Collector]]: ) -> Sequence[Union[nodes.Item, nodes.Collector]]:
... ...
def perform_collect( def perform_collect( # noqa: F811
self, args: Optional[Sequence[str]] = None, genitems: bool = True self, args: Optional[Sequence[str]] = None, genitems: bool = True
) -> Sequence[Union[nodes.Item, nodes.Collector]]: ) -> Sequence[Union[nodes.Item, nodes.Collector]]:
"""Perform the collection phase for this session. """Perform the collection phase for this session.

View File

@ -62,8 +62,8 @@ def param(
assert eval(test_input) == expected assert eval(test_input) == expected
:param values: Variable args of the values of the parameter set, in order. :param values: Variable args of the values of the parameter set, in order.
:keyword marks: A single mark or a list of marks to be applied to this parameter set. :param marks: A single mark or a list of marks to be applied to this parameter set.
:keyword str id: The id to attribute to this parameter set. :param id: The id to attribute to this parameter set.
""" """
return ParameterSet.param(*values, marks=marks, id=id) return ParameterSet.param(*values, marks=marks, id=id)

View File

@ -126,12 +126,12 @@ class ParameterSet(NamedTuple):
@staticmethod @staticmethod
def _parse_parametrize_args( def _parse_parametrize_args(
argnames: Union[str, List[str], Tuple[str, ...]], argnames: Union[str, Sequence[str]],
argvalues: Iterable[Union["ParameterSet", Sequence[object], object]], argvalues: Iterable[Union["ParameterSet", Sequence[object], object]],
*args, *args,
**kwargs, **kwargs,
) -> Tuple[Union[List[str], Tuple[str, ...]], bool]: ) -> Tuple[Sequence[str], bool]:
if not isinstance(argnames, (tuple, list)): if isinstance(argnames, str):
argnames = [x.strip() for x in argnames.split(",") if x.strip()] argnames = [x.strip() for x in argnames.split(",") if x.strip()]
force_tuple = len(argnames) == 1 force_tuple = len(argnames) == 1
else: else:
@ -150,12 +150,12 @@ class ParameterSet(NamedTuple):
@classmethod @classmethod
def _for_parametrize( def _for_parametrize(
cls, cls,
argnames: Union[str, List[str], Tuple[str, ...]], argnames: Union[str, Sequence[str]],
argvalues: Iterable[Union["ParameterSet", Sequence[object], object]], argvalues: Iterable[Union["ParameterSet", Sequence[object], object]],
func, func,
config: Config, config: Config,
nodeid: str, nodeid: str,
) -> Tuple[Union[List[str], Tuple[str, ...]], List["ParameterSet"]]: ) -> Tuple[Sequence[str], List["ParameterSet"]]:
argnames, force_tuple = cls._parse_parametrize_args(argnames, argvalues) argnames, force_tuple = cls._parse_parametrize_args(argnames, argvalues)
parameters = cls._parse_parametrize_parameters(argvalues, force_tuple) parameters = cls._parse_parametrize_parameters(argvalues, force_tuple)
del argvalues del argvalues
@ -434,7 +434,7 @@ if TYPE_CHECKING:
class _ParametrizeMarkDecorator(MarkDecorator): class _ParametrizeMarkDecorator(MarkDecorator):
def __call__( # type: ignore[override] def __call__( # type: ignore[override]
self, self,
argnames: Union[str, List[str], Tuple[str, ...]], argnames: Union[str, Sequence[str]],
argvalues: Iterable[Union[ParameterSet, Sequence[object], object]], argvalues: Iterable[Union[ParameterSet, Sequence[object], object]],
*, *,
indirect: Union[bool, Sequence[str]] = ..., indirect: Union[bool, Sequence[str]] = ...,

View File

@ -29,21 +29,26 @@ V = TypeVar("V")
def monkeypatch() -> Generator["MonkeyPatch", None, None]: def monkeypatch() -> Generator["MonkeyPatch", None, None]:
"""A convenient fixture for monkey-patching. """A convenient fixture for monkey-patching.
The fixture provides these methods to modify objects, dictionaries or The fixture provides these methods to modify objects, dictionaries, or
os.environ:: :data:`os.environ`:
monkeypatch.setattr(obj, name, value, raising=True) * :meth:`monkeypatch.setattr(obj, name, value, raising=True) <pytest.MonkeyPatch.setattr>`
monkeypatch.delattr(obj, name, raising=True) * :meth:`monkeypatch.delattr(obj, name, raising=True) <pytest.MonkeyPatch.delattr>`
monkeypatch.setitem(mapping, name, value) * :meth:`monkeypatch.setitem(mapping, name, value) <pytest.MonkeyPatch.setitem>`
monkeypatch.delitem(obj, name, raising=True) * :meth:`monkeypatch.delitem(obj, name, raising=True) <pytest.MonkeyPatch.delitem>`
monkeypatch.setenv(name, value, prepend=None) * :meth:`monkeypatch.setenv(name, value, prepend=None) <pytest.MonkeyPatch.setenv>`
monkeypatch.delenv(name, raising=True) * :meth:`monkeypatch.delenv(name, raising=True) <pytest.MonkeyPatch.delenv>`
monkeypatch.syspath_prepend(path) * :meth:`monkeypatch.syspath_prepend(path) <pytest.MonkeyPatch.syspath_prepend>`
monkeypatch.chdir(path) * :meth:`monkeypatch.chdir(path) <pytest.MonkeyPatch.chdir>`
* :meth:`monkeypatch.context() <pytest.MonkeyPatch.context>`
All modifications will be undone after the requesting test function or All modifications will be undone after the requesting test function or
fixture has finished. The ``raising`` parameter determines if a KeyError fixture has finished. The ``raising`` parameter determines if a :class:`KeyError`
or AttributeError will be raised if the set/deletion operation has no target. or :class:`AttributeError` will be raised if the set/deletion operation does not have the
specified target.
To undo modifications done by the fixture in a contained scope,
use :meth:`context() <pytest.MonkeyPatch.context>`.
""" """
mpatch = MonkeyPatch() mpatch = MonkeyPatch()
yield mpatch yield mpatch
@ -115,7 +120,7 @@ class MonkeyPatch:
Returned by the :fixture:`monkeypatch` fixture. Returned by the :fixture:`monkeypatch` fixture.
:versionchanged:: 6.2 .. versionchanged:: 6.2
Can now also be used directly as `pytest.MonkeyPatch()`, for when Can now also be used directly as `pytest.MonkeyPatch()`, for when
the fixture is not available. In this case, use the fixture is not available. In this case, use
:meth:`with MonkeyPatch.context() as mp: <context>` or remember to call :meth:`with MonkeyPatch.context() as mp: <context>` or remember to call
@ -182,16 +187,40 @@ class MonkeyPatch:
value: object = notset, value: object = notset,
raising: bool = True, raising: bool = True,
) -> None: ) -> None:
"""Set attribute value on target, memorizing the old value. """
Set attribute value on target, memorizing the old value.
For convenience you can specify a string as ``target`` which For example:
.. code-block:: python
import os
monkeypatch.setattr(os, "getcwd", lambda: "/")
The code above replaces the :func:`os.getcwd` function by a ``lambda`` which
always returns ``"/"``.
For convenience, you can specify a string as ``target`` which
will be interpreted as a dotted import path, with the last part will be interpreted as a dotted import path, with the last part
being the attribute name. For example, being the attribute name:
``monkeypatch.setattr("os.getcwd", lambda: "/")``
would set the ``getcwd`` function of the ``os`` module.
Raises AttributeError if the attribute does not exist, unless .. code-block:: python
monkeypatch.setattr("os.getcwd", lambda: "/")
Raises :class:`AttributeError` if the attribute does not exist, unless
``raising`` is set to False. ``raising`` is set to False.
**Where to patch**
``monkeypatch.setattr`` works by (temporarily) changing the object that a name points to with another one.
There can be many names pointing to any individual object, so for patching to work you must ensure
that you patch the name used by the system under test.
See the section :ref:`Where to patch <python:where-to-patch>` in the :mod:`unittest.mock`
docs for a complete explanation, which is meant for :func:`unittest.mock.patch` but
applies to ``monkeypatch.setattr`` as well.
""" """
__tracebackhide__ = True __tracebackhide__ = True
import inspect import inspect
@ -338,7 +367,8 @@ class MonkeyPatch:
def chdir(self, path: Union[str, "os.PathLike[str]"]) -> None: def chdir(self, path: Union[str, "os.PathLike[str]"]) -> None:
"""Change the current working directory to the specified path. """Change the current working directory to the specified path.
Path can be a string or a path object. :param path:
The path to change into.
""" """
if self._cwd is None: if self._cwd is None:
self._cwd = os.getcwd() self._cwd = os.getcwd()
@ -353,11 +383,14 @@ class MonkeyPatch:
There is generally no need to call `undo()`, since it is There is generally no need to call `undo()`, since it is
called automatically during tear-down. called automatically during tear-down.
Note that the same `monkeypatch` fixture is used across a .. note::
single test function invocation. If `monkeypatch` is used both by The same `monkeypatch` fixture is used across a
the test function itself and one of the test fixtures, single test function invocation. If `monkeypatch` is used both by
calling `undo()` will undo all of the changes made in the test function itself and one of the test fixtures,
both functions. calling `undo()` will undo all of the changes made in
both functions.
Prefer to use :meth:`context() <pytest.MonkeyPatch.context>` instead.
""" """
for obj, name, value in reversed(self._setattr): for obj, name, value in reversed(self._setattr):
if value is not notset: if value is not notset:

View File

@ -193,7 +193,7 @@ class Node(metaclass=NodeMeta):
nodeid: Optional[str] = None, nodeid: Optional[str] = None,
) -> None: ) -> None:
#: A unique name within the scope of the parent node. #: A unique name within the scope of the parent node.
self.name = name self.name: str = name
#: The parent collector node. #: The parent collector node.
self.parent = parent self.parent = parent
@ -208,7 +208,7 @@ class Node(metaclass=NodeMeta):
if session: if session:
#: The pytest session this node is part of. #: The pytest session this node is part of.
self.session = session self.session: Session = session
else: else:
if not parent: if not parent:
raise TypeError("session or parent must be provided") raise TypeError("session or parent must be provided")
@ -239,9 +239,7 @@ class Node(metaclass=NodeMeta):
#: A place where plugins can store information on the node for their #: A place where plugins can store information on the node for their
#: own use. #: own use.
#: self.stash: Stash = Stash()
#: :type: Stash
self.stash = Stash()
# Deprecated alias. Was never public. Can be removed in a few releases. # Deprecated alias. Was never public. Can be removed in a few releases.
self._store = self.stash self._store = self.stash
@ -326,7 +324,10 @@ class Node(metaclass=NodeMeta):
def listchain(self) -> List["Node"]: def listchain(self) -> List["Node"]:
"""Return list of all parent collectors up to self, starting from """Return list of all parent collectors up to self, starting from
the root of collection tree.""" the root of collection tree.
:returns: The nodes.
"""
chain = [] chain = []
item: Optional[Node] = self item: Optional[Node] = self
while item is not None: while item is not None:
@ -340,6 +341,8 @@ class Node(metaclass=NodeMeta):
) -> None: ) -> None:
"""Dynamically add a marker object to the node. """Dynamically add a marker object to the node.
:param marker:
The marker.
:param append: :param append:
Whether to append the marker, or prepend it. Whether to append the marker, or prepend it.
""" """
@ -361,6 +364,7 @@ class Node(metaclass=NodeMeta):
"""Iterate over all markers of the node. """Iterate over all markers of the node.
:param name: If given, filter the results by the name attribute. :param name: If given, filter the results by the name attribute.
:returns: An iterator of the markers of the node.
""" """
return (x[1] for x in self.iter_markers_with_node(name=name)) return (x[1] for x in self.iter_markers_with_node(name=name))
@ -407,7 +411,8 @@ class Node(metaclass=NodeMeta):
return [x.name for x in self.listchain()] return [x.name for x in self.listchain()]
def addfinalizer(self, fin: Callable[[], object]) -> None: def addfinalizer(self, fin: Callable[[], object]) -> None:
"""Register a function to be called when this node is finalized. """Register a function to be called without arguments when this node is
finalized.
This method can only be called when this node is active This method can only be called when this node is active
in a setup chain, for example during self.setup(). in a setup chain, for example during self.setup().
@ -416,7 +421,11 @@ class Node(metaclass=NodeMeta):
def getparent(self, cls: Type[_NodeType]) -> Optional[_NodeType]: def getparent(self, cls: Type[_NodeType]) -> Optional[_NodeType]:
"""Get the next parent node (including self) which is an instance of """Get the next parent node (including self) which is an instance of
the given class.""" the given class.
:param cls: The node class to search for.
:returns: The node, if found.
"""
current: Optional[Node] = self current: Optional[Node] = self
while current and not isinstance(current, cls): while current and not isinstance(current, cls):
current = current.parent current = current.parent

View File

@ -241,6 +241,9 @@ def xfail(reason: str = "") -> NoReturn:
This function should be called only during testing (setup, call or teardown). This function should be called only during testing (setup, call or teardown).
:param reason:
The message to show the user as reason for the xfail.
.. note:: .. note::
It is better to use the :ref:`pytest.mark.xfail ref` marker when It is better to use the :ref:`pytest.mark.xfail ref` marker when
possible to declare a test to be xfailed under certain conditions possible to declare a test to be xfailed under certain conditions
@ -256,12 +259,12 @@ def importorskip(
"""Import and return the requested module ``modname``, or skip the """Import and return the requested module ``modname``, or skip the
current test if the module cannot be imported. current test if the module cannot be imported.
:param str modname: :param modname:
The name of the module to import. The name of the module to import.
:param str minversion: :param minversion:
If given, the imported module's ``__version__`` attribute must be at If given, the imported module's ``__version__`` attribute must be at
least this minimal version, otherwise the test is still skipped. least this minimal version, otherwise the test is still skipped.
:param str reason: :param reason:
If given, this reason is shown as the message when the module cannot If given, this reason is shown as the message when the module cannot
be imported. be imported.

View File

@ -661,17 +661,7 @@ class Pytester:
against expected output, perfect for black-box testing of pytest plugins. against expected output, perfect for black-box testing of pytest plugins.
It attempts to isolate the test run from external factors as much as possible, modifying It attempts to isolate the test run from external factors as much as possible, modifying
the current working directory to ``path`` and environment variables during initialization. the current working directory to :attr:`path` and environment variables during initialization.
Attributes:
:ivar Path path: temporary directory path used to create files/run tests from, etc.
:ivar plugins:
A list of plugins to use with :py:meth:`parseconfig` and
:py:meth:`runpytest`. Initially this is an empty list but plugins can
be added to the list. The type of items to add to the list depends on
the method using them so refer to them for details.
""" """
__test__ = False __test__ = False
@ -700,6 +690,10 @@ class Pytester:
name = request.node.name name = request.node.name
self._name = name self._name = name
self._path: Path = tmp_path_factory.mktemp(name, numbered=True) self._path: Path = tmp_path_factory.mktemp(name, numbered=True)
#: A list of plugins to use with :py:meth:`parseconfig` and
#: :py:meth:`runpytest`. Initially this is an empty list but plugins can
#: be added to the list. The type of items to add to the list depends on
#: the method using them so refer to them for details.
self.plugins: List[Union[str, _PluggyPlugin]] = [] self.plugins: List[Union[str, _PluggyPlugin]] = []
self._cwd_snapshot = CwdSnapshot() self._cwd_snapshot = CwdSnapshot()
self._sys_path_snapshot = SysPathsSnapshot() self._sys_path_snapshot = SysPathsSnapshot()
@ -724,7 +718,7 @@ class Pytester:
@property @property
def path(self) -> Path: def path(self) -> Path:
"""Temporary directory where files are created and pytest is executed.""" """Temporary directory path used to create files/run tests from, etc."""
return self._path return self._path
def __repr__(self) -> str: def __repr__(self) -> str:
@ -755,7 +749,7 @@ class Pytester:
return SysModulesSnapshot(preserve=preserve_module) return SysModulesSnapshot(preserve=preserve_module)
def make_hook_recorder(self, pluginmanager: PytestPluginManager) -> HookRecorder: def make_hook_recorder(self, pluginmanager: PytestPluginManager) -> HookRecorder:
"""Create a new :py:class:`HookRecorder` for a PluginManager.""" """Create a new :class:`HookRecorder` for a :class:`PytestPluginManager`."""
pluginmanager.reprec = reprec = HookRecorder(pluginmanager, _ispytest=True) pluginmanager.reprec = reprec = HookRecorder(pluginmanager, _ispytest=True)
self._request.addfinalizer(reprec.finish_recording) self._request.addfinalizer(reprec.finish_recording)
return reprec return reprec
@ -804,7 +798,7 @@ class Pytester:
def makefile(self, ext: str, *args: str, **kwargs: str) -> Path: def makefile(self, ext: str, *args: str, **kwargs: str) -> Path:
r"""Create new text file(s) in the test directory. r"""Create new text file(s) in the test directory.
:param str ext: :param ext:
The extension the file(s) should use, including the dot, e.g. `.py`. The extension the file(s) should use, including the dot, e.g. `.py`.
:param args: :param args:
All args are treated as strings and joined using newlines. All args are treated as strings and joined using newlines.
@ -813,6 +807,8 @@ class Pytester:
:param kwargs: :param kwargs:
Each keyword is the name of a file, while the value of it will Each keyword is the name of a file, while the value of it will
be written as contents of the file. be written as contents of the file.
:returns:
The first created file.
Examples: Examples:
@ -832,11 +828,19 @@ class Pytester:
return self._makefile(ext, args, kwargs) return self._makefile(ext, args, kwargs)
def makeconftest(self, source: str) -> Path: def makeconftest(self, source: str) -> Path:
"""Write a conftest.py file with 'source' as contents.""" """Write a contest.py file.
:param source: The contents.
:returns: The conftest.py file.
"""
return self.makepyfile(conftest=source) return self.makepyfile(conftest=source)
def makeini(self, source: str) -> Path: def makeini(self, source: str) -> Path:
"""Write a tox.ini file with 'source' as contents.""" """Write a tox.ini file.
:param source: The contents.
:returns: The tox.ini file.
"""
return self.makefile(".ini", tox=source) return self.makefile(".ini", tox=source)
def getinicfg(self, source: str) -> SectionWrapper: def getinicfg(self, source: str) -> SectionWrapper:
@ -845,7 +849,10 @@ class Pytester:
return IniConfig(str(p))["pytest"] return IniConfig(str(p))["pytest"]
def makepyprojecttoml(self, source: str) -> Path: def makepyprojecttoml(self, source: str) -> Path:
"""Write a pyproject.toml file with 'source' as contents. """Write a pyproject.toml file.
:param source: The contents.
:returns: The pyproject.ini file.
.. versionadded:: 6.0 .. versionadded:: 6.0
""" """
@ -898,6 +905,9 @@ class Pytester:
This is undone automatically when this object dies at the end of each This is undone automatically when this object dies at the end of each
test. test.
:param path:
The path.
""" """
if path is None: if path is None:
path = self.path path = self.path
@ -905,7 +915,13 @@ class Pytester:
self._monkeypatch.syspath_prepend(str(path)) self._monkeypatch.syspath_prepend(str(path))
def mkdir(self, name: Union[str, "os.PathLike[str]"]) -> Path: def mkdir(self, name: Union[str, "os.PathLike[str]"]) -> Path:
"""Create a new (sub)directory.""" """Create a new (sub)directory.
:param name:
The name of the directory, relative to the pytester path.
:returns:
The created directory.
"""
p = self.path / name p = self.path / name
p.mkdir() p.mkdir()
return p return p
@ -924,14 +940,15 @@ class Pytester:
def copy_example(self, name: Optional[str] = None) -> Path: def copy_example(self, name: Optional[str] = None) -> Path:
"""Copy file from project's directory into the testdir. """Copy file from project's directory into the testdir.
:param str name: The name of the file to copy. :param name:
:return: path to the copied directory (inside ``self.path``). The name of the file to copy.
:return:
Path to the copied directory (inside ``self.path``).
""" """
example_dir = self._request.config.getini("pytester_example_dir") example_dir_ = self._request.config.getini("pytester_example_dir")
if example_dir is None: if example_dir_ is None:
raise ValueError("pytester_example_dir is unset, can't copy examples") raise ValueError("pytester_example_dir is unset, can't copy examples")
example_dir = self._request.config.rootpath / example_dir example_dir: Path = self._request.config.rootpath / example_dir_
for extra_element in self._request.node.iter_markers("pytester_example_path"): for extra_element in self._request.node.iter_markers("pytester_example_path"):
assert extra_element.args assert extra_element.args
@ -967,14 +984,16 @@ class Pytester:
def getnode( def getnode(
self, config: Config, arg: Union[str, "os.PathLike[str]"] self, config: Config, arg: Union[str, "os.PathLike[str]"]
) -> Optional[Union[Collector, Item]]: ) -> Union[Collector, Item]:
"""Return the collection node of a file. """Get the collection node of a file.
:param pytest.Config config: :param config:
A pytest config. A pytest config.
See :py:meth:`parseconfig` and :py:meth:`parseconfigure` for creating it. See :py:meth:`parseconfig` and :py:meth:`parseconfigure` for creating it.
:param os.PathLike[str] arg: :param arg:
Path to the file. Path to the file.
:returns:
The node.
""" """
session = Session.from_config(config) session = Session.from_config(config)
assert "::" not in str(arg) assert "::" not in str(arg)
@ -984,13 +1003,18 @@ class Pytester:
config.hook.pytest_sessionfinish(session=session, exitstatus=ExitCode.OK) config.hook.pytest_sessionfinish(session=session, exitstatus=ExitCode.OK)
return res return res
def getpathnode(self, path: Union[str, "os.PathLike[str]"]): def getpathnode(
self, path: Union[str, "os.PathLike[str]"]
) -> Union[Collector, Item]:
"""Return the collection node of a file. """Return the collection node of a file.
This is like :py:meth:`getnode` but uses :py:meth:`parseconfigure` to This is like :py:meth:`getnode` but uses :py:meth:`parseconfigure` to
create the (configured) pytest Config instance. create the (configured) pytest Config instance.
:param os.PathLike[str] path: Path to the file. :param path:
Path to the file.
:returns:
The node.
""" """
path = Path(path) path = Path(path)
config = self.parseconfigure(path) config = self.parseconfigure(path)
@ -1006,6 +1030,11 @@ class Pytester:
This recurses into the collection node and returns a list of all the This recurses into the collection node and returns a list of all the
test items contained within. test items contained within.
:param colitems:
The collection nodes.
:returns:
The collected items.
""" """
session = colitems[0].session session = colitems[0].session
result: List[Item] = [] result: List[Item] = []
@ -1192,15 +1221,16 @@ class Pytester:
return new_args return new_args
def parseconfig(self, *args: Union[str, "os.PathLike[str]"]) -> Config: def parseconfig(self, *args: Union[str, "os.PathLike[str]"]) -> Config:
"""Return a new pytest Config instance from given commandline args. """Return a new pytest :class:`pytest.Config` instance from given
commandline args.
This invokes the pytest bootstrapping code in _pytest.config to create This invokes the pytest bootstrapping code in _pytest.config to create a
a new :py:class:`_pytest.core.PluginManager` and call the new :py:class:`pytest.PytestPluginManager` and call the
pytest_cmdline_parse hook to create a new :hook:`pytest_cmdline_parse` hook to create a new :class:`pytest.Config`
:py:class:`pytest.Config` instance. instance.
If :py:attr:`plugins` has been populated they should be plugin modules If :attr:`plugins` has been populated they should be plugin modules
to be registered with the PluginManager. to be registered with the plugin manager.
""" """
import _pytest.config import _pytest.config
@ -1218,7 +1248,8 @@ class Pytester:
"""Return a new pytest configured Config instance. """Return a new pytest configured Config instance.
Returns a new :py:class:`pytest.Config` instance like Returns a new :py:class:`pytest.Config` instance like
:py:meth:`parseconfig`, but also calls the pytest_configure hook. :py:meth:`parseconfig`, but also calls the :hook:`pytest_configure`
hook.
""" """
config = self.parseconfig(*args) config = self.parseconfig(*args)
config._do_configure() config._do_configure()
@ -1237,6 +1268,8 @@ class Pytester:
The module source. The module source.
:param funcname: :param funcname:
The name of the test function for which to return a test item. The name of the test function for which to return a test item.
:returns:
The test item.
""" """
items = self.getitems(source) items = self.getitems(source)
for item in items: for item in items:
@ -1377,6 +1410,8 @@ class Pytester:
- Otherwise, it is passed through to :py:class:`subprocess.Popen`. - Otherwise, it is passed through to :py:class:`subprocess.Popen`.
For further information in this case, consult the document of the For further information in this case, consult the document of the
``stdin`` parameter in :py:class:`subprocess.Popen`. ``stdin`` parameter in :py:class:`subprocess.Popen`.
:returns:
The result.
""" """
__tracebackhide__ = True __tracebackhide__ = True
@ -1463,6 +1498,8 @@ class Pytester:
:param timeout: :param timeout:
The period in seconds after which to timeout and raise The period in seconds after which to timeout and raise
:py:class:`Pytester.TimeoutExpired`. :py:class:`Pytester.TimeoutExpired`.
:returns:
The result.
""" """
__tracebackhide__ = True __tracebackhide__ = True
p = make_numbered_dir(root=self.path, prefix="runpytest-", mode=0o700) p = make_numbered_dir(root=self.path, prefix="runpytest-", mode=0o700)

View File

@ -1207,7 +1207,7 @@ class Metafunc:
def parametrize( def parametrize(
self, self,
argnames: Union[str, List[str], Tuple[str, ...]], argnames: Union[str, Sequence[str]],
argvalues: Iterable[Union[ParameterSet, Sequence[object], object]], argvalues: Iterable[Union[ParameterSet, Sequence[object], object]],
indirect: Union[bool, Sequence[str]] = False, indirect: Union[bool, Sequence[str]] = False,
ids: Optional[ ids: Optional[

View File

@ -12,7 +12,6 @@ from typing import Generic
from typing import List from typing import List
from typing import Mapping from typing import Mapping
from typing import Optional from typing import Optional
from typing import overload
from typing import Pattern from typing import Pattern
from typing import Sequence from typing import Sequence
from typing import Tuple from typing import Tuple
@ -28,6 +27,7 @@ if TYPE_CHECKING:
import _pytest._code import _pytest._code
from _pytest.compat import final from _pytest.compat import final
from _pytest.compat import STRING_TYPES from _pytest.compat import STRING_TYPES
from _pytest.compat import overload
from _pytest.outcomes import fail from _pytest.outcomes import fail
@ -521,7 +521,7 @@ def approx(expected, rel=None, abs=None, nan_ok: bool = False) -> ApproxBase:
"""Assert that two numbers (or two ordered sequences of numbers) are equal to each other """Assert that two numbers (or two ordered sequences of numbers) are equal to each other
within some tolerance. within some tolerance.
Due to the :std:doc:`tutorial/floatingpoint`, numbers that we Due to the :doc:`python:tutorial/floatingpoint`, numbers that we
would intuitively expect to be equal are not always so:: would intuitively expect to be equal are not always so::
>>> 0.1 + 0.2 == 0.3 >>> 0.1 + 0.2 == 0.3
@ -786,7 +786,7 @@ def raises(
@overload @overload
def raises( def raises( # noqa: F811
expected_exception: Union[Type[E], Tuple[Type[E], ...]], expected_exception: Union[Type[E], Tuple[Type[E], ...]],
func: Callable[..., Any], func: Callable[..., Any],
*args: Any, *args: Any,
@ -795,18 +795,21 @@ def raises(
... ...
def raises( def raises( # noqa: F811
expected_exception: Union[Type[E], Tuple[Type[E], ...]], *args: Any, **kwargs: Any expected_exception: Union[Type[E], Tuple[Type[E], ...]], *args: Any, **kwargs: Any
) -> Union["RaisesContext[E]", _pytest._code.ExceptionInfo[E]]: ) -> Union["RaisesContext[E]", _pytest._code.ExceptionInfo[E]]:
r"""Assert that a code block/function call raises ``expected_exception`` r"""Assert that a code block/function call raises an exception.
or raise a failure exception otherwise.
:kwparam match: :param typing.Type[E] | typing.Tuple[typing.Type[E], ...] expected_exception:
The excpected exception type, or a tuple if one of multiple possible
exception types are excepted.
:kwparam str | typing.Pattern[str] | None match:
If specified, a string containing a regular expression, If specified, a string containing a regular expression,
or a regular expression object, that is tested against the string or a regular expression object, that is tested against the string
representation of the exception using :py:func:`re.search`. To match a literal representation of the exception using :func:`re.search`.
string that may contain :std:ref:`special characters <re-syntax>`, the pattern can
first be escaped with :py:func:`re.escape`. To match a literal string that may contain :ref:`special characters
<re-syntax>`, the pattern can first be escaped with :func:`re.escape`.
(This is only used when :py:func:`pytest.raises` is used as a context manager, (This is only used when :py:func:`pytest.raises` is used as a context manager,
and passed through to the function otherwise. and passed through to the function otherwise.

View File

@ -9,7 +9,6 @@ from typing import Generator
from typing import Iterator from typing import Iterator
from typing import List from typing import List
from typing import Optional from typing import Optional
from typing import overload
from typing import Pattern from typing import Pattern
from typing import Tuple from typing import Tuple
from typing import Type from typing import Type
@ -17,6 +16,7 @@ from typing import TypeVar
from typing import Union from typing import Union
from _pytest.compat import final from _pytest.compat import final
from _pytest.compat import overload
from _pytest.deprecated import check_ispytest from _pytest.deprecated import check_ispytest
from _pytest.deprecated import WARNS_NONE_ARG from _pytest.deprecated import WARNS_NONE_ARG
from _pytest.fixtures import fixture from _pytest.fixtures import fixture
@ -47,11 +47,13 @@ def deprecated_call(
@overload @overload
def deprecated_call(func: Callable[..., T], *args: Any, **kwargs: Any) -> T: def deprecated_call( # noqa: F811
func: Callable[..., T], *args: Any, **kwargs: Any
) -> T:
... ...
def deprecated_call( def deprecated_call( # noqa: F811
func: Optional[Callable[..., Any]] = None, *args: Any, **kwargs: Any func: Optional[Callable[..., Any]] = None, *args: Any, **kwargs: Any
) -> Union["WarningsRecorder", Any]: ) -> Union["WarningsRecorder", Any]:
"""Assert that code produces a ``DeprecationWarning`` or ``PendingDeprecationWarning``. """Assert that code produces a ``DeprecationWarning`` or ``PendingDeprecationWarning``.
@ -93,7 +95,7 @@ def warns(
@overload @overload
def warns( def warns( # noqa: F811
expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]], expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]],
func: Callable[..., T], func: Callable[..., T],
*args: Any, *args: Any,
@ -102,7 +104,7 @@ def warns(
... ...
def warns( def warns( # noqa: F811
expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]] = Warning, expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]] = Warning,
*args: Any, *args: Any,
match: Optional[Union[str, Pattern[str]]] = None, match: Optional[Union[str, Pattern[str]]] = None,
@ -110,15 +112,15 @@ def warns(
) -> Union["WarningsChecker", Any]: ) -> Union["WarningsChecker", Any]:
r"""Assert that code raises a particular class of warning. r"""Assert that code raises a particular class of warning.
Specifically, the parameter ``expected_warning`` can be a warning class or Specifically, the parameter ``expected_warning`` can be a warning class or sequence
sequence of warning classes, and the code inside the ``with`` block must issue a warning of that class or of warning classes, and the code inside the ``with`` block must issue at least one
classes. warning of that class or classes.
This helper produces a list of :class:`warnings.WarningMessage` objects, This helper produces a list of :class:`warnings.WarningMessage` objects, one for
one for each warning raised. each warning raised (regardless of whether it is an ``expected_warning`` or not).
This function can be used as a context manager, or any of the other ways This function can be used as a context manager, which will capture all the raised
:func:`pytest.raises` can be used:: warnings inside it::
>>> import pytest >>> import pytest
>>> with pytest.warns(RuntimeWarning): >>> with pytest.warns(RuntimeWarning):
@ -139,6 +141,14 @@ def warns(
... ...
Failed: DID NOT WARN. No warnings of type ...UserWarning... were emitted... Failed: DID NOT WARN. No warnings of type ...UserWarning... were emitted...
**Using with** ``pytest.mark.parametrize``
When using :ref:`pytest.mark.parametrize ref` it is possible to parametrize tests
such that some runs raise a warning and others do not.
This could be achieved in the same way as with exceptions, see
:ref:`parametrizing_conditional_raising` for an example.
""" """
__tracebackhide__ = True __tracebackhide__ = True
if not args: if not args:

View File

@ -276,7 +276,7 @@ class TestReport(BaseReport):
#: A name -> value dictionary containing all keywords and #: A name -> value dictionary containing all keywords and
#: markers associated with a test invocation. #: markers associated with a test invocation.
self.keywords = keywords self.keywords: Mapping[str, Any] = keywords
#: Test outcome, always one of "passed", "failed", "skipped". #: Test outcome, always one of "passed", "failed", "skipped".
self.outcome = outcome self.outcome = outcome
@ -298,7 +298,7 @@ class TestReport(BaseReport):
self.sections = list(sections) self.sections = list(sections)
#: Time it took to run just the test. #: Time it took to run just the test.
self.duration = duration self.duration: float = duration
self.__dict__.update(extra) self.__dict__.update(extra)
@ -309,7 +309,11 @@ class TestReport(BaseReport):
@classmethod @classmethod
def from_item_and_call(cls, item: Item, call: "CallInfo[None]") -> "TestReport": def from_item_and_call(cls, item: Item, call: "CallInfo[None]") -> "TestReport":
"""Create and fill a TestReport with standard item and call info.""" """Create and fill a TestReport with standard item and call info.
:param item: The item.
:param call: The call info.
"""
when = call.when when = call.when
# Remove "collect" from the Literal type -- only for collection calls. # Remove "collect" from the Literal type -- only for collection calls.
assert when != "collect" assert when != "collect"

View File

@ -100,7 +100,11 @@ class TempPathFactory:
return p return p
def getbasetemp(self) -> Path: def getbasetemp(self) -> Path:
"""Return the base temporary directory, creating it if needed.""" """Return the base temporary directory, creating it if needed.
:returns:
The base temporary directory.
"""
if self._basetemp is not None: if self._basetemp is not None:
return self._basetemp return self._basetemp

View File

@ -1470,3 +1470,90 @@ def test_no_recursion_index_on_recursion_error():
with pytest.raises(RuntimeError) as excinfo: with pytest.raises(RuntimeError) as excinfo:
RecursionDepthError().trigger RecursionDepthError().trigger
assert "maximum recursion" in str(excinfo.getrepr()) assert "maximum recursion" in str(excinfo.getrepr())
def _exceptiongroup_common(
pytester: Pytester,
outer_chain: str,
inner_chain: str,
native: bool,
) -> None:
pre_raise = "exceptiongroup." if not native else ""
pre_catch = pre_raise if sys.version_info < (3, 11) else ""
filestr = f"""
{"import exceptiongroup" if not native else ""}
import pytest
def f(): raise ValueError("From f()")
def g(): raise BaseException("From g()")
def inner(inner_chain):
excs = []
for callback in [f, g]:
try:
callback()
except BaseException as err:
excs.append(err)
if excs:
if inner_chain == "none":
raise {pre_raise}BaseExceptionGroup("Oops", excs)
try:
raise SyntaxError()
except SyntaxError as e:
if inner_chain == "from":
raise {pre_raise}BaseExceptionGroup("Oops", excs) from e
else:
raise {pre_raise}BaseExceptionGroup("Oops", excs)
def outer(outer_chain, inner_chain):
try:
inner(inner_chain)
except {pre_catch}BaseExceptionGroup as e:
if outer_chain == "none":
raise
if outer_chain == "from":
raise IndexError() from e
else:
raise IndexError()
def test():
outer("{outer_chain}", "{inner_chain}")
"""
pytester.makepyfile(test_excgroup=filestr)
result = pytester.runpytest()
match_lines = []
if inner_chain in ("another", "from"):
match_lines.append(r"SyntaxError: <no detail available>")
match_lines += [
r" + Exception Group Traceback (most recent call last):",
rf" \| {pre_catch}BaseExceptionGroup: Oops \(2 sub-exceptions\)",
r" \| ValueError: From f\(\)",
r" \| BaseException: From g\(\)",
r"=* short test summary info =*",
]
if outer_chain in ("another", "from"):
match_lines.append(r"FAILED test_excgroup.py::test - IndexError")
else:
match_lines.append(
rf"FAILED test_excgroup.py::test - {pre_catch}BaseExceptionGroup: Oops \(2.*"
)
result.stdout.re_match_lines(match_lines)
@pytest.mark.skipif(
sys.version_info < (3, 11), reason="Native ExceptionGroup not implemented"
)
@pytest.mark.parametrize("outer_chain", ["none", "from", "another"])
@pytest.mark.parametrize("inner_chain", ["none", "from", "another"])
def test_native_exceptiongroup(pytester: Pytester, outer_chain, inner_chain) -> None:
_exceptiongroup_common(pytester, outer_chain, inner_chain, native=True)
@pytest.mark.parametrize("outer_chain", ["none", "from", "another"])
@pytest.mark.parametrize("inner_chain", ["none", "from", "another"])
def test_exceptiongroup(pytester: Pytester, outer_chain, inner_chain) -> None:
# with py>=3.11 does not depend on exceptiongroup, though there is a toxenv for it
pytest.importorskip("exceptiongroup")
_exceptiongroup_common(pytester, outer_chain, inner_chain, native=False)

View File

@ -1,6 +1,6 @@
anyio[curio,trio]==3.6.1 anyio[curio,trio]==3.6.1
django==4.0.6 django==4.1
pytest-asyncio==0.18.3 pytest-asyncio==0.19.0
pytest-bdd==6.0.1 pytest-bdd==6.0.1
pytest-cov==3.0.0 pytest-cov==3.0.0
pytest-django==4.5.2 pytest-django==4.5.2

View File

@ -1625,6 +1625,28 @@ def test_escaped_skipreason_issue3533(
snode.assert_attr(message="1 <> 2") snode.assert_attr(message="1 <> 2")
def test_escaped_setup_teardown_error(
pytester: Pytester, run_and_parse: RunAndParse
) -> None:
pytester.makepyfile(
"""
import pytest
@pytest.fixture()
def my_setup():
raise Exception("error: \033[31mred\033[m")
def test_esc(my_setup):
pass
"""
)
_, dom = run_and_parse()
node = dom.find_first_by_tag("testcase")
snode = node.find_first_by_tag("error")
assert "#x1B[31mred#x1B[m" in snode["message"]
assert "#x1B[31mred#x1B[m" in snode.text
@parametrize_families @parametrize_families
def test_logging_passing_tests_disabled_does_not_log_test_output( def test_logging_passing_tests_disabled_does_not_log_test_output(
pytester: Pytester, run_and_parse: RunAndParse, xunit_family: str pytester: Pytester, run_and_parse: RunAndParse, xunit_family: str

View File

@ -17,6 +17,10 @@ envlist =
docs docs
docs-checklinks docs-checklinks
# checks that 3.11 native ExceptionGroup works with exceptiongroup
# not included in CI.
py311-exceptiongroup
[testenv] [testenv]
@ -46,6 +50,7 @@ setenv =
extras = testing extras = testing
deps = deps =
doctesting: PyYAML doctesting: PyYAML
exceptiongroup: exceptiongroup>=1.0.0rc8
numpy: numpy>=1.19.4 numpy: numpy>=1.19.4
pexpect: pexpect>=4.8.0 pexpect: pexpect>=4.8.0
pluggymain: pluggy @ git+https://github.com/pytest-dev/pluggy.git pluggymain: pluggy @ git+https://github.com/pytest-dev/pluggy.git