Merge branch 'pytest-dev:main' into issue-11037

This commit is contained in:
OlegP-andrew 2023-12-06 19:12:08 -05:00 committed by GitHub
commit ebe2257919
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 944 additions and 578 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -230,6 +230,8 @@ def assertrepr_compare(
if not explanation:
return None
if explanation[0] != "":
explanation = [""] + explanation
return [summary] + explanation
@ -318,18 +320,6 @@ def _diff_text(left: str, right: str, verbose: int = 0) -> List[str]:
return explanation
def _surrounding_parens_on_own_lines(lines: List[str]) -> None:
"""Move opening/closing parenthesis/bracket to own lines."""
opening = lines[0][:1]
if opening in ["(", "[", "{"]:
lines[0] = " " + lines[0][1:]
lines[:] = [opening] + lines
closing = lines[-1][-1:]
if closing in [")", "]", "}"]:
lines[-1] = lines[-1][:-1] + ","
lines[:] = lines + [closing]
def _compare_eq_iterable(
left: Iterable[Any],
right: Iterable[Any],
@ -341,22 +331,10 @@ def _compare_eq_iterable(
# dynamic import to speedup pytest
import difflib
left_formatting = pprint.pformat(left).splitlines()
right_formatting = pprint.pformat(right).splitlines()
left_formatting = PrettyPrinter().pformat(left).splitlines()
right_formatting = PrettyPrinter().pformat(right).splitlines()
# Re-format for different output lengths.
lines_left = len(left_formatting)
lines_right = len(right_formatting)
if lines_left != lines_right:
printer = PrettyPrinter()
left_formatting = printer.pformat(left).splitlines()
right_formatting = printer.pformat(right).splitlines()
if lines_left > 1 or lines_right > 1:
_surrounding_parens_on_own_lines(left_formatting)
_surrounding_parens_on_own_lines(right_formatting)
explanation = ["Full diff:"]
explanation = ["", "Full diff:"]
# "right" is the expected base against which we compare "left",
# see https://github.com/pytest-dev/pytest/issues/3333
explanation.extend(

View File

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

View File

@ -564,6 +564,22 @@ class LogCaptureFixture:
self.handler.setLevel(handler_orig_level)
logging.disable(original_disable_level)
@contextmanager
def filtering(self, filter_: logging.Filter) -> Generator[None, None, None]:
"""Context manager that temporarily adds the given filter to the caplog's
:meth:`handler` for the 'with' statement block, and removes that filter at the
end of the block.
:param filter_: A custom :class:`logging.Filter` object.
.. versionadded:: 7.5
"""
self.handler.addFilter(filter_)
try:
yield
finally:
self.handler.removeFilter(filter_)
@fixture
def caplog(request: FixtureRequest) -> Generator[LogCaptureFixture, None, None]:

View File

@ -121,13 +121,18 @@ def pytest_configure(config: Config) -> None:
class LsofFdLeakChecker:
def get_open_files(self) -> List[Tuple[str, str]]:
if sys.version_info >= (3, 11):
# New in Python 3.11, ignores utf-8 mode
encoding = locale.getencoding()
else:
encoding = locale.getpreferredencoding(False)
out = subprocess.run(
("lsof", "-Ffn0", "-p", str(os.getpid())),
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL,
check=True,
text=True,
encoding=locale.getpreferredencoding(False),
encoding=encoding,
).stdout
def isopen(line: str) -> bool:

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -392,6 +392,7 @@ class TestAssert_reprcompare:
def test_text_diff(self) -> None:
assert callequal("spam", "eggs") == [
"'spam' == 'eggs'",
"",
"- eggs",
"+ spam",
]
@ -399,7 +400,7 @@ class TestAssert_reprcompare:
def test_text_skipping(self) -> None:
lines = callequal("a" * 50 + "spam", "a" * 50 + "eggs")
assert lines is not None
assert "Skipping" in lines[1]
assert "Skipping" in lines[2]
for line in lines:
assert "a" * 50 not in line
@ -423,6 +424,7 @@ class TestAssert_reprcompare:
assert diff == [
"b'spam' == b'eggs'",
"",
"At index 0 diff: b's' != b'e'",
"Use -v to get more diff",
]
@ -432,7 +434,9 @@ class TestAssert_reprcompare:
diff = callequal(b"spam", b"eggs", verbose=1)
assert diff == [
"b'spam' == b'eggs'",
"",
"At index 0 diff: b's' != b'e'",
"",
"Full diff:",
"- b'eggs'",
"+ b'spam'",
@ -451,10 +455,13 @@ class TestAssert_reprcompare:
[0, 2],
"""
Full diff:
- [0, 2]
[
0,
- 2,
? ^
+ [0, 1]
+ 1,
? ^
]
""",
id="lists",
),
@ -463,10 +470,12 @@ class TestAssert_reprcompare:
{0: 2},
"""
Full diff:
- {0: 2}
{
- 0: 2,
? ^
+ {0: 1}
+ 0: 1,
? ^
}
""",
id="dicts",
),
@ -475,10 +484,13 @@ class TestAssert_reprcompare:
{0, 2},
"""
Full diff:
- {0, 2}
{
0,
- 2,
? ^
+ {0, 1}
+ 1,
? ^
}
""",
id="sets",
),
@ -501,6 +513,7 @@ class TestAssert_reprcompare:
expl = callequal([1, 2], [10, 2], verbose=-1)
assert expl == [
"[1, 2] == [10, 2]",
"",
"At index 0 diff: 1 != 10",
"Use -v to get more diff",
]
@ -539,7 +552,9 @@ class TestAssert_reprcompare:
diff = callequal(l1, l2, verbose=True)
assert diff == [
"['a', 'b', 'c'] == ['a', 'b', 'c...dddddddddddd']",
"",
"Right contains one more item: '" + long_d + "'",
"",
"Full diff:",
" [",
" 'a',",
@ -552,7 +567,9 @@ class TestAssert_reprcompare:
diff = callequal(l2, l1, verbose=True)
assert diff == [
"['a', 'b', 'c...dddddddddddd'] == ['a', 'b', 'c']",
"",
"Left contains one more item: '" + long_d + "'",
"",
"Full diff:",
" [",
" 'a',",
@ -571,7 +588,9 @@ class TestAssert_reprcompare:
diff = callequal(l1, l2, verbose=True)
assert diff == [
"['aaaaaaaaaaa...cccccccccccc'] == ['bbbbbbbbbbb...aaaaaaaaaaaa']",
"",
"At index 0 diff: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' != 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'",
"",
"Full diff:",
" [",
"+ 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',",
@ -588,8 +607,10 @@ class TestAssert_reprcompare:
diff = callequal(l1, l2, verbose=True)
assert diff == [
"['a', 'aaaaaa...aaaaaaa', ...] == ['should not get wrapped']",
"",
"At index 0 diff: 'a' != 'should not get wrapped'",
"Left contains 7 more items, first extra item: 'aaaaaaaaaa'",
"",
"Full diff:",
" [",
"- 'should not get wrapped',",
@ -611,30 +632,44 @@ class TestAssert_reprcompare:
diff = callequal(d1, d2, verbose=True)
assert diff == [
"{'common': 1,...1, 'env2': 2}} == {'common': 1,...: {'env1': 1}}",
"",
"Omitting 1 identical items, use -vv to show",
"Differing items:",
"{'env': {'env1': 1, 'env2': 2}} != {'env': {'env1': 1}}",
"",
"Full diff:",
"- {'common': 1, 'env': {'env1': 1}}",
"+ {'common': 1, 'env': {'env1': 1, 'env2': 2}}",
"? +++++++++++",
" {",
" 'common': 1,",
" 'env': {",
" 'env1': 1,",
"+ 'env2': 2,",
" },",
" }",
]
long_a = "a" * 80
sub = {"long_a": long_a, "sub1": {"long_a": "substring that gets wrapped " * 2}}
sub = {"long_a": long_a, "sub1": {"long_a": "substring that gets wrapped " * 3}}
d1 = {"env": {"sub": sub}}
d2 = {"env": {"sub": sub}, "new": 1}
diff = callequal(d1, d2, verbose=True)
assert diff == [
"{'env': {'sub... wrapped '}}}} == {'env': {'sub...}}}, 'new': 1}",
"",
"Omitting 1 identical items, use -vv to show",
"Right contains 1 more item:",
"{'new': 1}",
"",
"Full diff:",
" {",
" 'env': {'sub': {'long_a': '" + long_a + "',",
" 'sub1': {'long_a': 'substring that gets wrapped substring '",
" 'that gets wrapped '}}},",
" 'env': {",
" 'sub': {",
f" 'long_a': '{long_a}',",
" 'sub1': {",
" 'long_a': 'substring that gets wrapped substring that gets wrapped '",
" 'substring that gets wrapped ',",
" },",
" },",
" },",
"- 'new': 1,",
" }",
]
@ -647,7 +682,7 @@ class TestAssert_reprcompare:
def test_dict_omitting(self) -> None:
lines = callequal({"a": 0, "b": 1}, {"a": 1, "b": 1})
assert lines is not None
assert lines[1].startswith("Omitting 1 identical item")
assert lines[2].startswith("Omitting 1 identical item")
assert "Common items" not in lines
for line in lines[1:]:
assert "b" not in line
@ -656,60 +691,109 @@ class TestAssert_reprcompare:
"""Ensure differing items are visible for verbosity=1 (#1512)."""
lines = callequal({"a": 0, "b": 1}, {"a": 1, "b": 1}, verbose=1)
assert lines is not None
assert lines[1].startswith("Omitting 1 identical item")
assert lines[2].startswith("Differing items")
assert lines[3] == "{'a': 0} != {'a': 1}"
assert lines[1] == ""
assert lines[2].startswith("Omitting 1 identical item")
assert lines[3].startswith("Differing items")
assert lines[4] == "{'a': 0} != {'a': 1}"
assert "Common items" not in lines
def test_dict_omitting_with_verbosity_2(self) -> None:
lines = callequal({"a": 0, "b": 1}, {"a": 1, "b": 1}, verbose=2)
assert lines is not None
assert lines[1].startswith("Common items:")
assert "Omitting" not in lines[1]
assert lines[2] == "{'b': 1}"
assert lines[2].startswith("Common items:")
assert "Omitting" not in lines[2]
assert lines[3] == "{'b': 1}"
def test_dict_different_items(self) -> None:
lines = callequal({"a": 0}, {"b": 1, "c": 2}, verbose=2)
assert lines == [
"{'a': 0} == {'b': 1, 'c': 2}",
"",
"Left contains 1 more item:",
"{'a': 0}",
"Right contains 2 more items:",
"{'b': 1, 'c': 2}",
"",
"Full diff:",
"- {'b': 1, 'c': 2}",
"+ {'a': 0}",
" {",
"- 'b': 1,",
"? ^ ^",
"+ 'a': 0,",
"? ^ ^",
"- 'c': 2,",
" }",
]
lines = callequal({"b": 1, "c": 2}, {"a": 0}, verbose=2)
assert lines == [
"{'b': 1, 'c': 2} == {'a': 0}",
"",
"Left contains 2 more items:",
"{'b': 1, 'c': 2}",
"Right contains 1 more item:",
"{'a': 0}",
"",
"Full diff:",
"- {'a': 0}",
"+ {'b': 1, 'c': 2}",
" {",
"- 'a': 0,",
"? ^ ^",
"+ 'b': 1,",
"? ^ ^",
"+ 'c': 2,",
" }",
]
def test_sequence_different_items(self) -> None:
lines = callequal((1, 2), (3, 4, 5), verbose=2)
assert lines == [
"(1, 2) == (3, 4, 5)",
"",
"At index 0 diff: 1 != 3",
"Right contains one more item: 5",
"",
"Full diff:",
"- (3, 4, 5)",
"+ (1, 2)",
" (",
"- 3,",
"? ^",
"+ 1,",
"? ^",
"- 4,",
"? ^",
"+ 2,",
"? ^",
"- 5,",
" )",
]
lines = callequal((1, 2, 3), (4,), verbose=2)
assert lines == [
"(1, 2, 3) == (4,)",
"",
"At index 0 diff: 1 != 4",
"Left contains 2 more items, first extra item: 2",
"",
"Full diff:",
"- (4,)",
"+ (1, 2, 3)",
" (",
"- 4,",
"? ^",
"+ 1,",
"? ^",
"+ 2,",
"+ 3,",
" )",
]
lines = callequal((1, 2, 3), (1, 20, 3), verbose=2)
assert lines == [
"(1, 2, 3) == (1, 20, 3)",
"",
"At index 1 diff: 2 != 20",
"",
"Full diff:",
" (",
" 1,",
"- 20,",
"? -",
"+ 2,",
" 3,",
" )",
]
def test_set(self) -> None:
@ -767,7 +851,7 @@ class TestAssert_reprcompare:
assert expl is not None
assert expl[0].startswith("{} == <[ValueError")
assert "raised in repr" in expl[0]
assert expl[1:] == [
assert expl[2:] == [
"(pytest_assertion plugin: representation of details failed:"
" {}:{}: ValueError: 42.".format(
__file__, A.__repr__.__code__.co_firstlineno + 1
@ -793,6 +877,7 @@ class TestAssert_reprcompare:
def test_unicode(self) -> None:
assert callequal("£€", "£") == [
"'£€' == '£'",
"",
"- £",
"+ £€",
]
@ -808,7 +893,7 @@ class TestAssert_reprcompare:
return "\xff"
expl = callequal(A(), "1")
assert expl == ["ÿ == '1'", "- 1"]
assert expl == ["ÿ == '1'", "", "- 1"]
def test_format_nonascii_explanation(self) -> None:
assert util.format_explanation("λ")
@ -831,6 +916,7 @@ class TestAssert_reprcompare:
expl = callequal(left, right)
assert expl == [
r"'hyv\xe4' == 'hyva\u0308'",
"",
f"- {str(right)}",
f"+ {str(left)}",
]
@ -838,6 +924,7 @@ class TestAssert_reprcompare:
expl = callequal(left, right, verbose=2)
assert expl == [
r"'hyv\xe4' == 'hyva\u0308'",
"",
f"- {str(right)}",
f"+ {str(left)}",
]
@ -1126,6 +1213,7 @@ class TestAssert_reprcompare_namedtuple:
# Because the types are different, uses the generic sequence matcher.
assert lines == [
"NT1(a=1, b='b') == NT2(a=2, b='b')",
"",
"At index 0 diff: 1 != 2",
"Use -v to get more diff",
]
@ -1313,7 +1401,7 @@ class TestTruncateExplanation:
line_count = 7
line_len = 100
expected_truncated_lines = 1
expected_truncated_lines = 2
pytester.makepyfile(
r"""
def test_many_lines():
@ -1333,8 +1421,7 @@ class TestTruncateExplanation:
[
"*+ 1*",
"*+ 3*",
"*+ 5*",
"*truncated (%d line hidden)*use*-vv*" % expected_truncated_lines,
"*truncated (%d lines hidden)*use*-vv*" % expected_truncated_lines,
]
)
@ -1377,6 +1464,7 @@ def test_rewritten(pytester: Pytester) -> None:
def test_reprcompare_notin() -> None:
assert callop("not in", "foo", "aaafoobbb") == [
"'foo' not in 'aaafoobbb'",
"",
"'foo' is contained here:",
" aaafoobbb",
"? +++",
@ -1386,6 +1474,7 @@ def test_reprcompare_notin() -> None:
def test_reprcompare_whitespaces() -> None:
assert callequal("\r\n", "\n") == [
r"'\r\n' == '\n'",
"",
r"Strings contain only whitespace, escaping them using repr()",
r"- '\n'",
r"+ '\r\n'",
@ -1844,8 +1933,8 @@ def test_reprcompare_verbose_long() -> None:
assert [0, 1] == [0, 2]
""",
[
"{bold}{red}E {light-red}- [0, 2]{hl-reset}{endline}{reset}",
"{bold}{red}E {light-green}+ [0, 1]{hl-reset}{endline}{reset}",
"{bold}{red}E {light-red}- 2,{hl-reset}{endline}{reset}",
"{bold}{red}E {light-green}+ 1,{hl-reset}{endline}{reset}",
],
),
(
@ -1917,14 +2006,32 @@ def test_fine_grained_assertion_verbosity(pytester: Pytester):
f"{p.name} .FFF [100%]",
"E At index 2 diff: 'grapes' != 'orange'",
"E Full diff:",
"E - ['banana', 'apple', 'orange', 'melon', 'kiwi']",
"E [",
"E 'banana',",
"E 'apple',",
"E - 'orange',",
"E ? ^ ^^",
"E + ['banana', 'apple', 'grapes', 'melon', 'kiwi']",
"E + 'grapes',",
"E ? ^ ^ +",
"E 'melon',",
"E 'kiwi',",
"E ]",
"E Full diff:",
"E - {'0': 0, '10': 10, '20': 20, '30': 30, '40': 40}",
"E ? - - - - - - - -",
"E + {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4}",
"E {",
"E '0': 0,",
"E - '10': 10,",
"E ? - -",
"E + '1': 1,",
"E - '20': 20,",
"E ? - -",
"E + '2': 2,",
"E - '30': 30,",
"E ? - -",
"E + '3': 3,",
"E - '40': 40,",
"E ? - -",
"E + '4': 4,",
"E }",
f"E AssertionError: assert 'hello world' in '{long_text}'",
]
)

View File

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

View File

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

View File

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

View File

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