Merge branch 'main' into patch-1
This commit is contained in:
commit
b3c1377693
|
@ -114,6 +114,7 @@ jobs:
|
|||
python: "3.11-dev"
|
||||
os: ubuntu-latest
|
||||
tox_env: "py311"
|
||||
use_coverage: true
|
||||
- name: "ubuntu-pypy3"
|
||||
python: "pypy-3.7"
|
||||
os: ubuntu-latest
|
||||
|
|
|
@ -68,6 +68,9 @@ repos:
|
|||
- packaging
|
||||
- tomli
|
||||
- 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
|
||||
hooks:
|
||||
- id: rst
|
||||
|
|
2
AUTHORS
2
AUTHORS
|
@ -168,6 +168,7 @@ Jeff Rackauckas
|
|||
Jeff Widman
|
||||
Jenni Rinker
|
||||
John Eddie Ayson
|
||||
John Litborn
|
||||
John Towler
|
||||
Jon Parise
|
||||
Jon Sonesen
|
||||
|
@ -313,6 +314,7 @@ Seth Junot
|
|||
Shantanu Jain
|
||||
Shubham Adep
|
||||
Simon Gomizelj
|
||||
Simon Holesch
|
||||
Simon Kerr
|
||||
Skylar Downes
|
||||
Srinivas Reddy Thatiparthy
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Invalid XML characters in setup or teardown error messages are now properly escaped for JUnit XML reports.
|
|
@ -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).
|
|
@ -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``.
|
|
@ -0,0 +1 @@
|
|||
The documentation is now built using Sphinx 5.x (up from 3.x previously).
|
|
@ -0,0 +1 @@
|
|||
Update documentation on how :func:`pytest.warns` affects :class:`DeprecationWarning`.
|
|
@ -38,6 +38,7 @@ release = ".".join(version.split(".")[:2])
|
|||
|
||||
autodoc_member_order = "bysource"
|
||||
autodoc_typehints = "description"
|
||||
autodoc_typehints_description_target = "documented"
|
||||
todo_include_todos = 1
|
||||
|
||||
latex_engine = "lualatex"
|
||||
|
@ -162,11 +163,11 @@ linkcheck_workers = 5
|
|||
|
||||
_repo = "https://github.com/pytest-dev/pytest"
|
||||
extlinks = {
|
||||
"bpo": ("https://bugs.python.org/issue%s", "bpo-"),
|
||||
"pypi": ("https://pypi.org/project/%s/", ""),
|
||||
"issue": (f"{_repo}/issues/%s", "issue #"),
|
||||
"pull": (f"{_repo}/pull/%s", "pull request #"),
|
||||
"user": ("https://github.com/%s", "@"),
|
||||
"bpo": ("https://bugs.python.org/issue%s", "bpo-%s"),
|
||||
"pypi": ("https://pypi.org/project/%s/", "%s"),
|
||||
"issue": (f"{_repo}/issues/%s", "issue #%s"),
|
||||
"pull": (f"{_repo}/pull/%s", "pull request #%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:
|
||||
# from sphinx.ext.autodoc import cut_lines
|
||||
# app.connect('autodoc-process-docstring', cut_lines(4, what=['module']))
|
||||
app.add_crossref_type(
|
||||
"fixture",
|
||||
"fixture",
|
||||
|
|
|
@ -42,6 +42,8 @@ Running pytest now produces this output:
|
|||
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
|
||||
======================= 1 passed, 1 warning in 0.12s =======================
|
||||
|
||||
.. _`controlling-warnings`:
|
||||
|
||||
Controlling warnings
|
||||
--------------------
|
||||
|
||||
|
@ -176,11 +178,14 @@ using an external system.
|
|||
DeprecationWarning and PendingDeprecationWarning
|
||||
------------------------------------------------
|
||||
|
||||
|
||||
By default pytest will display ``DeprecationWarning`` and ``PendingDeprecationWarning`` warnings from
|
||||
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.
|
||||
|
||||
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
|
||||
(such as third-party libraries), in which case you might use the warning filters options (ini or marks) to ignore
|
||||
those warnings.
|
||||
|
@ -197,6 +202,9 @@ For example:
|
|||
This will ignore all warnings of type ``DeprecationWarning`` where the start of the message matches
|
||||
the regular expression ``".*U.*mode is deprecated"``.
|
||||
|
||||
See :ref:`@pytest.mark.filterwarnings <filterwarnings>` and
|
||||
:ref:`Controlling warnings <controlling-warnings>` for more examples.
|
||||
|
||||
.. note::
|
||||
|
||||
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
|
||||
------------------------------------------
|
||||
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
@ -261,8 +269,8 @@ which works in a similar manner to :ref:`raises <assertraises>`:
|
|||
with pytest.warns(UserWarning):
|
||||
warnings.warn("my warning", UserWarning)
|
||||
|
||||
The test will fail if the warning in question is not raised. The keyword
|
||||
argument ``match`` to assert that the exception matches a text or regex::
|
||||
The test will fail if the warning in question is not raised. Use the keyword
|
||||
argument ``match`` to assert that the warning matches a text or regex::
|
||||
|
||||
>>> with warns(UserWarning, match='must be 0 or None'):
|
||||
... 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:
|
||||
|
||||
- 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
|
||||
|
||||
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:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("error")
|
||||
...
|
||||
def test_warning():
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("error")
|
||||
...
|
||||
|
||||
- To suppress warnings, use:
|
||||
|
||||
|
|
|
@ -735,8 +735,81 @@ does offer some nuances for when you're in a pinch.
|
|||
.. code-block:: pytest
|
||||
|
||||
$ pytest -q test_emaillib.py
|
||||
. [100%]
|
||||
1 passed in 0.12s
|
||||
. [100%]
|
||||
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`:
|
||||
|
||||
|
|
|
@ -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
|
||||
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
|
||||
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/
|
||||
|
||||
Simple example: monkeypatching functions
|
||||
----------------------------------------
|
||||
Monkeypatching functions
|
||||
------------------------
|
||||
|
||||
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``
|
||||
|
|
|
@ -90,7 +90,7 @@ and can also be used to hold pytest configuration if they have a ``[pytest]`` se
|
|||
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.
|
||||
|
||||
.. code-block:: ini
|
||||
|
|
|
@ -11,7 +11,7 @@ automatically. Packages classified as inactive are excluded.
|
|||
creating a PDF, because otherwise the table gets far too wide for the
|
||||
page.
|
||||
|
||||
This list contains 1094 plugins.
|
||||
This list contains 1100 plugins.
|
||||
|
||||
.. 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-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-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-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
|
||||
|
@ -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-failed-screenshot` Test case fails,take a screenshot,save it,attach it to the allure Apr 21, 2021 N/A N/A
|
||||
:pypi:`pytest-failed-to-verify` A pytest plugin that helps better distinguishing real test failures from setup flakiness. Aug 08, 2019 5 - Production/Stable pytest (>=4.1.0)
|
||||
:pypi:`pytest-fail-slow` Fail tests that take too long to run 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-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
|
||||
|
@ -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-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-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-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
|
||||
|
@ -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-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-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-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)
|
||||
|
@ -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-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-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-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
|
||||
|
@ -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-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-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-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
|
||||
|
@ -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-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-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-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
|
||||
|
@ -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-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-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-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-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-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-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
|
||||
|
@ -547,6 +548,7 @@ This list contains 1094 plugins.
|
|||
: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-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-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)
|
||||
|
@ -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-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-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-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
|
||||
|
@ -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-ngrok` Jan 20, 2022 3 - Alpha pytest
|
||||
:pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0)
|
||||
:pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies 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-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
|
||||
|
@ -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-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-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-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)
|
||||
|
@ -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-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-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-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-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-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-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-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-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
|
||||
|
@ -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-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-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-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
|
||||
|
@ -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-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-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-reporter` Sep 10, 2018 N/A N/A
|
||||
: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-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-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-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
|
||||
|
@ -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-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-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-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)
|
||||
|
@ -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-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-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-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
|
||||
|
@ -2399,7 +2405,7 @@ This list contains 1094 plugins.
|
|||
Use pytest's runner to discover and execute C++ tests
|
||||
|
||||
:pypi:`pytest-cppython`
|
||||
*last release*: Jun 08, 2022,
|
||||
*last release*: Aug 13, 2022,
|
||||
*status*: 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.
|
||||
|
||||
:pypi:`pytest-fail-slow`
|
||||
*last release*: Apr 25, 2022,
|
||||
*last release*: Aug 13, 2022,
|
||||
*status*: 4 - Beta,
|
||||
*requires*: pytest (>=6.0)
|
||||
|
||||
|
@ -3840,6 +3846,13 @@ This list contains 1094 plugins.
|
|||
|
||||
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`
|
||||
*last release*: Apr 30, 2022,
|
||||
*status*: 4 - Beta,
|
||||
|
@ -4184,7 +4197,7 @@ This list contains 1094 plugins.
|
|||
A pytest plugin for use with homeassistant custom components.
|
||||
|
||||
:pypi:`pytest-homeassistant-custom-component`
|
||||
*last release*: Aug 05, 2022,
|
||||
*last release*: Aug 13, 2022,
|
||||
*status*: 3 - Alpha,
|
||||
*requires*: pytest (==7.1.2)
|
||||
|
||||
|
@ -4352,7 +4365,7 @@ This list contains 1094 plugins.
|
|||
A plugin to sent pytest results to an Ibutsu server
|
||||
|
||||
:pypi:`pytest-icdiff`
|
||||
*last release*: Apr 08, 2020,
|
||||
*last release*: Aug 09, 2022,
|
||||
*status*: 4 - Beta,
|
||||
*requires*: N/A
|
||||
|
||||
|
@ -4443,7 +4456,7 @@ This list contains 1094 plugins.
|
|||
A py.test plugin providing fixtures to simplify inmanta modules testing.
|
||||
|
||||
:pypi:`pytest-inmanta-extensions`
|
||||
*last release*: Apr 12, 2022,
|
||||
*last release*: Aug 10, 2022,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: N/A
|
||||
|
||||
|
@ -4520,11 +4533,11 @@ This list contains 1094 plugins.
|
|||
Pytest plugin for intercepting outgoing connection requests during pytest run.
|
||||
|
||||
:pypi:`pytest-invenio`
|
||||
*last release*: May 05, 2022,
|
||||
*last release*: Aug 09, 2022,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: pytest (<7,>=6)
|
||||
|
||||
Pytest fixtures for Invenio.
|
||||
"Pytest fixtures for Invenio."
|
||||
|
||||
:pypi:`pytest-involve`
|
||||
*last release*: Feb 02, 2020,
|
||||
|
@ -4632,7 +4645,7 @@ This list contains 1094 plugins.
|
|||
Generate JSON test reports
|
||||
|
||||
:pypi:`pytest-json-fixtures`
|
||||
*last release*: Aug 03, 2022,
|
||||
*last release*: Aug 09, 2022,
|
||||
*status*: 4 - Beta,
|
||||
*requires*: pytest (>=7.1.0)
|
||||
|
||||
|
@ -4674,7 +4687,7 @@ This list contains 1094 plugins.
|
|||
|
||||
|
||||
:pypi:`pytest-kind`
|
||||
*last release*: Jan 24, 2021,
|
||||
*last release*: Aug 11, 2022,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: N/A
|
||||
|
||||
|
@ -4820,6 +4833,13 @@ This list contains 1094 plugins.
|
|||
|
||||
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`
|
||||
*last release*: Jan 21, 2021,
|
||||
*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.
|
||||
|
||||
:pypi:`pytest-mock-resources`
|
||||
*last release*: Jul 20, 2022,
|
||||
*last release*: Aug 12, 2022,
|
||||
*status*: N/A,
|
||||
*requires*: pytest (>=1.0)
|
||||
|
||||
|
@ -5486,7 +5506,7 @@ This list contains 1094 plugins.
|
|||
pytest ngs fixtures
|
||||
|
||||
:pypi:`pytest-nhsd-apim`
|
||||
*last release*: Jul 21, 2022,
|
||||
*last release*: Aug 10, 2022,
|
||||
*status*: N/A,
|
||||
*requires*: pytest (==6.2.5)
|
||||
|
||||
|
@ -6249,7 +6269,7 @@ This list contains 1094 plugins.
|
|||
pytest plugin to check source code with pylint
|
||||
|
||||
:pypi:`pytest-pyodide`
|
||||
*last release*: Aug 04, 2022,
|
||||
*last release*: Aug 10, 2022,
|
||||
*status*: N/A,
|
||||
*requires*: pytest
|
||||
|
||||
|
@ -6753,7 +6773,7 @@ This list contains 1094 plugins.
|
|||
pytest plugin to re-run tests to eliminate flaky failures
|
||||
|
||||
:pypi:`pytest-resilient-circuits`
|
||||
*last release*: Jul 07, 2022,
|
||||
*last release*: Aug 12, 2022,
|
||||
*status*: N/A,
|
||||
*requires*: N/A
|
||||
|
||||
|
@ -6787,6 +6807,13 @@ This list contains 1094 plugins.
|
|||
|
||||
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`
|
||||
*last release*: May 11, 2022,
|
||||
*status*: 5 - Production/Stable,
|
||||
|
@ -6802,7 +6829,7 @@ This list contains 1094 plugins.
|
|||
A RethinkDB plugin for pytest.
|
||||
|
||||
:pypi:`pytest-retry`
|
||||
*last release*: Aug 05, 2022,
|
||||
*last release*: Aug 11, 2022,
|
||||
*status*: N/A,
|
||||
*requires*: pytest (>=7.0.0)
|
||||
|
||||
|
@ -6836,6 +6863,13 @@ This list contains 1094 plugins.
|
|||
|
||||
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`
|
||||
*last release*: Aug 08, 2019,
|
||||
*status*: 5 - Production/Stable,
|
||||
|
@ -7487,6 +7521,13 @@ This list contains 1094 plugins.
|
|||
|
||||
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`
|
||||
*last release*: Dec 19, 2019,
|
||||
*status*: N/A,
|
||||
|
@ -7908,9 +7949,9 @@ This list contains 1094 plugins.
|
|||
Pytest plugin for sending report to testrail system.
|
||||
|
||||
:pypi:`pytest-testrail-ns`
|
||||
*last release*: Jul 26, 2022,
|
||||
*last release*: Aug 12, 2022,
|
||||
*status*: N/A,
|
||||
*requires*: pytest (>=3.6)
|
||||
*requires*: N/A
|
||||
|
||||
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.
|
||||
|
||||
:pypi:`pytest-tmreport`
|
||||
*last release*: Nov 17, 2021,
|
||||
*last release*: Aug 12, 2022,
|
||||
*status*: N/A,
|
||||
*requires*: N/A
|
||||
|
||||
|
@ -8244,11 +8285,11 @@ This list contains 1094 plugins.
|
|||
Test Class Base
|
||||
|
||||
:pypi:`pytest-tui`
|
||||
*last release*: Aug 03, 2022,
|
||||
*last release*: Aug 13, 2022,
|
||||
*status*: 4 - Beta,
|
||||
*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`
|
||||
*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
|
||||
|
||||
: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`
|
||||
*last release*: Mar 26, 2021,
|
||||
*status*: N/A,
|
||||
|
|
|
@ -102,7 +102,7 @@ pytest.deprecated_call
|
|||
|
||||
**Tutorial**: :ref:`ensuring_function_triggers`
|
||||
|
||||
.. autofunction:: pytest.deprecated_call()
|
||||
.. autofunction:: pytest.deprecated_call([match])
|
||||
:with:
|
||||
|
||||
pytest.register_assert_rewrite
|
||||
|
@ -529,6 +529,7 @@ New code should avoid using :fixture:`testdir` in favor of :fixture:`pytester`.
|
|||
|
||||
.. autoclass:: pytest.Testdir()
|
||||
:members:
|
||||
:noindex: TimeoutExpired
|
||||
|
||||
|
||||
.. fixture:: recwarn
|
||||
|
|
|
@ -2,9 +2,6 @@ pallets-sphinx-themes
|
|||
pluggy>=1.0
|
||||
pygments-pytest>=2.2.0
|
||||
sphinx-removed-in>=0.2.0
|
||||
sphinx>=3.1,<4
|
||||
sphinx>=5,<6
|
||||
sphinxcontrib-trio
|
||||
sphinxcontrib-svg2pdfconverter
|
||||
|
||||
# XXX: sphinx<4 is broken with latest jinja2
|
||||
jinja2<3.1
|
||||
|
|
|
@ -3,7 +3,6 @@ requires = [
|
|||
# sync with setup.py until we discard non-pep-517/518
|
||||
"setuptools>=45.0",
|
||||
"setuptools-scm[toml]>=6.2.3",
|
||||
"wheel",
|
||||
]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ install_requires =
|
|||
pluggy>=0.12,<2.0
|
||||
py>=1.8.2
|
||||
colorama;sys_platform=="win32"
|
||||
exceptiongroup>=1.0.0rc8;python_version<"3.11"
|
||||
importlib-metadata>=0.12;python_version<"3.8"
|
||||
tomli>=1.0.0;python_version<"3.11"
|
||||
python_requires = >=3.7
|
||||
|
|
|
@ -56,6 +56,9 @@ if TYPE_CHECKING:
|
|||
|
||||
_TracebackStyle = Literal["long", "short", "line", "no", "native", "value", "auto"]
|
||||
|
||||
if sys.version_info[:2] < (3, 11):
|
||||
from exceptiongroup import BaseExceptionGroup
|
||||
|
||||
|
||||
class Code:
|
||||
"""Wrapper around Python code objects."""
|
||||
|
@ -924,7 +927,21 @@ class FormattedExcinfo:
|
|||
while e is not None and id(e) not in seen:
|
||||
seen.add(id(e))
|
||||
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] = (
|
||||
excinfo_._getreprcrash() if self.style != "value" else None
|
||||
)
|
||||
|
|
|
@ -53,7 +53,7 @@ def register_assert_rewrite(*names: str) -> None:
|
|||
actually imported, usually in your __init__.py if you are a plugin
|
||||
using a package.
|
||||
|
||||
:raises TypeError: If the given module names are not strings.
|
||||
:param names: The module names to register.
|
||||
"""
|
||||
for name in names:
|
||||
if not isinstance(name, str):
|
||||
|
|
|
@ -20,6 +20,16 @@ from typing import Union
|
|||
import attr
|
||||
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:
|
||||
from typing_extensions import Final
|
||||
|
||||
|
@ -345,7 +355,6 @@ else:
|
|||
if sys.version_info >= (3, 8):
|
||||
from functools import cached_property as cached_property
|
||||
else:
|
||||
from typing import overload
|
||||
from typing import Type
|
||||
|
||||
class cached_property(Generic[_S, _T]):
|
||||
|
|
|
@ -66,14 +66,15 @@ class Parser:
|
|||
) -> "OptionGroup":
|
||||
"""Get (or create) a named option Group.
|
||||
|
||||
:name: Name of the option group.
|
||||
:description: Long description for --help output.
|
||||
:after: Name of another group, used for ordering --help output.
|
||||
:param name: Name of the option group.
|
||||
:param description: Long description for --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
|
||||
signature as :func:`parser.addoption <pytest.Parser.addoption>` but
|
||||
will be shown in the respective group in the output of
|
||||
``pytest. --help``.
|
||||
``pytest --help``.
|
||||
"""
|
||||
for group in self._groups:
|
||||
if group.name == name:
|
||||
|
@ -89,10 +90,11 @@ class Parser:
|
|||
def addoption(self, *opts: str, **attrs: Any) -> None:
|
||||
"""Register a command line option.
|
||||
|
||||
:opts: Option names, can be short or long options.
|
||||
:attrs: Same attributes which the ``add_argument()`` function of the
|
||||
`argparse library <https://docs.python.org/library/argparse.html>`_
|
||||
accepts.
|
||||
: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.
|
||||
|
||||
After command line parsing, options are available on the pytest config
|
||||
object via ``config.option.NAME`` where ``NAME`` is usually set
|
||||
|
@ -148,7 +150,10 @@ class Parser:
|
|||
args: Sequence[Union[str, "os.PathLike[str]"]],
|
||||
namespace: Optional[argparse.Namespace] = None,
|
||||
) -> 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]
|
||||
|
||||
def parse_known_and_unknown_args(
|
||||
|
@ -156,8 +161,13 @@ class Parser:
|
|||
args: Sequence[Union[str, "os.PathLike[str]"]],
|
||||
namespace: Optional[argparse.Namespace] = None,
|
||||
) -> Tuple[argparse.Namespace, List[str]]:
|
||||
"""Parse and return a namespace object with known arguments, and
|
||||
the remaining arguments unknown at this point."""
|
||||
"""Parse the known arguments at this point, and also return the
|
||||
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()
|
||||
strargs = [os.fspath(x) for x in args]
|
||||
return optparser.parse_known_args(strargs, namespace=namespace)
|
||||
|
@ -173,9 +183,9 @@ class Parser:
|
|||
) -> None:
|
||||
"""Register an ini-file option.
|
||||
|
||||
:name:
|
||||
:param name:
|
||||
Name of the ini-variable.
|
||||
:type:
|
||||
:param type:
|
||||
Type of the variable. Can be:
|
||||
|
||||
* ``string``: a string
|
||||
|
@ -189,7 +199,7 @@ class Parser:
|
|||
The ``paths`` variable type.
|
||||
|
||||
Defaults to ``string`` if ``None`` or not passed.
|
||||
:default:
|
||||
:param default:
|
||||
Default value if no ini-file option exists but is queried.
|
||||
|
||||
The value of ini-variables can be retrieved via a call to
|
||||
|
@ -354,24 +364,30 @@ class OptionGroup:
|
|||
self.options: List[Argument] = []
|
||||
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.
|
||||
|
||||
If a shortened version of a long option is specified, it will
|
||||
be suppressed in the help. ``addoption('--twowords', '--two-words')``
|
||||
results in help showing ``--two-words`` only, but ``--twowords`` gets
|
||||
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()
|
||||
)
|
||||
if conflict:
|
||||
raise ValueError("option names %s already added" % conflict)
|
||||
option = Argument(*optnames, **attrs)
|
||||
option = Argument(*opts, **attrs)
|
||||
self._addoption_instance(option, shortupper=False)
|
||||
|
||||
def _addoption(self, *optnames: str, **attrs: Any) -> None:
|
||||
option = Argument(*optnames, **attrs)
|
||||
def _addoption(self, *opts: str, **attrs: Any) -> None:
|
||||
option = Argument(*opts, **attrs)
|
||||
self._addoption_instance(option, shortupper=True)
|
||||
|
||||
def _addoption_instance(self, option: "Argument", shortupper: bool = False) -> None:
|
||||
|
|
|
@ -20,7 +20,6 @@ from typing import List
|
|||
from typing import MutableMapping
|
||||
from typing import NoReturn
|
||||
from typing import Optional
|
||||
from typing import overload
|
||||
from typing import Sequence
|
||||
from typing import Set
|
||||
from typing import Tuple
|
||||
|
@ -48,6 +47,7 @@ from _pytest.compat import getimfunc
|
|||
from _pytest.compat import getlocation
|
||||
from _pytest.compat import is_generator
|
||||
from _pytest.compat import NOTSET
|
||||
from _pytest.compat import overload
|
||||
from _pytest.compat import safe_getattr
|
||||
from _pytest.config import _PluggyPlugin
|
||||
from _pytest.config import Config
|
||||
|
@ -513,8 +513,8 @@ class FixtureRequest:
|
|||
return self._pyfuncitem.session # type: ignore[no-any-return]
|
||||
|
||||
def addfinalizer(self, finalizer: Callable[[], object]) -> None:
|
||||
"""Add finalizer/teardown function to be called after the last test
|
||||
within the requesting test context finished execution."""
|
||||
"""Add finalizer/teardown function to be called without arguments after
|
||||
the last test within the requesting test context finished execution."""
|
||||
# XXX usually this method is shadowed by fixturedef specific ones.
|
||||
self._addfinalizer(finalizer, scope=self.scope)
|
||||
|
||||
|
@ -529,13 +529,16 @@ class FixtureRequest:
|
|||
on all function invocations.
|
||||
|
||||
:param marker:
|
||||
A :class:`pytest.MarkDecorator` object created by a call
|
||||
to ``pytest.mark.NAME(...)``.
|
||||
An object created by a call to ``pytest.mark.NAME(...)``.
|
||||
"""
|
||||
self.node.add_marker(marker)
|
||||
|
||||
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)
|
||||
|
||||
def _fillfixtures(self) -> None:
|
||||
|
@ -557,6 +560,8 @@ class FixtureRequest:
|
|||
phase, but during the test teardown phase a fixture's value may not
|
||||
be available.
|
||||
|
||||
:param argname:
|
||||
The fixture name.
|
||||
:raises pytest.FixtureLookupError:
|
||||
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}>"
|
||||
|
||||
def addfinalizer(self, finalizer: Callable[[], object]) -> None:
|
||||
"""Add finalizer/teardown function to be called after the last test
|
||||
within the requesting test context finished execution."""
|
||||
"""Add finalizer/teardown function to be called without arguments after
|
||||
the last test within the requesting test context finished execution."""
|
||||
self._fixturedef.addfinalizer(finalizer)
|
||||
|
||||
def _schedule_finalizers(
|
||||
|
@ -1226,7 +1231,7 @@ def fixture(
|
|||
|
||||
|
||||
@overload
|
||||
def fixture(
|
||||
def fixture( # noqa: F811
|
||||
fixture_function: None = ...,
|
||||
*,
|
||||
scope: "Union[_ScopeName, Callable[[str, Config], _ScopeName]]" = ...,
|
||||
|
@ -1240,7 +1245,7 @@ def fixture(
|
|||
...
|
||||
|
||||
|
||||
def fixture(
|
||||
def fixture( # noqa: F811
|
||||
fixture_function: Optional[FixtureFunction] = None,
|
||||
*,
|
||||
scope: "Union[_ScopeName, Callable[[str, Config], _ScopeName]]" = "function",
|
||||
|
|
|
@ -143,7 +143,7 @@ def pytest_configure(config: "Config") -> None:
|
|||
def pytest_cmdline_parse(
|
||||
pluginmanager: "PytestPluginManager", args: List[str]
|
||||
) -> 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`.
|
||||
|
||||
|
@ -152,8 +152,9 @@ def pytest_cmdline_parse(
|
|||
``plugins`` arg when using `pytest.main`_ to perform an in-process
|
||||
test run.
|
||||
|
||||
:param pytest.PytestPluginManager pluginmanager: The pytest plugin manager.
|
||||
:param List[str] args: List of arguments passed on the command line.
|
||||
:param pluginmanager: The pytest plugin manager.
|
||||
: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::
|
||||
This hook will not be called for ``conftest.py`` files, only for setuptools plugins.
|
||||
|
||||
:param pytest.Config config: The pytest config object.
|
||||
:param List[str] args: Arguments passed on the command line.
|
||||
:param config: The pytest config object.
|
||||
: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`.
|
||||
|
||||
: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::
|
||||
This hook will not be called for ``conftest.py`` files, only for setuptools plugins.
|
||||
|
||||
:param pytest.Config early_config: The pytest config object.
|
||||
:param List[str] args: Arguments passed on the command line.
|
||||
:param pytest.Parser parser: To add command line options.
|
||||
:param early_config: The pytest config object.
|
||||
:param args: Arguments passed on the command line.
|
||||
: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
|
||||
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
|
||||
the items in-place.
|
||||
|
||||
:param pytest.Session session: The pytest session object.
|
||||
:param pytest.Config config: The pytest config object.
|
||||
:param List[pytest.Item] items: List of item objects.
|
||||
:param session: The pytest session object.
|
||||
:param config: The pytest config object.
|
||||
:param items: List of item objects.
|
||||
"""
|
||||
|
||||
|
||||
def pytest_collection_finish(session: "Session") -> None:
|
||||
"""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`.
|
||||
|
||||
:param pathlib.Path collection_path : The path to analyze.
|
||||
:param LEGACY_PATH path: The path to analyze (deprecated).
|
||||
:param pytest.Config config: The pytest config object.
|
||||
:param collection_path: The path to analyze.
|
||||
:param path: The path to analyze (deprecated).
|
||||
:param config: The pytest config object.
|
||||
|
||||
.. versionchanged:: 7.0.0
|
||||
The ``collection_path`` parameter was added as a :class:`pathlib.Path`
|
||||
|
@ -284,12 +286,12 @@ def pytest_ignore_collect(
|
|||
def pytest_collect_file(
|
||||
file_path: Path, path: "LEGACY_PATH", parent: "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.
|
||||
|
||||
:param pathlib.Path file_path: The path to analyze.
|
||||
:param LEGACY_PATH path: The path to collect (deprecated).
|
||||
:param file_path: The path to analyze.
|
||||
:param path: The path to collect (deprecated).
|
||||
|
||||
.. versionchanged:: 7.0.0
|
||||
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:
|
||||
"""Collector starts collecting."""
|
||||
"""Collector starts collecting.
|
||||
|
||||
:param collector:
|
||||
The collector.
|
||||
"""
|
||||
|
||||
|
||||
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:
|
||||
"""Collector finished collecting."""
|
||||
"""Collector finished collecting.
|
||||
|
||||
:param report:
|
||||
The collect report.
|
||||
"""
|
||||
|
||||
|
||||
def pytest_deselected(items: Sequence["Item"]) -> None:
|
||||
"""Called for deselected test items, e.g. by keyword.
|
||||
|
||||
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`.
|
||||
|
||||
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(
|
||||
module_path: Path, path: "LEGACY_PATH", parent
|
||||
) -> 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.
|
||||
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.
|
||||
|
||||
Stops at first non-None result, see :ref:`firstresult`.
|
||||
|
||||
:param pathlib.Path module_path: The path of the module to collect.
|
||||
:param LEGACY_PATH path: The path of the module to collect (deprecated).
|
||||
:param module_path: The path of the module to collect.
|
||||
:param path: The path of the module to collect (deprecated).
|
||||
|
||||
.. versionchanged:: 7.0.0
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
Stops at first non-None result, see :ref:`firstresult`.
|
||||
|
||||
:param pyfuncitem:
|
||||
The function item.
|
||||
"""
|
||||
|
||||
|
||||
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)
|
||||
|
@ -391,7 +427,7 @@ def pytest_make_parametrize_id(
|
|||
|
||||
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 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
|
||||
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`.
|
||||
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.
|
||||
|
||||
: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)``.
|
||||
"""
|
||||
|
||||
|
@ -480,7 +516,7 @@ def pytest_runtest_logfinish(
|
|||
|
||||
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)``.
|
||||
"""
|
||||
|
||||
|
@ -492,6 +528,9 @@ def pytest_runtest_setup(item: "Item") -> None:
|
|||
parents (which haven't been setup yet). This includes obtaining the
|
||||
values of fixtures required by the item (which haven't been obtained
|
||||
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).
|
||||
|
||||
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
|
||||
they go out of scope).
|
||||
|
||||
:param item:
|
||||
The item.
|
||||
:param nextitem:
|
||||
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.
|
||||
|
@ -527,6 +571,7 @@ def pytest_runtest_makereport(
|
|||
|
||||
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.
|
||||
|
||||
Stops at first non-None result, see :ref:`firstresult`.
|
||||
|
@ -547,7 +592,11 @@ def pytest_report_to_serializable(
|
|||
report: Union["CollectReport", "TestReport"],
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""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)
|
||||
|
@ -556,7 +605,10 @@ def pytest_report_from_serializable(
|
|||
data: Dict[str, Any],
|
||||
) -> Optional[Union["CollectReport", "TestReport"]]:
|
||||
"""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]:
|
||||
"""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`.
|
||||
|
||||
|
@ -586,7 +643,13 @@ def pytest_fixture_post_finalizer(
|
|||
) -> None:
|
||||
"""Called after fixture teardown, but before the cache is cleared, so
|
||||
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
|
||||
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:
|
||||
"""Called after whole test run finished, right before returning the exit status to the system.
|
||||
|
||||
:param pytest.Session session: The pytest session object.
|
||||
:param int exitstatus: The status which pytest will return to the system.
|
||||
:param session: The pytest session object.
|
||||
:param exitstatus: The status which pytest will return to the system.
|
||||
"""
|
||||
|
||||
|
||||
def pytest_unconfigure(config: "Config") -> None:
|
||||
"""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
|
||||
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
|
||||
when enabling this option, as assertions will require to be re-written.
|
||||
|
||||
:param pytest.Item item: pytest item object of current test.
|
||||
:param int lineno: Line number of the assert statement.
|
||||
:param str orig: String with the original assertion.
|
||||
:param str expl: String with the assert explanation.
|
||||
:param item: pytest item object of current test.
|
||||
:param lineno: Line number of the assert statement.
|
||||
:param orig: String with the original assertion.
|
||||
:param expl: String with the assert explanation.
|
||||
"""
|
||||
|
||||
|
||||
|
@ -677,9 +743,9 @@ def pytest_report_header(
|
|||
) -> Union[str, List[str]]:
|
||||
"""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 Path start_path: The starting dir.
|
||||
:param LEGACY_PATH startdir: The starting dir (deprecated).
|
||||
:param config: The pytest config object.
|
||||
:param start_path: The starting dir.
|
||||
:param startdir: The starting dir (deprecated).
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -714,9 +780,9 @@ def pytest_report_collectionfinish(
|
|||
|
||||
.. versionadded:: 3.2
|
||||
|
||||
:param pytest.Config config: The pytest config object.
|
||||
:param Path start_path: The starting dir.
|
||||
:param LEGACY_PATH startdir: The starting dir (deprecated).
|
||||
:param config: The pytest config object.
|
||||
:param start_path: The starting dir.
|
||||
:param startdir: The starting dir (deprecated).
|
||||
:param items: List of pytest items that are going to be executed; this list should not be modified.
|
||||
|
||||
.. note::
|
||||
|
@ -755,6 +821,7 @@ def pytest_report_teststatus(
|
|||
|
||||
:param report: The report object whose status is to be returned.
|
||||
:param config: The pytest config object.
|
||||
:returns: The test status.
|
||||
|
||||
Stops at first non-None result, see :ref:`firstresult`.
|
||||
"""
|
||||
|
@ -767,9 +834,9 @@ def pytest_terminal_summary(
|
|||
) -> None:
|
||||
"""Add a section to terminal summary reporting.
|
||||
|
||||
:param _pytest.terminal.TerminalReporter terminalreporter: The internal terminal reporter object.
|
||||
:param int exitstatus: The exit status that will be reported back to the OS.
|
||||
:param pytest.Config config: The pytest config object.
|
||||
:param terminalreporter: The internal terminal reporter object.
|
||||
:param exitstatus: The exit status that will be reported back to the OS.
|
||||
:param config: The pytest config object.
|
||||
|
||||
.. versionadded:: 4.2
|
||||
The ``config`` parameter.
|
||||
|
@ -785,21 +852,21 @@ def pytest_warning_recorded(
|
|||
) -> None:
|
||||
"""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 same attributes as the parameters of :py:func:`warnings.showwarning`.
|
||||
|
||||
:param str when:
|
||||
:param when:
|
||||
Indicates when the warning was captured. Possible values:
|
||||
|
||||
* ``"config"``: during pytest configuration/initialization stage.
|
||||
* ``"collect"``: during test collection.
|
||||
* ``"runtest"``: during test execution.
|
||||
|
||||
:param str nodeid:
|
||||
:param nodeid:
|
||||
Full id of the item.
|
||||
|
||||
:param tuple|None location:
|
||||
:param location:
|
||||
When available, holds information about the execution context of the captured
|
||||
warning (filename, linenumber, function). ``function`` evaluates to <module>
|
||||
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
|
||||
|
||||
:param pytest.Config config: The pytest config object.
|
||||
:param config: The pytest config object.
|
||||
: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
|
||||
INTERNALERROR message directly to sys.stderr.
|
||||
|
||||
:param excrepr: The exception repr object.
|
||||
:param excinfo: The exception info.
|
||||
"""
|
||||
|
||||
|
||||
def pytest_keyboard_interrupt(
|
||||
excinfo: "ExceptionInfo[Union[KeyboardInterrupt, Exit]]",
|
||||
) -> None:
|
||||
"""Called for keyboard interrupt."""
|
||||
"""Called for keyboard interrupt.
|
||||
|
||||
:param excinfo: The exception info.
|
||||
"""
|
||||
|
||||
|
||||
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
|
||||
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
|
||||
debugger enters interactive mode.
|
||||
|
||||
:param pytest.Config config: The pytest config object.
|
||||
:param pdb.Pdb pdb: The Pdb instance.
|
||||
:param config: The pytest config object.
|
||||
: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
|
||||
debugger leaves interactive mode.
|
||||
|
||||
:param pytest.Config config: The pytest config object.
|
||||
:param pdb.Pdb pdb: The Pdb instance.
|
||||
:param config: The pytest config object.
|
||||
:param pdb: The Pdb instance.
|
||||
"""
|
||||
|
|
|
@ -231,7 +231,7 @@ class _NodeReporter:
|
|||
msg = f'failed on teardown with "{reason}"'
|
||||
else:
|
||||
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:
|
||||
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("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::
|
||||
|
||||
|
|
|
@ -37,6 +37,8 @@ from _pytest.terminal import TerminalReporter
|
|||
|
||||
if TYPE_CHECKING:
|
||||
logging_StreamHandler = logging.StreamHandler[StringIO]
|
||||
|
||||
from typing_extensions import Literal
|
||||
else:
|
||||
logging_StreamHandler = logging.StreamHandler
|
||||
|
||||
|
@ -382,20 +384,19 @@ class LogCaptureFixture:
|
|||
|
||||
@property
|
||||
def handler(self) -> LogCaptureHandler:
|
||||
"""Get the logging handler used by the fixture.
|
||||
|
||||
:rtype: LogCaptureHandler
|
||||
"""
|
||||
"""Get the logging handler used by the fixture."""
|
||||
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.
|
||||
|
||||
:param str when:
|
||||
Which test phase to obtain the records from. Valid values are: "setup", "call" and "teardown".
|
||||
:param when:
|
||||
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.
|
||||
:rtype: List[logging.LogRecord]
|
||||
|
||||
.. versionadded:: 3.4
|
||||
"""
|
||||
|
@ -452,8 +453,8 @@ class LogCaptureFixture:
|
|||
The levels of the loggers changed by this function will be
|
||||
restored to their initial values at the end of the test.
|
||||
|
||||
:param int level: The level.
|
||||
:param str logger: The logger to update. If not given, the root logger.
|
||||
:param level: The level.
|
||||
:param logger: The logger to update. If not given, the root logger.
|
||||
"""
|
||||
logger_obj = logging.getLogger(logger)
|
||||
# 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
|
||||
value.
|
||||
|
||||
:param int level: The level.
|
||||
:param str logger: The logger to update. If not given, the root logger.
|
||||
:param level: The level.
|
||||
:param logger: The logger to update. If not given, the root logger.
|
||||
"""
|
||||
logger_obj = logging.getLogger(logger)
|
||||
orig_level = logger_obj.level
|
||||
|
|
|
@ -12,7 +12,6 @@ from typing import FrozenSet
|
|||
from typing import Iterator
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
from typing import overload
|
||||
from typing import Sequence
|
||||
from typing import Set
|
||||
from typing import Tuple
|
||||
|
@ -25,6 +24,7 @@ import attr
|
|||
import _pytest._code
|
||||
from _pytest import nodes
|
||||
from _pytest.compat import final
|
||||
from _pytest.compat import overload
|
||||
from _pytest.config import Config
|
||||
from _pytest.config import directory_arg
|
||||
from _pytest.config import ExitCode
|
||||
|
@ -597,12 +597,12 @@ class Session(nodes.FSCollector):
|
|||
...
|
||||
|
||||
@overload
|
||||
def perform_collect(
|
||||
def perform_collect( # noqa: F811
|
||||
self, args: Optional[Sequence[str]] = ..., genitems: bool = ...
|
||||
) -> Sequence[Union[nodes.Item, nodes.Collector]]:
|
||||
...
|
||||
|
||||
def perform_collect(
|
||||
def perform_collect( # noqa: F811
|
||||
self, args: Optional[Sequence[str]] = None, genitems: bool = True
|
||||
) -> Sequence[Union[nodes.Item, nodes.Collector]]:
|
||||
"""Perform the collection phase for this session.
|
||||
|
|
|
@ -62,8 +62,8 @@ def param(
|
|||
assert eval(test_input) == expected
|
||||
|
||||
: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.
|
||||
:keyword str id: The id to attribute to this parameter set.
|
||||
:param marks: A single mark or a list of marks to be applied to this parameter set.
|
||||
:param id: The id to attribute to this parameter set.
|
||||
"""
|
||||
return ParameterSet.param(*values, marks=marks, id=id)
|
||||
|
||||
|
|
|
@ -126,12 +126,12 @@ class ParameterSet(NamedTuple):
|
|||
|
||||
@staticmethod
|
||||
def _parse_parametrize_args(
|
||||
argnames: Union[str, List[str], Tuple[str, ...]],
|
||||
argnames: Union[str, Sequence[str]],
|
||||
argvalues: Iterable[Union["ParameterSet", Sequence[object], object]],
|
||||
*args,
|
||||
**kwargs,
|
||||
) -> Tuple[Union[List[str], Tuple[str, ...]], bool]:
|
||||
if not isinstance(argnames, (tuple, list)):
|
||||
) -> Tuple[Sequence[str], bool]:
|
||||
if isinstance(argnames, str):
|
||||
argnames = [x.strip() for x in argnames.split(",") if x.strip()]
|
||||
force_tuple = len(argnames) == 1
|
||||
else:
|
||||
|
@ -150,12 +150,12 @@ class ParameterSet(NamedTuple):
|
|||
@classmethod
|
||||
def _for_parametrize(
|
||||
cls,
|
||||
argnames: Union[str, List[str], Tuple[str, ...]],
|
||||
argnames: Union[str, Sequence[str]],
|
||||
argvalues: Iterable[Union["ParameterSet", Sequence[object], object]],
|
||||
func,
|
||||
config: Config,
|
||||
nodeid: str,
|
||||
) -> Tuple[Union[List[str], Tuple[str, ...]], List["ParameterSet"]]:
|
||||
) -> Tuple[Sequence[str], List["ParameterSet"]]:
|
||||
argnames, force_tuple = cls._parse_parametrize_args(argnames, argvalues)
|
||||
parameters = cls._parse_parametrize_parameters(argvalues, force_tuple)
|
||||
del argvalues
|
||||
|
@ -434,7 +434,7 @@ if TYPE_CHECKING:
|
|||
class _ParametrizeMarkDecorator(MarkDecorator):
|
||||
def __call__( # type: ignore[override]
|
||||
self,
|
||||
argnames: Union[str, List[str], Tuple[str, ...]],
|
||||
argnames: Union[str, Sequence[str]],
|
||||
argvalues: Iterable[Union[ParameterSet, Sequence[object], object]],
|
||||
*,
|
||||
indirect: Union[bool, Sequence[str]] = ...,
|
||||
|
|
|
@ -29,21 +29,26 @@ V = TypeVar("V")
|
|||
def monkeypatch() -> Generator["MonkeyPatch", None, None]:
|
||||
"""A convenient fixture for monkey-patching.
|
||||
|
||||
The fixture provides these methods to modify objects, dictionaries or
|
||||
os.environ::
|
||||
The fixture provides these methods to modify objects, dictionaries, or
|
||||
:data:`os.environ`:
|
||||
|
||||
monkeypatch.setattr(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)
|
||||
* :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>`
|
||||
|
||||
All modifications will be undone after the requesting test function or
|
||||
fixture has finished. The ``raising`` parameter determines if a KeyError
|
||||
or AttributeError will be raised if the set/deletion operation has no target.
|
||||
fixture has finished. The ``raising`` parameter determines if a :class:`KeyError`
|
||||
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()
|
||||
yield mpatch
|
||||
|
@ -115,7 +120,7 @@ class MonkeyPatch:
|
|||
|
||||
Returned by the :fixture:`monkeypatch` fixture.
|
||||
|
||||
:versionchanged:: 6.2
|
||||
.. versionchanged:: 6.2
|
||||
Can now also be used directly as `pytest.MonkeyPatch()`, for when
|
||||
the fixture is not available. In this case, use
|
||||
:meth:`with MonkeyPatch.context() as mp: <context>` or remember to call
|
||||
|
@ -182,16 +187,40 @@ class MonkeyPatch:
|
|||
value: object = notset,
|
||||
raising: bool = True,
|
||||
) -> 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
|
||||
being the attribute name. For example,
|
||||
``monkeypatch.setattr("os.getcwd", lambda: "/")``
|
||||
would set the ``getcwd`` function of the ``os`` module.
|
||||
being the attribute name:
|
||||
|
||||
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.
|
||||
|
||||
**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
|
||||
import inspect
|
||||
|
@ -338,7 +367,8 @@ class MonkeyPatch:
|
|||
def chdir(self, path: Union[str, "os.PathLike[str]"]) -> None:
|
||||
"""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:
|
||||
self._cwd = os.getcwd()
|
||||
|
@ -353,11 +383,14 @@ class MonkeyPatch:
|
|||
There is generally no need to call `undo()`, since it is
|
||||
called automatically during tear-down.
|
||||
|
||||
Note that the same `monkeypatch` fixture is used across a
|
||||
single test function invocation. If `monkeypatch` is used both by
|
||||
the test function itself and one of the test fixtures,
|
||||
calling `undo()` will undo all of the changes made in
|
||||
both functions.
|
||||
.. note::
|
||||
The same `monkeypatch` fixture is used across a
|
||||
single test function invocation. If `monkeypatch` is used both by
|
||||
the test function itself and one of the test fixtures,
|
||||
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):
|
||||
if value is not notset:
|
||||
|
|
|
@ -193,7 +193,7 @@ class Node(metaclass=NodeMeta):
|
|||
nodeid: Optional[str] = None,
|
||||
) -> None:
|
||||
#: A unique name within the scope of the parent node.
|
||||
self.name = name
|
||||
self.name: str = name
|
||||
|
||||
#: The parent collector node.
|
||||
self.parent = parent
|
||||
|
@ -208,7 +208,7 @@ class Node(metaclass=NodeMeta):
|
|||
|
||||
if session:
|
||||
#: The pytest session this node is part of.
|
||||
self.session = session
|
||||
self.session: Session = session
|
||||
else:
|
||||
if not parent:
|
||||
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
|
||||
#: own use.
|
||||
#:
|
||||
#: :type: Stash
|
||||
self.stash = Stash()
|
||||
self.stash: Stash = Stash()
|
||||
# Deprecated alias. Was never public. Can be removed in a few releases.
|
||||
self._store = self.stash
|
||||
|
||||
|
@ -326,7 +324,10 @@ class Node(metaclass=NodeMeta):
|
|||
|
||||
def listchain(self) -> List["Node"]:
|
||||
"""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 = []
|
||||
item: Optional[Node] = self
|
||||
while item is not None:
|
||||
|
@ -340,6 +341,8 @@ class Node(metaclass=NodeMeta):
|
|||
) -> None:
|
||||
"""Dynamically add a marker object to the node.
|
||||
|
||||
:param marker:
|
||||
The marker.
|
||||
:param append:
|
||||
Whether to append the marker, or prepend it.
|
||||
"""
|
||||
|
@ -361,6 +364,7 @@ class Node(metaclass=NodeMeta):
|
|||
"""Iterate over all markers of the node.
|
||||
|
||||
: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))
|
||||
|
||||
|
@ -407,7 +411,8 @@ class Node(metaclass=NodeMeta):
|
|||
return [x.name for x in self.listchain()]
|
||||
|
||||
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
|
||||
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]:
|
||||
"""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
|
||||
while current and not isinstance(current, cls):
|
||||
current = current.parent
|
||||
|
|
|
@ -241,6 +241,9 @@ def xfail(reason: str = "") -> NoReturn:
|
|||
|
||||
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::
|
||||
It is better to use the :ref:`pytest.mark.xfail ref` marker when
|
||||
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
|
||||
current test if the module cannot be imported.
|
||||
|
||||
:param str modname:
|
||||
:param modname:
|
||||
The name of the module to import.
|
||||
:param str minversion:
|
||||
:param minversion:
|
||||
If given, the imported module's ``__version__`` attribute must be at
|
||||
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
|
||||
be imported.
|
||||
|
||||
|
|
|
@ -661,17 +661,7 @@ class Pytester:
|
|||
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
|
||||
the current working directory to ``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.
|
||||
the current working directory to :attr:`path` and environment variables during initialization.
|
||||
"""
|
||||
|
||||
__test__ = False
|
||||
|
@ -700,6 +690,10 @@ class Pytester:
|
|||
name = request.node.name
|
||||
self._name = name
|
||||
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._cwd_snapshot = CwdSnapshot()
|
||||
self._sys_path_snapshot = SysPathsSnapshot()
|
||||
|
@ -724,7 +718,7 @@ class Pytester:
|
|||
|
||||
@property
|
||||
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
|
||||
|
||||
def __repr__(self) -> str:
|
||||
|
@ -755,7 +749,7 @@ class Pytester:
|
|||
return SysModulesSnapshot(preserve=preserve_module)
|
||||
|
||||
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)
|
||||
self._request.addfinalizer(reprec.finish_recording)
|
||||
return reprec
|
||||
|
@ -804,7 +798,7 @@ class Pytester:
|
|||
def makefile(self, ext: str, *args: str, **kwargs: str) -> Path:
|
||||
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`.
|
||||
:param args:
|
||||
All args are treated as strings and joined using newlines.
|
||||
|
@ -813,6 +807,8 @@ class Pytester:
|
|||
:param kwargs:
|
||||
Each keyword is the name of a file, while the value of it will
|
||||
be written as contents of the file.
|
||||
:returns:
|
||||
The first created file.
|
||||
|
||||
Examples:
|
||||
|
||||
|
@ -832,11 +828,19 @@ class Pytester:
|
|||
return self._makefile(ext, args, kwargs)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
def getinicfg(self, source: str) -> SectionWrapper:
|
||||
|
@ -845,7 +849,10 @@ class Pytester:
|
|||
return IniConfig(str(p))["pytest"]
|
||||
|
||||
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
|
||||
"""
|
||||
|
@ -898,6 +905,9 @@ class Pytester:
|
|||
|
||||
This is undone automatically when this object dies at the end of each
|
||||
test.
|
||||
|
||||
:param path:
|
||||
The path.
|
||||
"""
|
||||
if path is None:
|
||||
path = self.path
|
||||
|
@ -905,7 +915,13 @@ class Pytester:
|
|||
self._monkeypatch.syspath_prepend(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.mkdir()
|
||||
return p
|
||||
|
@ -924,14 +940,15 @@ class Pytester:
|
|||
def copy_example(self, name: Optional[str] = None) -> Path:
|
||||
"""Copy file from project's directory into the testdir.
|
||||
|
||||
:param str name: The name of the file to copy.
|
||||
:return: path to the copied directory (inside ``self.path``).
|
||||
|
||||
:param name:
|
||||
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")
|
||||
if example_dir is None:
|
||||
example_dir_ = self._request.config.getini("pytester_example_dir")
|
||||
if example_dir_ is None:
|
||||
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"):
|
||||
assert extra_element.args
|
||||
|
@ -967,14 +984,16 @@ class Pytester:
|
|||
|
||||
def getnode(
|
||||
self, config: Config, arg: Union[str, "os.PathLike[str]"]
|
||||
) -> Optional[Union[Collector, Item]]:
|
||||
"""Return the collection node of a file.
|
||||
) -> Union[Collector, Item]:
|
||||
"""Get the collection node of a file.
|
||||
|
||||
:param pytest.Config config:
|
||||
:param config:
|
||||
A pytest config.
|
||||
See :py:meth:`parseconfig` and :py:meth:`parseconfigure` for creating it.
|
||||
:param os.PathLike[str] arg:
|
||||
:param arg:
|
||||
Path to the file.
|
||||
:returns:
|
||||
The node.
|
||||
"""
|
||||
session = Session.from_config(config)
|
||||
assert "::" not in str(arg)
|
||||
|
@ -984,13 +1003,18 @@ class Pytester:
|
|||
config.hook.pytest_sessionfinish(session=session, exitstatus=ExitCode.OK)
|
||||
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.
|
||||
|
||||
This is like :py:meth:`getnode` but uses :py:meth:`parseconfigure` to
|
||||
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)
|
||||
config = self.parseconfigure(path)
|
||||
|
@ -1006,6 +1030,11 @@ class Pytester:
|
|||
|
||||
This recurses into the collection node and returns a list of all the
|
||||
test items contained within.
|
||||
|
||||
:param colitems:
|
||||
The collection nodes.
|
||||
:returns:
|
||||
The collected items.
|
||||
"""
|
||||
session = colitems[0].session
|
||||
result: List[Item] = []
|
||||
|
@ -1192,15 +1221,16 @@ class Pytester:
|
|||
return new_args
|
||||
|
||||
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
|
||||
a new :py:class:`_pytest.core.PluginManager` and call the
|
||||
pytest_cmdline_parse hook to create a new
|
||||
:py:class:`pytest.Config` instance.
|
||||
This invokes the pytest bootstrapping code in _pytest.config to create a
|
||||
new :py:class:`pytest.PytestPluginManager` and call the
|
||||
:hook:`pytest_cmdline_parse` hook to create a new :class:`pytest.Config`
|
||||
instance.
|
||||
|
||||
If :py:attr:`plugins` has been populated they should be plugin modules
|
||||
to be registered with the PluginManager.
|
||||
If :attr:`plugins` has been populated they should be plugin modules
|
||||
to be registered with the plugin manager.
|
||||
"""
|
||||
import _pytest.config
|
||||
|
||||
|
@ -1218,7 +1248,8 @@ class Pytester:
|
|||
"""Return a new pytest configured Config instance.
|
||||
|
||||
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._do_configure()
|
||||
|
@ -1237,6 +1268,8 @@ class Pytester:
|
|||
The module source.
|
||||
:param funcname:
|
||||
The name of the test function for which to return a test item.
|
||||
:returns:
|
||||
The test item.
|
||||
"""
|
||||
items = self.getitems(source)
|
||||
for item in items:
|
||||
|
@ -1377,6 +1410,8 @@ class Pytester:
|
|||
- Otherwise, it is passed through to :py:class:`subprocess.Popen`.
|
||||
For further information in this case, consult the document of the
|
||||
``stdin`` parameter in :py:class:`subprocess.Popen`.
|
||||
:returns:
|
||||
The result.
|
||||
"""
|
||||
__tracebackhide__ = True
|
||||
|
||||
|
@ -1463,6 +1498,8 @@ class Pytester:
|
|||
:param timeout:
|
||||
The period in seconds after which to timeout and raise
|
||||
:py:class:`Pytester.TimeoutExpired`.
|
||||
:returns:
|
||||
The result.
|
||||
"""
|
||||
__tracebackhide__ = True
|
||||
p = make_numbered_dir(root=self.path, prefix="runpytest-", mode=0o700)
|
||||
|
|
|
@ -1207,7 +1207,7 @@ class Metafunc:
|
|||
|
||||
def parametrize(
|
||||
self,
|
||||
argnames: Union[str, List[str], Tuple[str, ...]],
|
||||
argnames: Union[str, Sequence[str]],
|
||||
argvalues: Iterable[Union[ParameterSet, Sequence[object], object]],
|
||||
indirect: Union[bool, Sequence[str]] = False,
|
||||
ids: Optional[
|
||||
|
|
|
@ -12,7 +12,6 @@ from typing import Generic
|
|||
from typing import List
|
||||
from typing import Mapping
|
||||
from typing import Optional
|
||||
from typing import overload
|
||||
from typing import Pattern
|
||||
from typing import Sequence
|
||||
from typing import Tuple
|
||||
|
@ -28,6 +27,7 @@ if TYPE_CHECKING:
|
|||
import _pytest._code
|
||||
from _pytest.compat import final
|
||||
from _pytest.compat import STRING_TYPES
|
||||
from _pytest.compat import overload
|
||||
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
|
||||
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::
|
||||
|
||||
>>> 0.1 + 0.2 == 0.3
|
||||
|
@ -786,7 +786,7 @@ def raises(
|
|||
|
||||
|
||||
@overload
|
||||
def raises(
|
||||
def raises( # noqa: F811
|
||||
expected_exception: Union[Type[E], Tuple[Type[E], ...]],
|
||||
func: Callable[..., 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
|
||||
) -> Union["RaisesContext[E]", _pytest._code.ExceptionInfo[E]]:
|
||||
r"""Assert that a code block/function call raises ``expected_exception``
|
||||
or raise a failure exception otherwise.
|
||||
r"""Assert that a code block/function call raises an exception.
|
||||
|
||||
: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,
|
||||
or a regular expression object, that is tested against the string
|
||||
representation of the exception using :py:func:`re.search`. To match a literal
|
||||
string that may contain :std:ref:`special characters <re-syntax>`, the pattern can
|
||||
first be escaped with :py:func:`re.escape`.
|
||||
representation of the exception using :func:`re.search`.
|
||||
|
||||
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,
|
||||
and passed through to the function otherwise.
|
||||
|
|
|
@ -9,7 +9,6 @@ from typing import Generator
|
|||
from typing import Iterator
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
from typing import overload
|
||||
from typing import Pattern
|
||||
from typing import Tuple
|
||||
from typing import Type
|
||||
|
@ -17,6 +16,7 @@ from typing import TypeVar
|
|||
from typing import Union
|
||||
|
||||
from _pytest.compat import final
|
||||
from _pytest.compat import overload
|
||||
from _pytest.deprecated import check_ispytest
|
||||
from _pytest.deprecated import WARNS_NONE_ARG
|
||||
from _pytest.fixtures import fixture
|
||||
|
@ -47,11 +47,13 @@ def deprecated_call(
|
|||
|
||||
|
||||
@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
|
||||
) -> Union["WarningsRecorder", Any]:
|
||||
"""Assert that code produces a ``DeprecationWarning`` or ``PendingDeprecationWarning``.
|
||||
|
@ -93,7 +95,7 @@ def warns(
|
|||
|
||||
|
||||
@overload
|
||||
def warns(
|
||||
def warns( # noqa: F811
|
||||
expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]],
|
||||
func: Callable[..., T],
|
||||
*args: Any,
|
||||
|
@ -102,7 +104,7 @@ def warns(
|
|||
...
|
||||
|
||||
|
||||
def warns(
|
||||
def warns( # noqa: F811
|
||||
expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]] = Warning,
|
||||
*args: Any,
|
||||
match: Optional[Union[str, Pattern[str]]] = None,
|
||||
|
@ -110,15 +112,15 @@ def warns(
|
|||
) -> Union["WarningsChecker", Any]:
|
||||
r"""Assert that code raises a particular class of warning.
|
||||
|
||||
Specifically, the parameter ``expected_warning`` can be a warning class or
|
||||
sequence of warning classes, and the code inside the ``with`` block must issue a warning of that class or
|
||||
classes.
|
||||
Specifically, the parameter ``expected_warning`` can be a warning class or sequence
|
||||
of warning classes, and the code inside the ``with`` block must issue at least one
|
||||
warning of that class or classes.
|
||||
|
||||
This helper produces a list of :class:`warnings.WarningMessage` objects,
|
||||
one for each warning raised.
|
||||
This helper produces a list of :class:`warnings.WarningMessage` objects, one for
|
||||
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
|
||||
:func:`pytest.raises` can be used::
|
||||
This function can be used as a context manager, which will capture all the raised
|
||||
warnings inside it::
|
||||
|
||||
>>> import pytest
|
||||
>>> with pytest.warns(RuntimeWarning):
|
||||
|
@ -139,6 +141,14 @@ def warns(
|
|||
...
|
||||
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
|
||||
if not args:
|
||||
|
|
|
@ -276,7 +276,7 @@ class TestReport(BaseReport):
|
|||
|
||||
#: A name -> value dictionary containing all keywords and
|
||||
#: markers associated with a test invocation.
|
||||
self.keywords = keywords
|
||||
self.keywords: Mapping[str, Any] = keywords
|
||||
|
||||
#: Test outcome, always one of "passed", "failed", "skipped".
|
||||
self.outcome = outcome
|
||||
|
@ -298,7 +298,7 @@ class TestReport(BaseReport):
|
|||
self.sections = list(sections)
|
||||
|
||||
#: Time it took to run just the test.
|
||||
self.duration = duration
|
||||
self.duration: float = duration
|
||||
|
||||
self.__dict__.update(extra)
|
||||
|
||||
|
@ -309,7 +309,11 @@ class TestReport(BaseReport):
|
|||
|
||||
@classmethod
|
||||
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
|
||||
# Remove "collect" from the Literal type -- only for collection calls.
|
||||
assert when != "collect"
|
||||
|
|
|
@ -100,7 +100,11 @@ class TempPathFactory:
|
|||
return p
|
||||
|
||||
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:
|
||||
return self._basetemp
|
||||
|
||||
|
|
|
@ -1470,3 +1470,90 @@ def test_no_recursion_index_on_recursion_error():
|
|||
with pytest.raises(RuntimeError) as excinfo:
|
||||
RecursionDepthError().trigger
|
||||
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)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
anyio[curio,trio]==3.6.1
|
||||
django==4.0.6
|
||||
pytest-asyncio==0.18.3
|
||||
django==4.1
|
||||
pytest-asyncio==0.19.0
|
||||
pytest-bdd==6.0.1
|
||||
pytest-cov==3.0.0
|
||||
pytest-django==4.5.2
|
||||
|
|
|
@ -1625,6 +1625,28 @@ def test_escaped_skipreason_issue3533(
|
|||
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
|
||||
def test_logging_passing_tests_disabled_does_not_log_test_output(
|
||||
pytester: Pytester, run_and_parse: RunAndParse, xunit_family: str
|
||||
|
|
5
tox.ini
5
tox.ini
|
@ -17,6 +17,10 @@ envlist =
|
|||
docs
|
||||
docs-checklinks
|
||||
|
||||
# checks that 3.11 native ExceptionGroup works with exceptiongroup
|
||||
# not included in CI.
|
||||
py311-exceptiongroup
|
||||
|
||||
|
||||
|
||||
[testenv]
|
||||
|
@ -46,6 +50,7 @@ setenv =
|
|||
extras = testing
|
||||
deps =
|
||||
doctesting: PyYAML
|
||||
exceptiongroup: exceptiongroup>=1.0.0rc8
|
||||
numpy: numpy>=1.19.4
|
||||
pexpect: pexpect>=4.8.0
|
||||
pluggymain: pluggy @ git+https://github.com/pytest-dev/pluggy.git
|
||||
|
|
Loading…
Reference in New Issue