Merge branch 'main' into patch-1

This commit is contained in:
Zac Hatfield-Dodds 2023-07-04 10:17:06 -07:00 committed by GitHub
commit cb732f7f49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
65 changed files with 659 additions and 570 deletions

View File

@ -13,39 +13,53 @@ on:
permissions: {}
jobs:
deploy:
if: github.repository == 'pytest-dev/pytest'
build:
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: write
timeout-minutes: 10
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
persist-credentials: false
- name: Build and Check Package
uses: hynek/build-and-inspect-python-package@v1.5
deploy:
if: github.repository == 'pytest-dev/pytest'
needs: [build]
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
id-token: write
steps:
- name: Download Package
uses: actions/download-artifact@v3
with:
name: Packages
path: dist
- name: Publish package to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.pypi_token }}
uses: pypa/gh-action-pypi-publish@v1.8.5
release-notes:
# todo: generate the content in the build job
# the goal being of using a github action script to push the release data
# after success instead of creating a complete python/tox env
needs: [deploy]
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: write
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.7"
python-version: "3.11"
- name: Install tox
run: |

View File

@ -37,25 +37,23 @@ jobs:
fail-fast: false
matrix:
name: [
"windows-py37",
"windows-py37-pluggy",
"windows-py38",
"windows-py38-pluggy",
"windows-py39",
"windows-py310",
"windows-py311",
"windows-py312",
"ubuntu-py37",
"ubuntu-py37-pluggy",
"ubuntu-py37-freeze",
"ubuntu-py38",
"ubuntu-py38-pluggy",
"ubuntu-py38-freeze",
"ubuntu-py39",
"ubuntu-py310",
"ubuntu-py311",
"ubuntu-py312",
"ubuntu-pypy3",
"macos-py37",
"macos-py38",
"macos-py39",
"macos-py310",
"macos-py312",
@ -66,19 +64,15 @@ jobs:
]
include:
- name: "windows-py37"
python: "3.7"
os: windows-latest
tox_env: "py37-numpy"
- name: "windows-py37-pluggy"
python: "3.7"
os: windows-latest
tox_env: "py37-pluggymain-pylib-xdist"
- name: "windows-py38"
python: "3.8"
os: windows-latest
tox_env: "py38-unittestextras"
use_coverage: true
- name: "windows-py38-pluggy"
python: "3.8"
os: windows-latest
tox_env: "py38-pluggymain-pylib-xdist"
- name: "windows-py39"
python: "3.9"
os: windows-latest
@ -96,23 +90,19 @@ jobs:
os: windows-latest
tox_env: "py312"
- name: "ubuntu-py37"
python: "3.7"
os: ubuntu-latest
tox_env: "py37-lsof-numpy-pexpect"
use_coverage: true
- name: "ubuntu-py37-pluggy"
python: "3.7"
os: ubuntu-latest
tox_env: "py37-pluggymain-pylib-xdist"
- name: "ubuntu-py37-freeze"
python: "3.7"
os: ubuntu-latest
tox_env: "py37-freeze"
- name: "ubuntu-py38"
python: "3.8"
os: ubuntu-latest
tox_env: "py38-xdist"
tox_env: "py38-lsof-numpy-pexpect"
use_coverage: true
- name: "ubuntu-py38-pluggy"
python: "3.8"
os: ubuntu-latest
tox_env: "py38-pluggymain-pylib-xdist"
- name: "ubuntu-py38-freeze"
python: "3.8"
os: ubuntu-latest
tox_env: "py38-freeze"
- name: "ubuntu-py39"
python: "3.9"
os: ubuntu-latest
@ -132,14 +122,14 @@ jobs:
tox_env: "py312"
use_coverage: true
- name: "ubuntu-pypy3"
python: "pypy-3.7"
python: "pypy-3.8"
os: ubuntu-latest
tox_env: "pypy3-xdist"
- name: "macos-py37"
python: "3.7"
- name: "macos-py38"
python: "3.8"
os: macos-latest
tox_env: "py37-xdist"
tox_env: "py38-xdist"
- name: "macos-py39"
python: "3.9"
os: macos-latest
@ -160,11 +150,11 @@ jobs:
tox_env: "plugins"
- name: "docs"
python: "3.7"
python: "3.8"
os: ubuntu-latest
tox_env: "docs"
- name: "doctesting"
python: "3.7"
python: "3.8"
os: ubuntu-latest
tox_env: "doctesting"
use_coverage: true

View File

@ -21,7 +21,7 @@ repos:
exclude: _pytest/(debugging|hookspec).py
language_version: python3
- repo: https://github.com/PyCQA/autoflake
rev: v2.1.1
rev: v2.2.0
hooks:
- id: autoflake
name: autoflake
@ -40,14 +40,14 @@ repos:
rev: v3.10.0
hooks:
- id: reorder-python-imports
args: ['--application-directories=.:src', --py37-plus]
args: ['--application-directories=.:src', --py38-plus]
- repo: https://github.com/asottile/pyupgrade
rev: v3.7.0
rev: v3.8.0
hooks:
- id: pyupgrade
args: [--py37-plus]
args: [--py38-plus]
- repo: https://github.com/asottile/setup-cfg-fmt
rev: v2.3.0
rev: v2.4.0
hooks:
- id: setup-cfg-fmt
args: ["--max-py-version=3.12", "--include-version-classifiers"]
@ -56,7 +56,7 @@ repos:
hooks:
- id: python-use-type-annotations
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.3.0
rev: v1.4.1
hooks:
- id: mypy
files: ^(src/|testing/)

View File

@ -11,6 +11,7 @@ Adam Johnson
Adam Stewart
Adam Uhlir
Ahn Ki-Wook
Akhilesh Ramakrishnan
Akiomi Kamakura
Alan Velasco
Alessio Izzo
@ -129,6 +130,7 @@ Eric Hunsberger
Eric Liu
Eric Siegerman
Erik Aronesty
Erik Hasse
Erik M. Bray
Evan Kepner
Evgeny Seliverstov
@ -310,6 +312,7 @@ Raphael Pierzina
Rafal Semik
Raquel Alegre
Ravi Chandra
Reagan Lee
Robert Holt
Roberto Aldera
Roberto Polli

View File

@ -201,7 +201,7 @@ Short version
#. Follow **PEP-8** for naming and `black <https://github.com/psf/black>`_ for formatting.
#. Tests are run using ``tox``::
tox -e linting,py37
tox -e linting,py39
The test environments above are usually enough to cover most cases locally.
@ -272,24 +272,24 @@ Here is a simple overview, with pytest-specific bits:
#. Run all the tests
You need to have Python 3.7 available in your system. Now
You need to have Python 3.8 or later available in your system. Now
running tests is as simple as issuing this command::
$ tox -e linting,py37
$ tox -e linting,py39
This command will run tests via the "tox" tool against Python 3.7
This command will run tests via the "tox" tool against Python 3.9
and also perform "lint" coding-style checks.
#. You can now edit your local working copy and run the tests again as necessary. Please follow PEP-8 for naming.
You can pass different options to ``tox``. For example, to run tests on Python 3.7 and pass options to pytest
You can pass different options to ``tox``. For example, to run tests on Python 3.9 and pass options to pytest
(e.g. enter pdb on failure) to pytest you can do::
$ tox -e py37 -- --pdb
$ tox -e py39 -- --pdb
Or to only run tests in a particular test module on Python 3.7::
Or to only run tests in a particular test module on Python 3.9::
$ tox -e py37 -- testing/test_config.py
$ tox -e py39 -- testing/test_config.py
When committing, ``pre-commit`` will re-format the files if necessary.

View File

@ -100,7 +100,7 @@ Features
- Can run `unittest <https://docs.pytest.org/en/stable/how-to/unittest.html>`_ (or trial),
`nose <https://docs.pytest.org/en/stable/how-to/nose.html>`_ test suites out of the box
- Python 3.7+ or PyPy3
- Python 3.8+ or PyPy3
- Rich plugin architecture, with over 850+ `external plugins <https://docs.pytest.org/en/latest/reference/plugin_list.html>`_ and thriving community

View File

@ -0,0 +1,2 @@
Fixed that fake intermediate modules generated by ``--import-mode=importlib`` would not include the
child modules as attributes of the parent modules.

View File

@ -0,0 +1,2 @@
markers are now considered in the reverse mro order to ensure base class markers are considered first
this resolves a regression.

View File

@ -0,0 +1,2 @@
Fixed issue when using ``--import-mode=importlib`` together with ``--doctest-modules`` that caused modules
to be imported more than once, causing problems with modules that have import side effects.

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

@ -0,0 +1 @@
Added a warning about modifying the root logger during tests when using ``caplog``.

View File

@ -0,0 +1,2 @@
Dropped support for Python 3.7, which `reached end-of-life on 2023-06-27
<https://devguide.python.org/versions/>`__.

View File

@ -0,0 +1 @@
``pytest.warns`` and similar functions now capture warnings when an exception is raised inside a ``with`` block.

View File

@ -0,0 +1,7 @@
:func:`pytest.warns <warns>` now re-emits unmatched warnings when the context
closes -- previously it would consume all warnings, hiding those that were not
matched by the function.
While this is a new feature, we decided to announce this as a breaking change
because many test suites are configured to error-out on warnings, and will
therefore fail on the newly-re-emitted warnings.

View File

@ -87,6 +87,7 @@ Released pytest versions support all Python versions that are actively maintaine
============== ===================
pytest version min. Python version
============== ===================
8.0+ 3.8+
7.1+ 3.7+
6.2 - 7.0 3.6+
5.0 - 6.1 3.5+

View File

@ -15,12 +15,10 @@
#
# The full version, including alpha/beta/rc tags.
# The short X.Y version.
import ast
import os
import shutil
import sys
from textwrap import dedent
from typing import List
from typing import TYPE_CHECKING
from _pytest import __version__ as version
@ -451,25 +449,6 @@ def setup(app: "sphinx.application.Sphinx") -> None:
configure_logging(app)
# Make Sphinx mark classes with "final" when decorated with @final.
# We need this because we import final from pytest._compat, not from
# typing (for Python < 3.8 compat), so Sphinx doesn't detect it.
# To keep things simple we accept any `@final` decorator.
# Ref: https://github.com/pytest-dev/pytest/pull/7780
import sphinx.pycode.ast
import sphinx.pycode.parser
original_is_final = sphinx.pycode.parser.VariableCommentPicker.is_final
def patched_is_final(self, decorators: List[ast.expr]) -> bool:
if original_is_final(self, decorators):
return True
return any(
sphinx.pycode.ast.unparse(decorator) == "final" for decorator in decorators
)
sphinx.pycode.parser.VariableCommentPicker.is_final = patched_is_final
# legacypath.py monkey-patches pytest.Testdir in. Import the file so
# that autodoc can discover references to it.
import _pytest.legacypath # noqa: F401

View File

@ -9,7 +9,7 @@ Get Started
Install ``pytest``
----------------------------------------
``pytest`` requires: Python 3.7+ or PyPy3.
``pytest`` requires: Python 3.8+ or PyPy3.
1. Run the following command in your command line:

View File

@ -172,6 +172,13 @@ the records for the ``setup`` and ``call`` stages during teardown like so:
The full API is available at :class:`pytest.LogCaptureFixture`.
.. warning::
The ``caplog`` fixture adds a handler to the root logger to capture logs. If the root logger is
modified during a test, for example with ``logging.config.dictConfig``, this handler may be
removed and cause no logs to be captured. To avoid this, ensure that any root logger configuration
only adds to the existing handlers.
.. _live_logs:

View File

@ -77,7 +77,7 @@ Features
- Can run :ref:`unittest <unittest>` (including trial) and :ref:`nose <noseintegration>` test suites out of the box
- Python 3.7+ or PyPy 3
- Python 3.8+ or PyPy 3
- Rich plugin architecture, with over 800+ :ref:`external plugins <plugin-list>` and thriving community

View File

@ -13,7 +13,7 @@ Packages classified as inactive are excluded.
creating a PDF, because otherwise the table gets far too wide for the
page.
This list contains 1267 plugins.
This list contains 1278 plugins.
.. only:: not latex
@ -36,12 +36,12 @@ This list contains 1267 plugins.
:pypi:`pytest-aiogram` May 06, 2023 N/A N/A
:pypi:`pytest-aiohttp` Pytest plugin for aiohttp support Feb 12, 2022 4 - Beta pytest (>=6.1.0)
:pypi:`pytest-aiohttp-client` Pytest \`client\` fixture for the Aiohttp Jan 10, 2023 N/A pytest (>=7.2.0,<8.0.0)
:pypi:`pytest-aiomoto` pytest-aiomoto Nov 09, 2022 N/A pytest (>=7.0,<8.0)
:pypi:`pytest-aiomoto` pytest-aiomoto Jun 24, 2023 N/A pytest (>=7.0,<8.0)
:pypi:`pytest-aioresponses` py.test integration for aioresponses Jul 29, 2021 4 - Beta pytest (>=3.5.0)
:pypi:`pytest-aioworkers` A plugin to test aioworkers project with pytest May 01, 2023 5 - Production/Stable pytest>=6.1.0
:pypi:`pytest-airflow` pytest support for airflow. Apr 03, 2019 3 - Alpha pytest (>=4.4.0)
:pypi:`pytest-airflow-utils` Nov 15, 2021 N/A N/A
:pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. May 23, 2023 N/A pytest (>=6.0)
:pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. Jun 27, 2023 N/A pytest (>=6.0)
:pypi:`pytest-allclose` Pytest fixture extending Numpy's allclose function Jul 30, 2019 5 - Production/Stable pytest
:pypi:`pytest-allure-adaptor` Plugin for py.test to generate allure xml reports Jan 10, 2018 N/A pytest (>=2.7.3)
:pypi:`pytest-allure-adaptor2` Plugin for py.test to generate allure xml reports Oct 14, 2020 N/A pytest (>=2.7.3)
@ -112,7 +112,7 @@ This list contains 1267 plugins.
:pypi:`pytest-base-url` pytest plugin for URL based testing Mar 27, 2022 5 - Production/Stable pytest (>=3.0.0,<8.0.0)
:pypi:`pytest-bdd` BDD for pytest Nov 08, 2022 6 - Mature pytest (>=6.2.0)
:pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0)
:pypi:`pytest-bdd-ng` BDD for pytest Oct 06, 2022 4 - Beta pytest (>=5.0)
:pypi:`pytest-bdd-ng` BDD for pytest Jul 01, 2023 4 - Beta pytest (>=5.0)
:pypi:`pytest-bdd-splinter` Common steps for pytest bdd and splinter integration Aug 12, 2019 5 - Production/Stable pytest (>=4.0.0)
:pypi:`pytest-bdd-web` A simple plugin to use with pytest Jan 02, 2020 4 - Beta pytest (>=3.5.0)
:pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A
@ -146,7 +146,7 @@ This list contains 1267 plugins.
:pypi:`pytest-browsermob-proxy` BrowserMob proxy plugin for py.test. Jun 11, 2013 4 - Beta N/A
:pypi:`pytest-browserstack-local` \`\`py.test\`\` plugin to run \`\`BrowserStackLocal\`\` in background. Feb 09, 2018 N/A N/A
:pypi:`pytest-budosystems` Budo Systems is a martial arts school management system. This module is the Budo Systems Pytest Plugin. May 07, 2023 3 - Alpha pytest
:pypi:`pytest-bug` Pytest plugin for marking tests as a bug Jan 29, 2023 5 - Production/Stable pytest (>=6.2.0)
:pypi:`pytest-bug` Pytest plugin for marking tests as a bug Jun 23, 2023 5 - Production/Stable pytest (>=7.1.0)
:pypi:`pytest-bugtong-tag` pytest-bugtong-tag is a plugin for pytest Jan 16, 2022 N/A N/A
:pypi:`pytest-bugzilla` py.test bugzilla integration plugin May 05, 2010 4 - Beta N/A
:pypi:`pytest-bugzilla-notifier` A plugin that allows you to execute create, update, and read information from BugZilla bugs Jun 15, 2018 4 - Beta pytest (>=2.9.2)
@ -213,26 +213,27 @@ This list contains 1267 plugins.
:pypi:`pytest-colordots` Colorizes the progress indicators Oct 06, 2017 5 - Production/Stable N/A
:pypi:`pytest-commander` An interactive GUI test runner for PyTest Aug 17, 2021 N/A pytest (<7.0.0,>=6.2.4)
:pypi:`pytest-common-subject` pytest framework for testing different aspects of a common method May 15, 2022 N/A pytest (>=3.6,<8)
:pypi:`pytest-compare` pytest plugin for comparing call arguments. Mar 30, 2023 5 - Production/Stable N/A
:pypi:`pytest-compare` pytest plugin for comparing call arguments. Jun 22, 2023 5 - Production/Stable N/A
:pypi:`pytest-concurrent` Concurrently execute test cases with multithread, multiprocess and gevent Jan 12, 2019 4 - Beta pytest (>=3.1.1)
:pypi:`pytest-config` Base configurations and utilities for developing your Python project test suite with pytest. Nov 07, 2014 5 - Production/Stable N/A
:pypi:`pytest-confluence-report` Package stands for pytest plugin to upload results into Confluence page. Apr 17, 2022 N/A N/A
:pypi:`pytest-console-scripts` Pytest plugin for testing console scripts May 31, 2023 4 - Beta pytest (>=4.0.0)
:pypi:`pytest-consul` pytest plugin with fixtures for testing consul aware apps Nov 24, 2018 3 - Alpha pytest
:pypi:`pytest-container` Pytest fixtures for writing container based tests Mar 21, 2023 4 - Beta pytest (>=3.10)
:pypi:`pytest-container` Pytest fixtures for writing container based tests Jun 19, 2023 4 - Beta pytest (>=3.10)
:pypi:`pytest-contextfixture` Define pytest fixtures as context managers. Mar 12, 2013 4 - Beta N/A
:pypi:`pytest-contexts` A plugin to run tests written with the Contexts framework using pytest May 19, 2021 4 - Beta N/A
:pypi:`pytest-cookies` The pytest plugin for your Cookiecutter templates. 🍪 Mar 22, 2023 5 - Production/Stable pytest (>=3.9.0)
:pypi:`pytest-copier` A pytest plugin to help testing Copier templates Jun 23, 2023 4 - Beta pytest>=7.1.2
:pypi:`pytest-couchdbkit` py.test extension for per-test couchdb databases using couchdbkit Apr 17, 2012 N/A N/A
:pypi:`pytest-count` count erros and send email Jan 12, 2018 4 - Beta N/A
:pypi:`pytest-cov` Pytest plugin for measuring coverage. May 24, 2023 5 - Production/Stable pytest (>=4.6)
:pypi:`pytest-cover` Pytest plugin for measuring coverage. Forked from \`pytest-cov\`. Aug 01, 2015 5 - Production/Stable N/A
:pypi:`pytest-coverage` Jun 17, 2015 N/A N/A
:pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jan 04, 2021 4 - Beta pytest (>=6.1.0)
:pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jun 28, 2023 4 - Beta N/A
:pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0)
:pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev'
:pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Jan 30, 2023 5 - Production/Stable pytest (>=7.0)
:pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Jun 14, 2023 N/A N/A
:pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Jun 19, 2023 N/A N/A
:pypi:`pytest-cqase` Custom qase pytest plugin Aug 22, 2022 N/A pytest (>=7.1.2,<8.0.0)
:pypi:`pytest-cram` Run cram tests with pytest. Aug 08, 2020 N/A N/A
:pypi:`pytest-crate` Manages CrateDB instances during your integration tests May 28, 2019 3 - Alpha pytest (>=4.0)
@ -241,7 +242,7 @@ This list contains 1267 plugins.
:pypi:`pytest-cricri` A Cricri plugin for pytest. Jan 27, 2018 N/A pytest
:pypi:`pytest-crontab` add crontab task in crontab Dec 09, 2019 N/A N/A
:pypi:`pytest-csv` CSV output for pytest. Apr 22, 2021 N/A pytest (>=6.0)
:pypi:`pytest-csv-params` Pytest plugin for Test Case Parametrization with CSV files Aug 28, 2022 5 - Production/Stable pytest (>=7.1.2,<8.0.0)
:pypi:`pytest-csv-params` Pytest plugin for Test Case Parametrization with CSV files Jul 01, 2023 5 - Production/Stable pytest (>=7.4.0,<8.0.0)
:pypi:`pytest-curio` Pytest support for curio. Oct 07, 2020 N/A N/A
:pypi:`pytest-curl-report` pytest plugin to generate curl command line report Dec 11, 2016 4 - Beta N/A
:pypi:`pytest-custom-concurrency` Custom grouping concurrence for pytest Feb 08, 2021 N/A N/A
@ -296,6 +297,7 @@ This list contains 1267 plugins.
:pypi:`pytest-diffeo` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A
:pypi:`pytest-diff-selector` Get tests affected by code changes (using git) Feb 24, 2022 4 - Beta pytest (>=6.2.2) ; extra == 'all'
:pypi:`pytest-difido` PyTest plugin for generating Difido reports Oct 23, 2022 4 - Beta pytest (>=4.0.0)
:pypi:`pytest-dir-equal` pytest-dir-equals is a pytest plugin providing helpers to assert directories equality allowing golden testing Jun 23, 2023 4 - Beta pytest>=7.1.2
:pypi:`pytest-disable` pytest plugin to disable a test and skip it from testrun Sep 10, 2015 4 - Beta N/A
:pypi:`pytest-disable-plugin` Disable plugins per test Feb 28, 2019 4 - Beta pytest (>=3.5.0)
:pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. Feb 05, 2023 4 - Beta pytest (!=6.0.0,<8,>=3.3.2)
@ -381,7 +383,7 @@ This list contains 1267 plugins.
: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)
:pypi:`pytest-enabler` Enable installed pytest plugins May 12, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing'
:pypi:`pytest-enabler` Enable installed pytest plugins Jun 26, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing'
:pypi:`pytest-encode` set your encoding and logger Nov 06, 2021 N/A N/A
:pypi:`pytest-encode-kane` set your encoding and logger Nov 16, 2021 N/A pytest
:pypi:`pytest-enhanced-reports` Enhanced test reports for pytest Dec 15, 2022 N/A N/A
@ -467,7 +469,8 @@ This list contains 1267 plugins.
:pypi:`pytest-flask-sqlalchemy` A pytest plugin for preserving test isolation in Flask-SQlAlchemy using database transactions. Apr 30, 2022 4 - Beta pytest (>=3.2.1)
:pypi:`pytest-flask-sqlalchemy-transactions` Run tests in transactions using pytest, Flask, and SQLalchemy. Aug 02, 2018 4 - Beta pytest (>=3.2.1)
:pypi:`pytest-flexreport` Apr 15, 2023 4 - Beta pytest
:pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd Jul 12, 2022 4 - Beta pytest
:pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd Jun 26, 2023 4 - Beta pytest (>=7.0.0)
:pypi:`pytest-fluentbit` A pytest plugin in order to provide logs via fluentbit Jun 16, 2023 4 - Beta pytest (>=7.0.0)
:pypi:`pytest-flyte` Pytest fixtures for simplifying Flyte integration testing May 03, 2021 N/A pytest
:pypi:`pytest-focus` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest
:pypi:`pytest-forbid` Mar 07, 2023 N/A pytest (>=7.2.2,<8.0.0)
@ -476,7 +479,7 @@ This list contains 1267 plugins.
:pypi:`pytest-forward-compatibility` A pytest plugin to shim pytest commandline options for fowards compatibility Sep 29, 2020 N/A N/A
:pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications May 03, 2023 4 - Beta pytest>=7.0.0
:pypi:`pytest-freezegun` Wrap tests with fixtures in freeze_time Jul 19, 2020 4 - Beta pytest (>=3.0.0)
:pypi:`pytest-freezer` Pytest plugin providing a fixture interface for spulec/freezegun Jun 17, 2023 N/A pytest>=3.6
:pypi:`pytest-freezer` Pytest plugin providing a fixture interface for spulec/freezegun Jun 21, 2023 N/A pytest >= 3.6
:pypi:`pytest-freeze-reqs` Check if requirement files are frozen Apr 29, 2021 N/A N/A
:pypi:`pytest-frozen-uuids` Deterministically frozen UUID's for your tests Apr 17, 2022 N/A pytest (>=3.0)
:pypi:`pytest-func-cov` Pytest plugin for measuring function coverage Apr 15, 2021 3 - Alpha pytest (>=5)
@ -491,8 +494,9 @@ This list contains 1267 plugins.
: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. Jun 14, 2023 N/A N/A
:pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Jun 28, 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 Jun 22, 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
:pypi:`pytest-git-fixtures` Pytest fixtures for testing with git. Mar 11, 2021 4 - Beta pytest
:pypi:`pytest-github` Plugin for py.test that associates tests with github issues using a marker. Mar 07, 2019 5 - Production/Stable N/A
@ -508,6 +512,7 @@ This list contains 1267 plugins.
:pypi:`pytest-google-chat` Notify google chat channel for test results Mar 27, 2022 4 - Beta pytest
:pypi:`pytest-graphql-schema` Get graphql schema as fixture for pytest Oct 18, 2019 N/A N/A
:pypi:`pytest-greendots` Green progress dots Feb 08, 2014 3 - Alpha N/A
:pypi:`pytest-group-by-class` A Pytest plugin for running a subset of your tests by splitting them in to groups of classes. Jun 27, 2023 5 - Production/Stable pytest (>=2.5)
:pypi:`pytest-growl` Growl notifications for pytest results. Jan 13, 2014 5 - Production/Stable N/A
:pypi:`pytest-grpc` pytest plugin for grpc May 01, 2020 N/A pytest (>=3.6.0)
:pypi:`pytest-grunnur` Py.Test plugin for Grunnur-based packages. Feb 05, 2023 N/A N/A
@ -523,10 +528,10 @@ This list contains 1267 plugins.
:pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest
:pypi:`pytest-historic-hook` Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report Apr 08, 2020 N/A pytest
:pypi:`pytest-homeassistant` A pytest plugin for use with homeassistant custom components. Aug 12, 2020 4 - Beta N/A
:pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jun 16, 2023 3 - Alpha pytest (==7.3.1)
:pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jun 24, 2023 3 - Alpha pytest (==7.3.1)
: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 16, 2023 N/A N/A
:pypi:`pytest-hot-reloading` Jun 23, 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-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0)
:pypi:`pytest-hoverfly-wrapper` Integrates the Hoverfly HTTP proxy into Pytest Feb 27, 2023 5 - Production/Stable pytest (>=3.7.0)
@ -554,7 +559,7 @@ This list contains 1267 plugins.
:pypi:`pytest-ibutsu` A plugin to sent pytest results to an Ibutsu server Aug 05, 2022 4 - Beta pytest>=7.1
:pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Aug 09, 2022 4 - Beta N/A
:pypi:`pytest-idapro` A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api Nov 03, 2018 N/A N/A
:pypi:`pytest-idem` A pytest plugin to help with testing idem projects Sep 07, 2022 5 - Production/Stable N/A
:pypi:`pytest-idem` A pytest plugin to help with testing idem projects Jun 23, 2023 5 - Production/Stable N/A
:pypi:`pytest-idempotent` Pytest plugin for testing function idempotence. Jul 25, 2022 N/A N/A
:pypi:`pytest-ignore-flaky` ignore failures from flaky tests (pytest plugin) Apr 23, 2021 5 - Production/Stable N/A
:pypi:`pytest-image-diff` Mar 09, 2023 3 - Alpha pytest
@ -577,7 +582,7 @@ This list contains 1267 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. May 09, 2023 4 - Beta pytest
:pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Jun 29, 2023 4 - Beta pytest
:pypi:`pytest-invenio` Pytest fixtures for Invenio. Jun 02, 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
@ -593,7 +598,7 @@ This list contains 1267 plugins.
:pypi:`pytest-jest` A custom jest-pytest oriented Pytest reporter May 22, 2018 4 - Beta pytest (>=3.3.2)
:pypi:`pytest-jinja` A plugin to generate customizable jinja-based HTML reports in pytest Oct 04, 2022 3 - Alpha pytest (>=6.2.5,<7.0.0)
:pypi:`pytest-jira` py.test JIRA integration plugin, using markers Jun 12, 2023 3 - Alpha N/A
:pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Jun 14, 2023 N/A pytest (>=7.2.0)
:pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Jun 19, 2023 N/A pytest (>=7.2.0)
:pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Jun 06, 2023 4 - Beta pytest
:pypi:`pytest-job-selection` A pytest plugin for load balancing test suites Jan 30, 2023 4 - Beta pytest (>=3.5.0)
:pypi:`pytest-jobserver` Limit parallel tests with posix jobserver. May 15, 2019 5 - Production/Stable pytest
@ -654,7 +659,7 @@ This list contains 1267 plugins.
:pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Jul 25, 2019 4 - Beta pytest (>=3.2)
:pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A
:pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0)
:pypi:`pytest-logikal` Common testing environment Jun 04, 2023 5 - Production/Stable pytest (==7.3.1)
:pypi:`pytest-logikal` Common testing environment Jun 22, 2023 5 - Production/Stable pytest (==7.3.1)
:pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A
:pypi:`pytest-loguru` Pytest Loguru Apr 12, 2022 5 - Production/Stable N/A
:pypi:`pytest-loop` pytest plugin for looping tests Jul 22, 2022 5 - Production/Stable pytest (>=6)
@ -676,7 +681,7 @@ This list contains 1267 plugins.
:pypi:`pytest-maybe-raises` Pytest fixture for optional exception testing. May 27, 2022 N/A pytest ; extra == 'dev'
:pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0)
:pypi:`pytest-md` Plugin for generating Markdown reports for pytest results Jul 11, 2019 3 - Alpha pytest (>=4.2.1)
:pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. May 28, 2023 4 - Beta pytest (!=6.0.0,<8,>=3.3.2)
:pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. Jun 25, 2023 4 - Beta pytest (!=6.0.0,<8,>=3.3.2)
:pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0)
:pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A
:pypi:`pytest-memray` A simple plugin to use with pytest Jun 06, 2023 N/A pytest>=7.2
@ -710,7 +715,7 @@ This list contains 1267 plugins.
:pypi:`pytest-molecule` PyTest Molecule Plugin :: discover and run molecule tests Mar 29, 2022 5 - Production/Stable pytest (>=7.0.0)
:pypi:`pytest-mongo` MongoDB process and client fixtures plugin for Pytest. Jun 07, 2021 5 - Production/Stable pytest
:pypi:`pytest-mongodb` pytest plugin for MongoDB fixtures May 16, 2023 5 - Production/Stable N/A
:pypi:`pytest-monitor` Pytest plugin for analyzing resource usage. Oct 22, 2022 5 - Production/Stable pytest
:pypi:`pytest-monitor` Pytest plugin for analyzing resource usage. Jun 25, 2023 5 - Production/Stable pytest
:pypi:`pytest-monkeyplus` pytest's monkeypatch subclass with extra functionalities Sep 18, 2012 5 - Production/Stable N/A
:pypi:`pytest-monkeytype` pytest-monkeytype: Generate Monkeytype annotations from your pytest tests. Jul 29, 2020 4 - Beta N/A
:pypi:`pytest-moto` Fixtures for integration tests of AWS services,uses moto mocking library. Aug 28, 2015 1 - Planning N/A
@ -728,13 +733,13 @@ This list contains 1267 plugins.
:pypi:`pytest-mutagen` Add the mutation testing feature to pytest Jul 24, 2020 N/A pytest (>=5.4)
:pypi:`pytest-mypy` Mypy static type checker plugin for Pytest Dec 18, 2022 4 - Beta pytest (>=6.2) ; python_version >= "3.10"
:pypi:`pytest-mypyd` Mypy static type checker plugin for Pytest Aug 20, 2019 4 - Beta pytest (<4.7,>=2.8) ; python_version < "3.5"
:pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins May 05, 2023 4 - Beta pytest (>=6.2.0)
:pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Jun 29, 2023 4 - Beta pytest (>=7.0.0)
:pypi:`pytest-mypy-plugins-shim` Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. Apr 12, 2021 N/A pytest>=6.0.0
:pypi:`pytest-mypy-testing` Pytest plugin to check mypy output. Feb 25, 2023 N/A pytest>=7,<8
:pypi:`pytest-mysql` MySQL process and client fixtures for pytest Mar 27, 2023 5 - Production/Stable pytest (>=6.2)
:pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0)
:pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0)
:pypi:`pytest-netdut` "Automated software testing for switches using pytest" Jun 05, 2023 N/A pytest (>=3.5.0)
:pypi:`pytest-netdut` "Automated software testing for switches using pytest" Jun 19, 2023 N/A pytest (>=3.5.0)
:pypi:`pytest-network` A simple plugin to disable network on socket level. May 07, 2020 N/A N/A
:pypi:`pytest-network-endpoints` Network endpoints plugin for pytest Mar 06, 2022 N/A pytest
:pypi:`pytest-never-sleep` pytest plugin helps to avoid adding tests without mock \`time.sleep\` May 05, 2021 3 - Alpha pytest (>=3.5.1)
@ -821,6 +826,7 @@ This list contains 1267 plugins.
:pypi:`pytest-play` pytest plugin that let you automate actions and assertions with test metrics reporting executing plain YAML files Jun 12, 2019 5 - Production/Stable N/A
:pypi:`pytest-playbook` Pytest plugin for reading playbooks. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0)
:pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Apr 24, 2023 N/A pytest (<8.0.0,>=6.2.4)
:pypi:`pytest-playwright-async` ASYNC Pytest plugin for Playwright Jun 26, 2023 N/A N/A
:pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A
:pypi:`pytest-playwright-snapshot` A pytest wrapper for snapshot testing with playwright Aug 19, 2021 N/A N/A
:pypi:`pytest-playwright-visual` A pytest fixture for visual testing with Playwright Apr 28, 2022 N/A N/A
@ -838,6 +844,7 @@ This list contains 1267 plugins.
:pypi:`pytest-poo` Visualize your crappy tests Mar 25, 2021 5 - Production/Stable pytest (>=2.3.4)
:pypi:`pytest-poo-fail` Visualize your failed tests with poo Feb 12, 2015 5 - Production/Stable N/A
:pypi:`pytest-pop` A pytest plugin to help with testing pop projects May 09, 2023 5 - Production/Stable pytest
:pypi:`pytest-porringer` Jun 24, 2023 N/A pytest>=7.1.2
:pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0)
:pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest
:pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. May 20, 2023 5 - Production/Stable pytest (>=6.2)
@ -847,7 +854,7 @@ This list contains 1267 plugins.
:pypi:`pytest-pretty` pytest plugin for printing summary data as I want it Apr 05, 2023 5 - Production/Stable pytest>=7
:pypi:`pytest-pretty-terminal` pytest plugin for generating prettier terminal output Jan 31, 2022 N/A pytest (>=3.4.1)
:pypi:`pytest-pride` Minitest-style test colors Apr 02, 2016 3 - Alpha N/A
:pypi:`pytest-print` pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) Jun 16, 2023 5 - Production/Stable pytest>=7.3.2
:pypi:`pytest-print` pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) Jun 28, 2023 5 - Production/Stable pytest>=7.3.2
:pypi:`pytest-profiles` pytest plugin for configuration profiles Dec 09, 2021 4 - Beta pytest (>=3.7.0)
:pypi:`pytest-profiling` Profiling plugin for py.test May 28, 2019 5 - Production/Stable pytest
:pypi:`pytest-progress` pytest plugin for instant test progress status Jan 31, 2022 5 - Production/Stable N/A
@ -868,7 +875,7 @@ This list contains 1267 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 Sep 10, 2022 5 - Production/Stable pytest (>=5.4)
: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" Jun 11, 2023 N/A pytest
:pypi:`pytest-pyodide` "Pytest plugin for testing applications that use Pyodide" Jun 19, 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)
@ -886,7 +893,7 @@ This list contains 1267 plugins.
:pypi:`pytest-qaseio` Pytest plugin for Qase.io integration May 11, 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 09, 2023 5 - Production/Stable pytest (>=6.2.5)
:pypi:`pytest-qgis` A pytest plugin for testing QGIS python plugins Jun 30, 2023 5 - Production/Stable pytest (>=6.2.5)
: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)
@ -939,7 +946,7 @@ This list contains 1267 plugins.
:pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest
:pypi:`pytest-report-me` A pytest plugin to generate report. Dec 31, 2020 N/A pytest
:pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2)
:pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Jun 08, 2023 N/A pytest (>=3.8.0)
:pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Jun 30, 2023 N/A pytest (>=3.8.0)
:pypi:`pytest-reports` An interesting python package Jun 07, 2023 N/A N/A
:pypi:`pytest-reqs` pytest plugin to check pinned requirements May 12, 2019 N/A pytest (>=2.4.2)
:pypi:`pytest-requests` A simple plugin to use with pytest Jun 24, 2019 4 - Beta pytest (>=3.5.0)
@ -969,7 +976,7 @@ This list contains 1267 plugins.
:pypi:`pytest-reverse` Pytest plugin to reverse test order. Jun 16, 2023 5 - Production/Stable pytest
:pypi:`pytest-rich` Leverage rich for richer test session output Mar 03, 2022 4 - Beta pytest (>=7.0)
:pypi:`pytest-rich-reporter` A pytest plugin using Rich for beautiful test result formatting. Feb 17, 2022 1 - Planning pytest (>=5.0.0)
:pypi:`pytest-richtrace` Nov 05, 2022 N/A pytest (>=7.2.0,<8.0.0)
:pypi:`pytest-richtrace` A pytest plugin that displays the names and information of the pytest hook functions as they are executed. Jun 20, 2023 N/A N/A
:pypi:`pytest-ringo` pytest plugin to test webapplications using the Ringo webframework Sep 27, 2017 3 - Alpha N/A
:pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5)
:pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest
@ -998,14 +1005,14 @@ This list contains 1267 plugins.
:pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2)
:pypi:`pytest-sanity` Dec 07, 2020 N/A N/A
:pypi:`pytest-sa-pg` May 14, 2019 N/A N/A
:pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jun 13, 2023 5 - Production/Stable N/A
:pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jun 30, 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-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-seleniumbase` A complete web automation framework for end-to-end testing. Jun 13, 2023 5 - Production/Stable N/A
:pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jun 30, 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
@ -1045,6 +1052,7 @@ This list contains 1267 plugins.
:pypi:`pytest-smartcov` Smart coverage plugin for pytest. Sep 30, 2017 3 - Alpha N/A
:pypi:`pytest-smell` Automated bad smell detection tool for Pytest Jun 26, 2022 N/A N/A
:pypi:`pytest-smtp` Send email with pytest execution result Feb 20, 2021 N/A pytest
:pypi:`pytest-smtp4dev` Plugin for smtp4dev API Jun 27, 2023 5 - Production/Stable N/A
:pypi:`pytest-smtpd` An SMTP server for testing built on aiosmtpd May 15, 2023 N/A pytest
:pypi:`pytest-snail` Plugin for adding a marker to slow running tests. 🐌 Nov 04, 2019 3 - Alpha pytest (>=5.0.1)
:pypi:`pytest-snapci` py.test plugin for Snap-CI Nov 12, 2015 N/A N/A
@ -1072,7 +1080,7 @@ This list contains 1267 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 Feb 22, 2023 N/A pytest (>5.4.0,<7.3)
:pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Jun 30, 2023 N/A pytest (>5.4.0,<8)
:pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Mar 07, 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
@ -1120,10 +1128,10 @@ This list contains 1267 plugins.
:pypi:`pytest-tcpclient` A pytest plugin for testing TCP clients Nov 16, 2022 N/A pytest (<8,>=7.1.3)
:pypi:`pytest-teamcity-logblock` py.test plugin to introduce block structure in teamcity build log, if output is not captured May 15, 2018 4 - Beta N/A
:pypi:`pytest-telegram` Pytest to Telegram reporting plugin Dec 10, 2020 5 - Production/Stable N/A
:pypi:`pytest-telegram-notifier` Telegram notification plugin for Pytest Mar 17, 2023 5 - Production/Stable N/A
:pypi:`pytest-telegram-notifier` Telegram notification plugin for Pytest Jun 27, 2023 5 - Production/Stable N/A
:pypi:`pytest-tempdir` Predictable and repeatable tempdir support. Oct 11, 2019 4 - Beta pytest (>=2.8.1)
:pypi:`pytest-terra-fixt` Terraform and Terragrunt fixtures for pytest Sep 15, 2022 N/A pytest (==6.2.5)
:pypi:`pytest-terraform` A pytest plugin for using terraform fixtures Sep 01, 2022 N/A pytest (>=6.0)
:pypi:`pytest-terraform` A pytest plugin for using terraform fixtures Jun 20, 2023 N/A pytest (>=6.0)
:pypi:`pytest-terraform-fixture` generate terraform resources to use with pytest Nov 14, 2018 4 - Beta N/A
:pypi:`pytest-testbook` A plugin to run tests written in Jupyter notebook Dec 11, 2016 3 - Alpha N/A
:pypi:`pytest-testconfig` Test configuration plugin for pytest. Jan 11, 2020 4 - Beta pytest (>=3.5.0)
@ -1155,18 +1163,20 @@ This list contains 1267 plugins.
:pypi:`pytest-test-this` Plugin for py.test to run relevant tests, based on naively checking if a test contains a reference to the symbol you supply Sep 15, 2019 2 - Pre-Alpha pytest (>=2.3)
:pypi:`pytest-test-utils` Jul 14, 2022 N/A pytest (>=5)
:pypi:`pytest-tesults` Tesults plugin for pytest Dec 23, 2022 5 - Production/Stable pytest (>=3.5.0)
:pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Jun 27, 2023 4 - Beta pytest (>=7.0.0)
:pypi:`pytest-tezos` pytest-ligo Jan 16, 2020 4 - Beta N/A
:pypi:`pytest-th2-bdd` pytest_th2_bdd May 13, 2022 N/A N/A
:pypi:`pytest-thawgun` Pytest plugin for time travel May 26, 2020 3 - Alpha N/A
:pypi:`pytest-threadleak` Detects thread leaks Jul 03, 2022 4 - Beta pytest (>=3.1.1)
:pypi:`pytest-tick` Ticking on tests Aug 31, 2021 5 - Production/Stable pytest (>=6.2.5,<7.0.0)
:pypi:`pytest-time` Jun 16, 2023 3 - Alpha pytest
:pypi:`pytest-time` Jun 24, 2023 3 - Alpha pytest
:pypi:`pytest-timeit` A pytest plugin to time test function runs Oct 13, 2016 4 - Beta N/A
:pypi:`pytest-timeout` pytest plugin to abort hanging tests Jan 18, 2022 5 - Production/Stable pytest (>=5.0.0)
:pypi:`pytest-timeouts` Linux-only Pytest plugin to control durations of various test case execution phases Sep 21, 2019 5 - Production/Stable N/A
:pypi:`pytest-timer` A timer plugin for pytest Jun 02, 2021 N/A N/A
:pypi:`pytest-timestamper` Pytest plugin to add a timestamp prefix to the pytest output Jun 06, 2021 N/A N/A
:pypi:`pytest-timestamps` A simple plugin to view timestamps for each test Apr 01, 2023 N/A pytest (>=5.2)
:pypi:`pytest-tinybird` A pytest plugin to report test results to tinybird Jun 26, 2023 4 - Beta pytest (>=3.8.0)
:pypi:`pytest-tipsi-django` Nov 17, 2021 4 - Beta pytest (>=6.0.0)
:pypi:`pytest-tipsi-testing` Better fixtures management. Various helpers Nov 04, 2020 4 - Beta pytest (>=3.3.0)
:pypi:`pytest-tldr` A pytest plugin that limits the output to just the things you need. Oct 26, 2022 4 - Beta pytest (>=3.5.0)
@ -1215,7 +1225,7 @@ This list contains 1267 plugins.
:pypi:`pytest-unmarked` Run only unmarked tests Aug 27, 2019 5 - Production/Stable N/A
:pypi:`pytest-unordered` Test equality of unordered collections in pytest Nov 28, 2022 4 - Beta pytest (>=6.0.0)
:pypi:`pytest-unstable` Set a test as unstable to return 0 even if it failed Sep 27, 2022 4 - Beta N/A
:pypi:`pytest-unused-fixtures` A pytest plugin to list unused fixtures after a test run. Jun 15, 2023 4 - Beta pytest (>=7.3.2,<8.0.0)
:pypi:`pytest-unused-fixtures` A pytest plugin to list unused fixtures after a test run. Jun 30, 2023 4 - Beta pytest (>=7.3.2,<8.0.0)
:pypi:`pytest-upload-report` pytest-upload-report is a plugin for pytest that upload your test report for test results. Jun 18, 2021 5 - Production/Stable N/A
:pypi:`pytest-utils` Some helpers for pytest. Feb 02, 2023 4 - Beta pytest (>=7.0.0,<8.0.0)
:pypi:`pytest-vagrant` A py.test plugin providing access to vagrant. Sep 07, 2021 5 - Production/Stable pytest
@ -1242,7 +1252,7 @@ This list contains 1267 plugins.
:pypi:`pytest-wa-e2e-plugin` Pytest plugin for testing whatsapp bots with end to end tests Feb 18, 2020 4 - Beta pytest (>=3.5.0)
:pypi:`pytest-wake` May 11, 2023 N/A pytest
:pypi:`pytest-watch` Local continuous test runner with pytest and watchdog. May 20, 2018 N/A N/A
:pypi:`pytest-watcher` Automatically rerun your tests on file modifications Jun 11, 2023 4 - Beta N/A
:pypi:`pytest-watcher` Automatically rerun your tests on file modifications Jun 24, 2023 4 - Beta N/A
:pypi:`pytest-wdl` Pytest plugin for testing WDL workflows. Nov 17, 2020 5 - Production/Stable N/A
:pypi:`pytest-web3-data` Sep 15, 2022 4 - Beta pytest
:pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest
@ -1259,7 +1269,7 @@ This list contains 1267 plugins.
: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)
:pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Jun 15, 2023 4 - Beta pytest (>=7.3.2,<8.0.0)
:pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Jun 19, 2023 4 - Beta pytest (>=7.3.2,<8.0.0)
:pypi:`pytest-xfaillist` Maintain a xfaillist in an additional file to avoid merge-conflicts. Sep 17, 2021 N/A pytest (>=6.2.2,<7.0.0)
:pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A
:pypi:`pytest-xlog` Extended logging for test and decorators May 31, 2020 4 - Beta N/A
@ -1271,15 +1281,16 @@ This list contains 1267 plugins.
:pypi:`pytest-xray-server` May 03, 2022 3 - Alpha pytest (>=5.3.1)
:pypi:`pytest-xskynet` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A
: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. Jun 18, 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 May 28, 2023 N/A pytest>=7.2.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 08, 2023 N/A pytest (>=7.2.0)
:pypi:`pytest-yaml-yoyo` http/https API run by yaml Jun 19, 2023 N/A pytest (>=7.2.0)
:pypi:`pytest-yapf` Run yapf Jul 06, 2017 4 - Beta pytest (>=3.1.1)
:pypi:`pytest-yapf3` Validate your Python file format with yapf Mar 29, 2023 5 - Production/Stable pytest (>=7)
:pypi:`pytest-yield` PyTest plugin to run tests concurrently, each \`yield\` switch context to other one Jan 23, 2019 N/A N/A
:pypi:`pytest-yls` Pytest plugin to test the YLS as a whole. Mar 29, 2023 N/A pytest (>=7.2.2,<8.0.0)
:pypi:`pytest-yls` Pytest plugin to test the YLS as a whole. Jun 21, 2023 N/A pytest (>=7.2.2,<8.0.0)
:pypi:`pytest-yuk` Display tests you are uneasy with, using 🤢/🤮 for pass/fail of tests marked with yuk. Mar 26, 2021 N/A pytest>=5.0.0
:pypi:`pytest-zafira` A Zafira plugin for pytest Sep 18, 2019 5 - Production/Stable pytest (==4.1.1)
:pypi:`pytest-zap` OWASP ZAP plugin for py.test. May 12, 2014 4 - Beta N/A
@ -1405,7 +1416,7 @@ This list contains 1267 plugins.
Pytest \`client\` fixture for the Aiohttp
:pypi:`pytest-aiomoto`
*last release*: Nov 09, 2022,
*last release*: Jun 24, 2023,
*status*: N/A,
*requires*: pytest (>=7.0,<8.0)
@ -1440,7 +1451,7 @@ This list contains 1267 plugins.
:pypi:`pytest-alembic`
*last release*: May 23, 2023,
*last release*: Jun 27, 2023,
*status*: N/A,
*requires*: pytest (>=6.0)
@ -1937,7 +1948,7 @@ This list contains 1267 plugins.
pytest plugin to display BDD info in HTML test report
:pypi:`pytest-bdd-ng`
*last release*: Oct 06, 2022,
*last release*: Jul 01, 2023,
*status*: 4 - Beta,
*requires*: pytest (>=5.0)
@ -2175,9 +2186,9 @@ This list contains 1267 plugins.
Budo Systems is a martial arts school management system. This module is the Budo Systems Pytest Plugin.
:pypi:`pytest-bug`
*last release*: Jan 29, 2023,
*last release*: Jun 23, 2023,
*status*: 5 - Production/Stable,
*requires*: pytest (>=6.2.0)
*requires*: pytest (>=7.1.0)
Pytest plugin for marking tests as a bug
@ -2644,7 +2655,7 @@ This list contains 1267 plugins.
pytest framework for testing different aspects of a common method
:pypi:`pytest-compare`
*last release*: Mar 30, 2023,
*last release*: Jun 22, 2023,
*status*: 5 - Production/Stable,
*requires*: N/A
@ -2686,7 +2697,7 @@ This list contains 1267 plugins.
pytest plugin with fixtures for testing consul aware apps
:pypi:`pytest-container`
*last release*: Mar 21, 2023,
*last release*: Jun 19, 2023,
*status*: 4 - Beta,
*requires*: pytest (>=3.10)
@ -2713,6 +2724,13 @@ This list contains 1267 plugins.
The pytest plugin for your Cookiecutter templates. 🍪
:pypi:`pytest-copier`
*last release*: Jun 23, 2023,
*status*: 4 - Beta,
*requires*: pytest>=7.1.2
A pytest plugin to help testing Copier templates
:pypi:`pytest-couchdbkit`
*last release*: Apr 17, 2012,
*status*: N/A,
@ -2749,9 +2767,9 @@ This list contains 1267 plugins.
:pypi:`pytest-coverage-context`
*last release*: Jan 04, 2021,
*last release*: Jun 28, 2023,
*status*: 4 - Beta,
*requires*: pytest (>=6.1.0)
*requires*: N/A
Coverage dynamic context support for PyTest, including sub-processes
@ -2777,7 +2795,7 @@ This list contains 1267 plugins.
Use pytest's runner to discover and execute C++ tests
:pypi:`pytest-cppython`
*last release*: Jun 14, 2023,
*last release*: Jun 19, 2023,
*status*: N/A,
*requires*: N/A
@ -2840,9 +2858,9 @@ This list contains 1267 plugins.
CSV output for pytest.
:pypi:`pytest-csv-params`
*last release*: Aug 28, 2022,
*last release*: Jul 01, 2023,
*status*: 5 - Production/Stable,
*requires*: pytest (>=7.1.2,<8.0.0)
*requires*: pytest (>=7.4.0,<8.0.0)
Pytest plugin for Test Case Parametrization with CSV files
@ -3224,6 +3242,13 @@ This list contains 1267 plugins.
PyTest plugin for generating Difido reports
:pypi:`pytest-dir-equal`
*last release*: Jun 23, 2023,
*status*: 4 - Beta,
*requires*: pytest>=7.1.2
pytest-dir-equals is a pytest plugin providing helpers to assert directories equality allowing golden testing
:pypi:`pytest-disable`
*last release*: Sep 10, 2015,
*status*: 4 - Beta,
@ -3820,7 +3845,7 @@ This list contains 1267 plugins.
Pytest plugin to represent test output with emoji support
:pypi:`pytest-enabler`
*last release*: May 12, 2023,
*last release*: Jun 26, 2023,
*status*: 5 - Production/Stable,
*requires*: pytest (>=6) ; extra == 'testing'
@ -4422,12 +4447,19 @@ This list contains 1267 plugins.
:pypi:`pytest-fluent`
*last release*: Jul 12, 2022,
*last release*: Jun 26, 2023,
*status*: 4 - Beta,
*requires*: pytest
*requires*: pytest (>=7.0.0)
A pytest plugin in order to provide logs via fluentd
:pypi:`pytest-fluentbit`
*last release*: Jun 16, 2023,
*status*: 4 - Beta,
*requires*: pytest (>=7.0.0)
A pytest plugin in order to provide logs via fluentbit
:pypi:`pytest-flyte`
*last release*: May 03, 2021,
*status*: N/A,
@ -4485,9 +4517,9 @@ This list contains 1267 plugins.
Wrap tests with fixtures in freeze_time
:pypi:`pytest-freezer`
*last release*: Jun 17, 2023,
*last release*: Jun 21, 2023,
*status*: N/A,
*requires*: pytest>=3.6
*requires*: pytest >= 3.6
Pytest plugin providing a fixture interface for spulec/freezegun
@ -4590,7 +4622,7 @@ This list contains 1267 plugins.
For finding/executing Ghost Inspector tests
:pypi:`pytest-girder`
*last release*: Jun 14, 2023,
*last release*: Jun 28, 2023,
*status*: N/A,
*requires*: N/A
@ -4603,6 +4635,13 @@ This list contains 1267 plugins.
Git repository fixture for py.test
:pypi:`pytest-gitconfig`
*last release*: Jun 22, 2023,
*status*: 4 - Beta,
*requires*: pytest>=7.1.2
Provide a gitconfig sandbox for testing
:pypi:`pytest-gitcov`
*last release*: Jan 11, 2020,
*status*: 2 - Pre-Alpha,
@ -4708,6 +4747,13 @@ This list contains 1267 plugins.
Green progress dots
:pypi:`pytest-group-by-class`
*last release*: Jun 27, 2023,
*status*: 5 - Production/Stable,
*requires*: pytest (>=2.5)
A Pytest plugin for running a subset of your tests by splitting them in to groups of classes.
:pypi:`pytest-growl`
*last release*: Jan 13, 2014,
*status*: 5 - Production/Stable,
@ -4814,7 +4860,7 @@ This list contains 1267 plugins.
A pytest plugin for use with homeassistant custom components.
:pypi:`pytest-homeassistant-custom-component`
*last release*: Jun 16, 2023,
*last release*: Jun 24, 2023,
*status*: 3 - Alpha,
*requires*: pytest (==7.3.1)
@ -4835,7 +4881,7 @@ This list contains 1267 plugins.
Report on tests that honor constraints, and guard against regressions
:pypi:`pytest-hot-reloading`
*last release*: Jun 16, 2023,
*last release*: Jun 23, 2023,
*status*: N/A,
*requires*: N/A
@ -5031,7 +5077,7 @@ This list contains 1267 plugins.
A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api
:pypi:`pytest-idem`
*last release*: Sep 07, 2022,
*last release*: Jun 23, 2023,
*status*: 5 - Production/Stable,
*requires*: N/A
@ -5192,7 +5238,7 @@ This list contains 1267 plugins.
Pytest plugin for intercepting outgoing connection requests during pytest run.
:pypi:`pytest-interface-tester`
*last release*: May 09, 2023,
*last release*: Jun 29, 2023,
*status*: 4 - Beta,
*requires*: pytest
@ -5304,7 +5350,7 @@ This list contains 1267 plugins.
py.test JIRA integration plugin, using markers
:pypi:`pytest-jira-xfail`
*last release*: Jun 14, 2023,
*last release*: Jun 19, 2023,
*status*: N/A,
*requires*: pytest (>=7.2.0)
@ -5731,7 +5777,7 @@ This list contains 1267 plugins.
:pypi:`pytest-logikal`
*last release*: Jun 04, 2023,
*last release*: Jun 22, 2023,
*status*: 5 - Production/Stable,
*requires*: pytest (==7.3.1)
@ -5885,7 +5931,7 @@ This list contains 1267 plugins.
Plugin for generating Markdown reports for pytest results
:pypi:`pytest-md-report`
*last release*: May 28, 2023,
*last release*: Jun 25, 2023,
*status*: 4 - Beta,
*requires*: pytest (!=6.0.0,<8,>=3.3.2)
@ -6123,7 +6169,7 @@ This list contains 1267 plugins.
pytest plugin for MongoDB fixtures
:pypi:`pytest-monitor`
*last release*: Oct 22, 2022,
*last release*: Jun 25, 2023,
*status*: 5 - Production/Stable,
*requires*: pytest
@ -6249,9 +6295,9 @@ This list contains 1267 plugins.
Mypy static type checker plugin for Pytest
:pypi:`pytest-mypy-plugins`
*last release*: May 05, 2023,
*last release*: Jun 29, 2023,
*status*: 4 - Beta,
*requires*: pytest (>=6.2.0)
*requires*: pytest (>=7.0.0)
pytest plugin for writing tests for mypy plugins
@ -6291,7 +6337,7 @@ This list contains 1267 plugins.
pytest-neo is a plugin for pytest that shows tests like screen of Matrix.
:pypi:`pytest-netdut`
*last release*: Jun 05, 2023,
*last release*: Jun 19, 2023,
*status*: N/A,
*requires*: pytest (>=3.5.0)
@ -6899,6 +6945,13 @@ This list contains 1267 plugins.
A pytest wrapper with fixtures for Playwright to automate web browsers
:pypi:`pytest-playwright-async`
*last release*: Jun 26, 2023,
*status*: N/A,
*requires*: N/A
ASYNC Pytest plugin for Playwright
:pypi:`pytest-playwrights`
*last release*: Dec 02, 2021,
*status*: N/A,
@ -7018,6 +7071,13 @@ This list contains 1267 plugins.
A pytest plugin to help with testing pop projects
:pypi:`pytest-porringer`
*last release*: Jun 24, 2023,
*status*: N/A,
*requires*: pytest>=7.1.2
:pypi:`pytest-portion`
*last release*: Jan 28, 2021,
*status*: 4 - Beta,
@ -7082,7 +7142,7 @@ This list contains 1267 plugins.
Minitest-style test colors
:pypi:`pytest-print`
*last release*: Jun 16, 2023,
*last release*: Jun 28, 2023,
*status*: 5 - Production/Stable,
*requires*: pytest>=7.3.2
@ -7229,7 +7289,7 @@ This list contains 1267 plugins.
Record PyMySQL queries and mock with the stored data.
:pypi:`pytest-pyodide`
*last release*: Jun 11, 2023,
*last release*: Jun 19, 2023,
*status*: N/A,
*requires*: pytest
@ -7355,7 +7415,7 @@ This list contains 1267 plugins.
Pytest plugin for uploading test results to your QA Touch Testrun.
:pypi:`pytest-qgis`
*last release*: Jun 09, 2023,
*last release*: Jun 30, 2023,
*status*: 5 - Production/Stable,
*requires*: pytest (>=6.2.5)
@ -7726,7 +7786,7 @@ This list contains 1267 plugins.
pytest plugin for adding tests' parameters to junit report
:pypi:`pytest-reportportal`
*last release*: Jun 08, 2023,
*last release*: Jun 30, 2023,
*status*: N/A,
*requires*: pytest (>=3.8.0)
@ -7936,11 +7996,11 @@ This list contains 1267 plugins.
A pytest plugin using Rich for beautiful test result formatting.
:pypi:`pytest-richtrace`
*last release*: Nov 05, 2022,
*last release*: Jun 20, 2023,
*status*: N/A,
*requires*: pytest (>=7.2.0,<8.0.0)
*requires*: N/A
A pytest plugin that displays the names and information of the pytest hook functions as they are executed.
:pypi:`pytest-ringo`
*last release*: Sep 27, 2017,
@ -8139,7 +8199,7 @@ This list contains 1267 plugins.
:pypi:`pytest-sbase`
*last release*: Jun 13, 2023,
*last release*: Jun 30, 2023,
*status*: 5 - Production/Stable,
*requires*: N/A
@ -8188,7 +8248,7 @@ This list contains 1267 plugins.
pytest plugin for Selenium
:pypi:`pytest-seleniumbase`
*last release*: Jun 13, 2023,
*last release*: Jun 30, 2023,
*status*: 5 - Production/Stable,
*requires*: N/A
@ -8467,6 +8527,13 @@ This list contains 1267 plugins.
Send email with pytest execution result
:pypi:`pytest-smtp4dev`
*last release*: Jun 27, 2023,
*status*: 5 - Production/Stable,
*requires*: N/A
Plugin for smtp4dev API
:pypi:`pytest-smtpd`
*last release*: May 15, 2023,
*status*: N/A,
@ -8657,9 +8724,9 @@ This list contains 1267 plugins.
:pypi:`pytest-splunk-addon`
*last release*: Feb 22, 2023,
*last release*: Jun 30, 2023,
*status*: N/A,
*requires*: pytest (>5.4.0,<7.3)
*requires*: pytest (>5.4.0,<8)
A Dynamic test tool for Splunk Apps and Add-ons
@ -8993,7 +9060,7 @@ This list contains 1267 plugins.
Pytest to Telegram reporting plugin
:pypi:`pytest-telegram-notifier`
*last release*: Mar 17, 2023,
*last release*: Jun 27, 2023,
*status*: 5 - Production/Stable,
*requires*: N/A
@ -9014,7 +9081,7 @@ This list contains 1267 plugins.
Terraform and Terragrunt fixtures for pytest
:pypi:`pytest-terraform`
*last release*: Sep 01, 2022,
*last release*: Jun 20, 2023,
*status*: N/A,
*requires*: pytest (>=6.0)
@ -9237,6 +9304,13 @@ This list contains 1267 plugins.
Tesults plugin for pytest
:pypi:`pytest-textual-snapshot`
*last release*: Jun 27, 2023,
*status*: 4 - Beta,
*requires*: pytest (>=7.0.0)
Snapshot testing for Textual apps
:pypi:`pytest-tezos`
*last release*: Jan 16, 2020,
*status*: 4 - Beta,
@ -9273,7 +9347,7 @@ This list contains 1267 plugins.
Ticking on tests
:pypi:`pytest-time`
*last release*: Jun 16, 2023,
*last release*: Jun 24, 2023,
*status*: 3 - Alpha,
*requires*: pytest
@ -9321,6 +9395,13 @@ This list contains 1267 plugins.
A simple plugin to view timestamps for each test
:pypi:`pytest-tinybird`
*last release*: Jun 26, 2023,
*status*: 4 - Beta,
*requires*: pytest (>=3.8.0)
A pytest plugin to report test results to tinybird
:pypi:`pytest-tipsi-django`
*last release*: Nov 17, 2021,
*status*: 4 - Beta,
@ -9658,7 +9739,7 @@ This list contains 1267 plugins.
Set a test as unstable to return 0 even if it failed
:pypi:`pytest-unused-fixtures`
*last release*: Jun 15, 2023,
*last release*: Jun 30, 2023,
*status*: 4 - Beta,
*requires*: pytest (>=7.3.2,<8.0.0)
@ -9847,7 +9928,7 @@ This list contains 1267 plugins.
Local continuous test runner with pytest and watchdog.
:pypi:`pytest-watcher`
*last release*: Jun 11, 2023,
*last release*: Jun 24, 2023,
*status*: 4 - Beta,
*requires*: N/A
@ -9966,7 +10047,7 @@ This list contains 1267 plugins.
pytest plugin helps to reproduce failures for particular xdist node
:pypi:`pytest-xdist-worker-stats`
*last release*: Jun 15, 2023,
*last release*: Jun 19, 2023,
*status*: 4 - Beta,
*requires*: pytest (>=7.3.2,<8.0.0)
@ -10049,6 +10130,13 @@ This list contains 1267 plugins.
A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests.
:pypi:`pytest-xvirt`
*last release*: Jun 18, 2023,
*status*: 4 - Beta,
*requires*: pytest (>=7.1.0)
A pytest plugin to virtualize test. For example to transparently running them on a remote box.
:pypi:`pytest-yaml`
*last release*: Oct 05, 2018,
*status*: N/A,
@ -10078,7 +10166,7 @@ This list contains 1267 plugins.
Run tests against wsgi apps defined in yaml
:pypi:`pytest-yaml-yoyo`
*last release*: Jun 08, 2023,
*last release*: Jun 19, 2023,
*status*: N/A,
*requires*: pytest (>=7.2.0)
@ -10106,7 +10194,7 @@ This list contains 1267 plugins.
PyTest plugin to run tests concurrently, each \`yield\` switch context to other one
:pypi:`pytest-yls`
*last release*: Mar 29, 2023,
*last release*: Jun 21, 2023,
*status*: N/A,
*requires*: pytest (>=7.2.2,<8.0.0)

View File

@ -17,7 +17,6 @@ classifiers =
Operating System :: POSIX
Programming Language :: Python :: 3
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
@ -50,9 +49,8 @@ install_requires =
pluggy>=0.12,<2.0
colorama;sys_platform=="win32"
exceptiongroup>=1.0.0rc8;python_version<"3.11"
importlib-metadata>=0.12;python_version<"3.8"
tomli>=1.0.0;python_version<"3.11"
python_requires = >=3.7
python_requires = >=3.8
package_dir =
=src
setup_requires =

View File

@ -17,18 +17,21 @@ from typing import Any
from typing import Callable
from typing import ClassVar
from typing import Dict
from typing import Final
from typing import final
from typing import Generic
from typing import Iterable
from typing import List
from typing import Literal
from typing import Mapping
from typing import Optional
from typing import overload
from typing import Pattern
from typing import Sequence
from typing import Set
from typing import SupportsIndex
from typing import Tuple
from typing import Type
from typing import TYPE_CHECKING
from typing import TypeVar
from typing import Union
@ -42,22 +45,16 @@ from _pytest._code.source import Source
from _pytest._io import TerminalWriter
from _pytest._io.saferepr import safeformat
from _pytest._io.saferepr import saferepr
from _pytest.compat import final
from _pytest.compat import get_real_func
from _pytest.deprecated import check_ispytest
from _pytest.pathlib import absolutepath
from _pytest.pathlib import bestrelpath
if TYPE_CHECKING:
from typing_extensions import Final
from typing_extensions import Literal
from typing_extensions import SupportsIndex
_TracebackStyle = Literal["long", "short", "line", "no", "native", "value", "auto"]
if sys.version_info[:2] < (3, 11):
from exceptiongroup import BaseExceptionGroup
_TracebackStyle = Literal["long", "short", "line", "no", "native", "value", "auto"]
class Code:
"""Wrapper around Python code objects."""
@ -633,7 +630,7 @@ class ExceptionInfo(Generic[E]):
def getrepr(
self,
showlocals: bool = False,
style: "_TracebackStyle" = "long",
style: _TracebackStyle = "long",
abspath: bool = False,
tbfilter: Union[
bool, Callable[["ExceptionInfo[BaseException]"], Traceback]
@ -725,7 +722,7 @@ class FormattedExcinfo:
fail_marker: ClassVar = "E"
showlocals: bool = False
style: "_TracebackStyle" = "long"
style: _TracebackStyle = "long"
abspath: bool = True
tbfilter: Union[bool, Callable[[ExceptionInfo[BaseException]], Traceback]] = True
funcargs: bool = False
@ -1090,7 +1087,7 @@ class ReprExceptionInfo(ExceptionRepr):
class ReprTraceback(TerminalRepr):
reprentries: Sequence[Union["ReprEntry", "ReprEntryNative"]]
extraline: Optional[str]
style: "_TracebackStyle"
style: _TracebackStyle
entrysep: ClassVar = "_ "
@ -1124,7 +1121,7 @@ class ReprTracebackNative(ReprTraceback):
class ReprEntryNative(TerminalRepr):
lines: Sequence[str]
style: ClassVar["_TracebackStyle"] = "native"
style: ClassVar[_TracebackStyle] = "native"
def toterminal(self, tw: TerminalWriter) -> None:
tw.write("".join(self.lines))
@ -1136,7 +1133,7 @@ class ReprEntry(TerminalRepr):
reprfuncargs: Optional["ReprFuncArgs"]
reprlocals: Optional["ReprLocals"]
reprfileloc: Optional["ReprFileLocation"]
style: "_TracebackStyle"
style: _TracebackStyle
def _write_entry_lines(self, tw: TerminalWriter) -> None:
"""Write the source code portions of a list of traceback entries with syntax highlighting.

View File

@ -149,8 +149,7 @@ def get_statement_startend2(lineno: int, node: ast.AST) -> Tuple[int, Optional[i
values: List[int] = []
for x in ast.walk(node):
if isinstance(x, (ast.stmt, ast.ExceptHandler)):
# Before Python 3.8, the lineno of a decorated class or function pointed at the decorator.
# Since Python 3.8, the lineno points to the class/def, so need to include the decorators.
# The lineno points to the class/def, so need to include the decorators.
if isinstance(x, (ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)):
for d in x.decorator_list:
values.append(d.lineno - 1)

View File

@ -2,12 +2,12 @@
import os
import shutil
import sys
from typing import final
from typing import Optional
from typing import Sequence
from typing import TextIO
from .wcwidth import wcswidth
from _pytest.compat import final
# This code was initially copied from py 1.8.1, file _io/terminalwriter.py.

View File

@ -44,17 +44,6 @@ from _pytest.stash import StashKey
if TYPE_CHECKING:
from _pytest.assertion import AssertionState
if sys.version_info >= (3, 8):
namedExpr = ast.NamedExpr
astNameConstant = ast.Constant
astStr = ast.Constant
astNum = ast.Constant
else:
namedExpr = ast.Expr
astNameConstant = ast.NameConstant
astStr = ast.Str
astNum = ast.Num
assertstate_key = StashKey["AssertionState"]()
@ -686,14 +675,10 @@ class AssertionRewriter(ast.NodeVisitor):
if (
expect_docstring
and isinstance(item, ast.Expr)
and isinstance(item.value, astStr)
and isinstance(item.value, ast.Constant)
and isinstance(item.value.value, str)
):
if sys.version_info >= (3, 8):
doc = item.value.value
else:
doc = item.value.s
if not isinstance(doc, str):
return
doc = item.value.value
if self.is_rewrite_disabled(doc):
return
expect_docstring = False
@ -825,7 +810,7 @@ class AssertionRewriter(ast.NodeVisitor):
current = self.stack.pop()
if self.stack:
self.explanation_specifiers = self.stack[-1]
keys = [astStr(key) for key in current.keys()]
keys = [ast.Constant(key) for key in current.keys()]
format_dict = ast.Dict(keys, list(current.values()))
form = ast.BinOp(expl_expr, ast.Mod(), format_dict)
name = "@py_format" + str(next(self.variable_counter))
@ -879,16 +864,16 @@ class AssertionRewriter(ast.NodeVisitor):
negation = ast.UnaryOp(ast.Not(), top_condition)
if self.enable_assertion_pass_hook: # Experimental pytest_assertion_pass hook
msg = self.pop_format_context(astStr(explanation))
msg = self.pop_format_context(ast.Constant(explanation))
# Failed
if assert_.msg:
assertmsg = self.helper("_format_assertmsg", assert_.msg)
gluestr = "\n>assert "
else:
assertmsg = astStr("")
assertmsg = ast.Constant("")
gluestr = "assert "
err_explanation = ast.BinOp(astStr(gluestr), ast.Add(), msg)
err_explanation = ast.BinOp(ast.Constant(gluestr), ast.Add(), msg)
err_msg = ast.BinOp(assertmsg, ast.Add(), err_explanation)
err_name = ast.Name("AssertionError", ast.Load())
fmt = self.helper("_format_explanation", err_msg)
@ -904,8 +889,8 @@ class AssertionRewriter(ast.NodeVisitor):
hook_call_pass = ast.Expr(
self.helper(
"_call_assertion_pass",
astNum(assert_.lineno),
astStr(orig),
ast.Constant(assert_.lineno),
ast.Constant(orig),
fmt_pass,
)
)
@ -924,7 +909,7 @@ class AssertionRewriter(ast.NodeVisitor):
variables = [
ast.Name(name, ast.Store()) for name in self.format_variables
]
clear_format = ast.Assign(variables, astNameConstant(None))
clear_format = ast.Assign(variables, ast.Constant(None))
self.statements.append(clear_format)
else: # Original assertion rewriting
@ -935,9 +920,9 @@ class AssertionRewriter(ast.NodeVisitor):
assertmsg = self.helper("_format_assertmsg", assert_.msg)
explanation = "\n>assert " + explanation
else:
assertmsg = astStr("")
assertmsg = ast.Constant("")
explanation = "assert " + explanation
template = ast.BinOp(assertmsg, ast.Add(), astStr(explanation))
template = ast.BinOp(assertmsg, ast.Add(), ast.Constant(explanation))
msg = self.pop_format_context(template)
fmt = self.helper("_format_explanation", msg)
err_name = ast.Name("AssertionError", ast.Load())
@ -949,7 +934,7 @@ class AssertionRewriter(ast.NodeVisitor):
# Clear temporary variables by setting them to None.
if self.variables:
variables = [ast.Name(name, ast.Store()) for name in self.variables]
clear = ast.Assign(variables, astNameConstant(None))
clear = ast.Assign(variables, ast.Constant(None))
self.statements.append(clear)
# Fix locations (line numbers/column offsets).
for stmt in self.statements:
@ -957,26 +942,26 @@ class AssertionRewriter(ast.NodeVisitor):
ast.copy_location(node, assert_)
return self.statements
def visit_NamedExpr(self, name: namedExpr) -> Tuple[namedExpr, str]:
def visit_NamedExpr(self, name: ast.NamedExpr) -> Tuple[ast.NamedExpr, str]:
# This method handles the 'walrus operator' repr of the target
# name if it's a local variable or _should_repr_global_name()
# thinks it's acceptable.
locs = ast.Call(self.builtin("locals"), [], [])
target_id = name.target.id # type: ignore[attr-defined]
inlocs = ast.Compare(astStr(target_id), [ast.In()], [locs])
inlocs = ast.Compare(ast.Constant(target_id), [ast.In()], [locs])
dorepr = self.helper("_should_repr_global_name", name)
test = ast.BoolOp(ast.Or(), [inlocs, dorepr])
expr = ast.IfExp(test, self.display(name), astStr(target_id))
expr = ast.IfExp(test, self.display(name), ast.Constant(target_id))
return name, self.explanation_param(expr)
def visit_Name(self, name: ast.Name) -> Tuple[ast.Name, str]:
# Display the repr of the name if it's a local variable or
# _should_repr_global_name() thinks it's acceptable.
locs = ast.Call(self.builtin("locals"), [], [])
inlocs = ast.Compare(astStr(name.id), [ast.In()], [locs])
inlocs = ast.Compare(ast.Constant(name.id), [ast.In()], [locs])
dorepr = self.helper("_should_repr_global_name", name)
test = ast.BoolOp(ast.Or(), [inlocs, dorepr])
expr = ast.IfExp(test, self.display(name), astStr(name.id))
expr = ast.IfExp(test, self.display(name), ast.Constant(name.id))
return name, self.explanation_param(expr)
def visit_BoolOp(self, boolop: ast.BoolOp) -> Tuple[ast.Name, str]:
@ -995,10 +980,10 @@ class AssertionRewriter(ast.NodeVisitor):
# cond is set in a prior loop iteration below
self.expl_stmts.append(ast.If(cond, fail_inner, [])) # noqa
self.expl_stmts = fail_inner
# Check if the left operand is a namedExpr and the value has already been visited
# Check if the left operand is a ast.NamedExpr and the value has already been visited
if (
isinstance(v, ast.Compare)
and isinstance(v.left, namedExpr)
and isinstance(v.left, ast.NamedExpr)
and v.left.target.id
in [
ast_expr.id
@ -1014,7 +999,7 @@ class AssertionRewriter(ast.NodeVisitor):
self.push_format_context()
res, expl = self.visit(v)
body.append(ast.Assign([ast.Name(res_var, ast.Store())], res))
expl_format = self.pop_format_context(astStr(expl))
expl_format = self.pop_format_context(ast.Constant(expl))
call = ast.Call(app, [expl_format], [])
self.expl_stmts.append(ast.Expr(call))
if i < levels:
@ -1026,7 +1011,7 @@ class AssertionRewriter(ast.NodeVisitor):
self.statements = body = inner
self.statements = save
self.expl_stmts = fail_save
expl_template = self.helper("_format_boolop", expl_list, astNum(is_or))
expl_template = self.helper("_format_boolop", expl_list, ast.Constant(is_or))
expl = self.pop_format_context(expl_template)
return ast.Name(res_var, ast.Load()), self.explanation_param(expl)
@ -1100,7 +1085,7 @@ class AssertionRewriter(ast.NodeVisitor):
comp.left = self.variables_overwrite[
comp.left.id
] # type:ignore[assignment]
if isinstance(comp.left, namedExpr):
if isinstance(comp.left, ast.NamedExpr):
self.variables_overwrite[
comp.left.target.id
] = comp.left # type:ignore[assignment]
@ -1116,7 +1101,7 @@ class AssertionRewriter(ast.NodeVisitor):
results = [left_res]
for i, op, next_operand in it:
if (
isinstance(next_operand, namedExpr)
isinstance(next_operand, ast.NamedExpr)
and isinstance(left_res, ast.Name)
and next_operand.target.id == left_res.id
):
@ -1129,9 +1114,9 @@ class AssertionRewriter(ast.NodeVisitor):
next_expl = f"({next_expl})"
results.append(next_res)
sym = BINOP_MAP[op.__class__]
syms.append(astStr(sym))
syms.append(ast.Constant(sym))
expl = f"{left_expl} {sym} {next_expl}"
expls.append(astStr(expl))
expls.append(ast.Constant(expl))
res_expr = ast.Compare(left_res, [op], [next_res])
self.statements.append(ast.Assign([store_names[i]], res_expr))
left_res, left_expl = next_res, next_expl
@ -1175,7 +1160,7 @@ def try_makedirs(cache_dir: Path) -> bool:
def get_cache_dir(file_path: Path) -> Path:
"""Return the cache directory to write .pyc files for the given .py file path."""
if sys.version_info >= (3, 8) and sys.pycache_prefix:
if sys.pycache_prefix:
# given:
# prefix = '/tmp/pycs'
# path = '/home/user/proj/test_app.py'

View File

@ -6,6 +6,7 @@ import json
import os
from pathlib import Path
from typing import Dict
from typing import final
from typing import Generator
from typing import Iterable
from typing import List
@ -18,7 +19,6 @@ from .pathlib import rm_rf
from .reports import CollectReport
from _pytest import nodes
from _pytest._io import TerminalWriter
from _pytest.compat import final
from _pytest.config import Config
from _pytest.config import ExitCode
from _pytest.config import hookimpl

View File

@ -11,11 +11,14 @@ from types import TracebackType
from typing import Any
from typing import AnyStr
from typing import BinaryIO
from typing import Final
from typing import final
from typing import Generator
from typing import Generic
from typing import Iterable
from typing import Iterator
from typing import List
from typing import Literal
from typing import NamedTuple
from typing import Optional
from typing import TextIO
@ -24,7 +27,6 @@ from typing import Type
from typing import TYPE_CHECKING
from typing import Union
from _pytest.compat import final
from _pytest.config import Config
from _pytest.config import hookimpl
from _pytest.config.argparsing import Parser
@ -35,11 +37,7 @@ from _pytest.nodes import Collector
from _pytest.nodes import File
from _pytest.nodes import Item
if TYPE_CHECKING:
from typing_extensions import Final
from typing_extensions import Literal
_CaptureMethod = Literal["fd", "sys", "no", "tee-sys"]
_CaptureMethod = Literal["fd", "sys", "no", "tee-sys"]
def pytest_addoption(parser: Parser) -> None:
@ -687,7 +685,7 @@ class MultiCapture(Generic[AnyStr]):
return CaptureResult(out, err) # type: ignore[arg-type]
def _get_multicapture(method: "_CaptureMethod") -> MultiCapture[str]:
def _get_multicapture(method: _CaptureMethod) -> MultiCapture[str]:
if method == "fd":
return MultiCapture(in_=FDCapture(0), out=FDCapture(1), err=FDCapture(2))
elif method == "sys":
@ -723,7 +721,7 @@ class CaptureManager:
needed to ensure the fixtures take precedence over the global capture.
"""
def __init__(self, method: "_CaptureMethod") -> None:
def __init__(self, method: _CaptureMethod) -> None:
self._method: Final = method
self._global_capturing: Optional[MultiCapture[str]] = None
self._capture_fixture: Optional[CaptureFixture[Any]] = None

View File

@ -12,26 +12,12 @@ from inspect import signature
from pathlib import Path
from typing import Any
from typing import Callable
from typing import Generic
from typing import Final
from typing import NoReturn
from typing import TYPE_CHECKING
from typing import TypeVar
import py
# fmt: off
# Workaround for https://github.com/sphinx-doc/sphinx/issues/10351.
# If `overload` is imported from `compat` instead of from `typing`,
# Sphinx doesn't recognize it as `overload` and the API docs for
# overloaded functions look good again. But type checkers handle
# it fine.
# fmt: on
if True:
from typing import overload as overload
if TYPE_CHECKING:
from typing_extensions import Final
_T = TypeVar("_T")
_S = TypeVar("_S")
@ -58,17 +44,6 @@ class NotSetType(enum.Enum):
NOTSET: Final = NotSetType.token # noqa: E305
# fmt: on
if sys.version_info >= (3, 8):
import importlib.metadata
importlib_metadata = importlib.metadata
else:
import importlib_metadata as importlib_metadata # noqa: F401
def _format_args(func: Callable[..., Any]) -> str:
return str(signature(func))
def is_generator(func: object) -> bool:
genfunc = inspect.isgeneratorfunction(func)
@ -338,47 +313,6 @@ def safe_isclass(obj: object) -> bool:
return False
if TYPE_CHECKING:
if sys.version_info >= (3, 8):
from typing import final as final
else:
from typing_extensions import final as final
elif sys.version_info >= (3, 8):
from typing import final as final
else:
def final(f):
return f
if sys.version_info >= (3, 8):
from functools import cached_property as cached_property
else:
class cached_property(Generic[_S, _T]):
__slots__ = ("func", "__doc__")
def __init__(self, func: Callable[[_S], _T]) -> None:
self.func = func
self.__doc__ = func.__doc__
@overload
def __get__(
self, instance: None, owner: type[_S] | None = ...
) -> cached_property[_S, _T]:
...
@overload
def __get__(self, instance: _S, owner: type[_S] | None = ...) -> _T:
...
def __get__(self, instance, owner=None):
if instance is None:
return self
value = instance.__dict__[self.func.__name__] = self.func(instance)
return value
def get_user_id() -> int | None:
"""Return the current user id, or None if we cannot get it reliably on the current platform."""
# win32 does not have a getuid() function.

View File

@ -5,6 +5,7 @@ import copy
import dataclasses
import enum
import glob
import importlib.metadata
import inspect
import os
import re
@ -21,6 +22,7 @@ from typing import Any
from typing import Callable
from typing import cast
from typing import Dict
from typing import final
from typing import Generator
from typing import IO
from typing import Iterable
@ -48,8 +50,6 @@ from .findpaths import determine_setup
from _pytest._code import ExceptionInfo
from _pytest._code import filter_traceback
from _pytest._io import TerminalWriter
from _pytest.compat import final
from _pytest.compat import importlib_metadata # type: ignore[attr-defined]
from _pytest.outcomes import fail
from _pytest.outcomes import Skipped
from _pytest.pathlib import absolutepath
@ -257,7 +257,8 @@ default_plugins = essential_plugins + (
"logging",
"reports",
"python_path",
*(["unraisableexception", "threadexception"] if sys.version_info >= (3, 8) else []),
"unraisableexception",
"threadexception",
"faulthandler",
)
@ -1216,7 +1217,7 @@ class Config:
package_files = (
str(file)
for dist in importlib_metadata.distributions()
for dist in importlib.metadata.distributions()
if any(ep.group == "pytest11" for ep in dist.entry_points)
for file in dist.files or []
)

View File

@ -7,6 +7,7 @@ from typing import Any
from typing import Callable
from typing import cast
from typing import Dict
from typing import final
from typing import List
from typing import Mapping
from typing import NoReturn
@ -17,7 +18,6 @@ from typing import TYPE_CHECKING
from typing import Union
import _pytest._io
from _pytest.compat import final
from _pytest.config.exceptions import UsageError
from _pytest.deprecated import ARGUMENT_PERCENT_DEFAULT
from _pytest.deprecated import ARGUMENT_TYPE_STR

View File

@ -1,4 +1,4 @@
from _pytest.compat import final
from typing import final
@final

View File

@ -13,6 +13,7 @@ from typing import Any
from typing import Callable
from typing import cast
from typing import Dict
from typing import final
from typing import Generator
from typing import Generic
from typing import Iterable
@ -21,6 +22,7 @@ from typing import List
from typing import MutableMapping
from typing import NoReturn
from typing import Optional
from typing import overload
from typing import Sequence
from typing import Set
from typing import Tuple
@ -35,10 +37,8 @@ from _pytest._code import getfslineno
from _pytest._code.code import FormattedExcinfo
from _pytest._code.code import TerminalRepr
from _pytest._io import TerminalWriter
from _pytest.compat import _format_args
from _pytest.compat import _PytestWrapper
from _pytest.compat import assert_never
from _pytest.compat import final
from _pytest.compat import get_real_func
from _pytest.compat import get_real_method
from _pytest.compat import getfuncargnames
@ -47,7 +47,6 @@ from _pytest.compat import getlocation
from _pytest.compat import is_generator
from _pytest.compat import NOTSET
from _pytest.compat import NotSetType
from _pytest.compat import overload
from _pytest.compat import safe_getattr
from _pytest.config import _PluggyPlugin
from _pytest.config import Config
@ -729,8 +728,10 @@ class FixtureRequest:
p = bestrelpath(session.path, fs)
else:
p = fs
args = _format_args(factory)
lines.append("%s:%d: def %s%s" % (p, lineno + 1, factory.__name__, args))
lines.append(
"%s:%d: def %s%s"
% (p, lineno + 1, factory.__name__, inspect.signature(factory))
)
return lines
def __repr__(self) -> str:

View File

@ -3,6 +3,8 @@ import dataclasses
import shlex
import subprocess
from pathlib import Path
from typing import Final
from typing import final
from typing import List
from typing import Optional
from typing import TYPE_CHECKING
@ -11,7 +13,6 @@ from typing import Union
from iniconfig import SectionWrapper
from _pytest.cacheprovider import Cache
from _pytest.compat import final
from _pytest.compat import LEGACY_PATH
from _pytest.compat import legacy_path
from _pytest.config import Config
@ -32,8 +33,6 @@ from _pytest.terminal import TerminalReporter
from _pytest.tmpdir import TempPathFactory
if TYPE_CHECKING:
from typing_extensions import Final
import pexpect

View File

@ -13,6 +13,7 @@ from logging import LogRecord
from pathlib import Path
from typing import AbstractSet
from typing import Dict
from typing import final
from typing import Generator
from typing import List
from typing import Mapping
@ -25,7 +26,6 @@ from typing import Union
from _pytest import nodes
from _pytest._io import TerminalWriter
from _pytest.capture import CaptureManager
from _pytest.compat import final
from _pytest.config import _strtobool
from _pytest.config import Config
from _pytest.config import create_terminal_writer

View File

@ -9,10 +9,12 @@ import sys
from pathlib import Path
from typing import Callable
from typing import Dict
from typing import final
from typing import FrozenSet
from typing import Iterator
from typing import List
from typing import Optional
from typing import overload
from typing import Sequence
from typing import Set
from typing import Tuple
@ -22,8 +24,6 @@ from typing import Union
import _pytest._code
from _pytest import nodes
from _pytest.compat import final
from _pytest.compat import overload
from _pytest.config import Config
from _pytest.config import directory_arg
from _pytest.config import ExitCode

View File

@ -18,7 +18,6 @@ import ast
import dataclasses
import enum
import re
import sys
import types
from typing import Callable
from typing import Iterator
@ -27,12 +26,6 @@ from typing import NoReturn
from typing import Optional
from typing import Sequence
if sys.version_info >= (3, 8):
astNameConstant = ast.Constant
else:
astNameConstant = ast.NameConstant
__all__ = [
"Expression",
"ParseError",
@ -138,7 +131,7 @@ IDENT_PREFIX = "$"
def expression(s: Scanner) -> ast.Expression:
if s.accept(TokenType.EOF):
ret: ast.expr = astNameConstant(False)
ret: ast.expr = ast.Constant(False)
else:
ret = expr(s)
s.accept(TokenType.EOF, reject=True)

View File

@ -5,6 +5,7 @@ import warnings
from typing import Any
from typing import Callable
from typing import Collection
from typing import final
from typing import Iterable
from typing import Iterator
from typing import List
@ -23,7 +24,6 @@ from typing import Union
from .._code import getfslineno
from ..compat import ascii_escaped
from ..compat import final
from ..compat import NOTSET
from ..compat import NotSetType
from _pytest.config import Config
@ -374,7 +374,9 @@ def get_unpacked_marks(
if not consider_mro:
mark_lists = [obj.__dict__.get("pytestmark", [])]
else:
mark_lists = [x.__dict__.get("pytestmark", []) for x in obj.__mro__]
mark_lists = [
x.__dict__.get("pytestmark", []) for x in reversed(obj.__mro__)
]
mark_list = []
for item in mark_lists:
if isinstance(item, list):

View File

@ -5,6 +5,7 @@ import sys
import warnings
from contextlib import contextmanager
from typing import Any
from typing import final
from typing import Generator
from typing import List
from typing import Mapping
@ -15,7 +16,6 @@ from typing import Tuple
from typing import TypeVar
from typing import Union
from _pytest.compat import final
from _pytest.fixtures import fixture
from _pytest.warning_types import PytestWarning

View File

@ -1,5 +1,6 @@
import os
import warnings
from functools import cached_property
from inspect import signature
from pathlib import Path
from typing import Any
@ -23,7 +24,6 @@ from _pytest._code import getfslineno
from _pytest._code.code import ExceptionInfo
from _pytest._code.code import TerminalRepr
from _pytest._code.code import Traceback
from _pytest.compat import cached_property
from _pytest.compat import LEGACY_PATH
from _pytest.config import Config
from _pytest.config import ConftestImportFailure

View File

@ -7,23 +7,12 @@ from typing import Callable
from typing import cast
from typing import NoReturn
from typing import Optional
from typing import Protocol
from typing import Type
from typing import TypeVar
from _pytest.deprecated import KEYWORD_MSG_ARG
TYPE_CHECKING = False # Avoid circular import through compat.
if TYPE_CHECKING:
from typing_extensions import Protocol
else:
# typing.Protocol is only available starting from Python 3.8. It is also
# available from typing_extensions, but we don't want a runtime dependency
# on that. So use a dummy runtime implementation.
from typing import Generic
Protocol = Generic
class OutcomeException(BaseException):
"""OutcomeException and its subclass instances indicate and contain info

View File

@ -523,6 +523,8 @@ def import_path(
if mode is ImportMode.importlib:
module_name = module_name_from_path(path, root)
with contextlib.suppress(KeyError):
return sys.modules[module_name]
for meta_importer in sys.meta_path:
spec = meta_importer.find_spec(module_name, [str(path.parent)])
@ -633,6 +635,9 @@ def insert_missing_modules(modules: Dict[str, ModuleType], module_name: str) ->
otherwise "src.tests.test_foo" is not importable by ``__import__``.
"""
module_parts = module_name.split(".")
child_module: Union[ModuleType, None] = None
module: Union[ModuleType, None] = None
child_name: str = ""
while module_name:
if module_name not in modules:
try:
@ -642,13 +647,22 @@ def insert_missing_modules(modules: Dict[str, ModuleType], module_name: str) ->
# ourselves to fall back to creating a dummy module.
if not sys.meta_path:
raise ModuleNotFoundError
importlib.import_module(module_name)
module = importlib.import_module(module_name)
except ModuleNotFoundError:
module = ModuleType(
module_name,
doc="Empty module created by pytest's importmode=importlib.",
)
else:
module = modules[module_name]
if child_module:
# Add child attribute to the parent that can reference the child
# modules.
if not hasattr(module, child_name):
setattr(module, child_name, child_module)
modules[module_name] = module
# Keep track of the child module while moving up the tree.
child_module, child_name = module, module_name.rpartition(".")[-1]
module_parts.pop(-1)
module_name = ".".join(module_parts)

View File

@ -20,10 +20,13 @@ from pathlib import Path
from typing import Any
from typing import Callable
from typing import Dict
from typing import Final
from typing import final
from typing import Generator
from typing import IO
from typing import Iterable
from typing import List
from typing import Literal
from typing import Optional
from typing import overload
from typing import Sequence
@ -40,7 +43,6 @@ from iniconfig import SectionWrapper
from _pytest import timing
from _pytest._code import Source
from _pytest.capture import _get_multicapture
from _pytest.compat import final
from _pytest.compat import NOTSET
from _pytest.compat import NotSetType
from _pytest.config import _PluggyPlugin
@ -68,11 +70,7 @@ from _pytest.reports import TestReport
from _pytest.tmpdir import TempPathFactory
from _pytest.warning_types import PytestWarning
if TYPE_CHECKING:
from typing_extensions import Final
from typing_extensions import Literal
import pexpect

View File

@ -15,6 +15,7 @@ from pathlib import Path
from typing import Any
from typing import Callable
from typing import Dict
from typing import final
from typing import Generator
from typing import Iterable
from typing import Iterator
@ -40,7 +41,6 @@ from _pytest._io import TerminalWriter
from _pytest._io.saferepr import saferepr
from _pytest.compat import ascii_escaped
from _pytest.compat import assert_never
from _pytest.compat import final
from _pytest.compat import get_default_arg_names
from _pytest.compat import get_real_func
from _pytest.compat import getimfunc

View File

@ -9,9 +9,11 @@ from typing import Any
from typing import Callable
from typing import cast
from typing import ContextManager
from typing import final
from typing import List
from typing import Mapping
from typing import Optional
from typing import overload
from typing import Pattern
from typing import Sequence
from typing import Tuple
@ -20,17 +22,14 @@ from typing import TYPE_CHECKING
from typing import TypeVar
from typing import Union
import _pytest._code
from _pytest.compat import STRING_TYPES
from _pytest.outcomes import fail
if TYPE_CHECKING:
from numpy import ndarray
import _pytest._code
from _pytest.compat import final
from _pytest.compat import STRING_TYPES
from _pytest.compat import overload
from _pytest.outcomes import fail
def _non_numeric_type_error(value, at: Optional[str]) -> TypeError:
at_str = f" at {at}" if at else ""
return TypeError(

View File

@ -5,18 +5,18 @@ from pprint import pformat
from types import TracebackType
from typing import Any
from typing import Callable
from typing import final
from typing import Generator
from typing import Iterator
from typing import List
from typing import Optional
from typing import overload
from typing import Pattern
from typing import Tuple
from typing import Type
from typing import TypeVar
from typing import Union
from _pytest.compat import final
from _pytest.compat import overload
from _pytest.deprecated import check_ispytest
from _pytest.deprecated import WARNS_NONE_ARG
from _pytest.fixtures import fixture
@ -117,10 +117,10 @@ def warns( # noqa: F811
warning of that class or classes.
This helper produces a list of :class:`warnings.WarningMessage` objects, one for
each warning raised (regardless of whether it is an ``expected_warning`` or not).
each warning emitted (regardless of whether it is an ``expected_warning`` or not).
Since pytest 8.0, unmatched warnings are also re-emitted when the context closes.
This function can be used as a context manager, which will capture all the raised
warnings inside it::
This function can be used as a context manager::
>>> import pytest
>>> with pytest.warns(RuntimeWarning):
@ -135,8 +135,9 @@ def warns( # noqa: F811
>>> with pytest.warns(UserWarning, match=r'must be \d+$'):
... warnings.warn("value must be 42", UserWarning)
>>> with pytest.warns(UserWarning, match=r'must be \d+$'):
... warnings.warn("this is not here", UserWarning)
>>> with pytest.warns(UserWarning): # catch re-emitted warning
... with pytest.warns(UserWarning, match=r'must be \d+$'):
... warnings.warn("this is not here", UserWarning)
Traceback (most recent call last):
...
Failed: DID NOT WARN. No warnings of type ...UserWarning... were emitted...
@ -277,6 +278,12 @@ class WarningsChecker(WarningsRecorder):
self.expected_warning = expected_warning_tup
self.match_expr = match_expr
def matches(self, warning: warnings.WarningMessage) -> bool:
assert self.expected_warning is not None
return issubclass(warning.category, self.expected_warning) and bool(
self.match_expr is None or re.search(self.match_expr, str(warning.message))
)
def __exit__(
self,
exc_type: Optional[Type[BaseException]],
@ -287,27 +294,34 @@ class WarningsChecker(WarningsRecorder):
__tracebackhide__ = True
if self.expected_warning is None:
# nothing to do in this deprecated case, see WARNS_NONE_ARG above
return
def found_str():
return pformat([record.message for record in self], indent=2)
# only check if we're not currently handling an exception
if exc_type is None and exc_val is None and exc_tb is None:
if self.expected_warning is not None:
if not any(issubclass(r.category, self.expected_warning) for r in self):
__tracebackhide__ = True
fail(
f"DID NOT WARN. No warnings of type {self.expected_warning} were emitted.\n"
f"The list of emitted warnings is: {found_str()}."
try:
if not any(issubclass(w.category, self.expected_warning) for w in self):
fail(
f"DID NOT WARN. No warnings of type {self.expected_warning} were emitted.\n"
f" Emitted warnings: {found_str()}."
)
elif not any(self.matches(w) for w in self):
fail(
f"DID NOT WARN. No warnings of type {self.expected_warning} matching the regex were emitted.\n"
f" Regex: {self.match_expr}\n"
f" Emitted warnings: {found_str()}."
)
finally:
# Whether or not any warnings matched, we want to re-emit all unmatched warnings.
for w in self:
if not self.matches(w):
warnings.warn_explicit(
str(w.message),
w.message.__class__, # type: ignore[arg-type]
w.filename,
w.lineno,
module=w.__module__,
source=w.source,
)
elif self.match_expr is not None:
for r in self:
if issubclass(r.category, self.expected_warning):
if re.compile(self.match_expr).search(str(r.message)):
break
else:
fail(
f"""\
DID NOT WARN. No warnings of type {self.expected_warning} matching the regex were emitted.
Regex: {self.match_expr}
Emitted warnings: {found_str()}"""
)

View File

@ -5,6 +5,7 @@ from pprint import pprint
from typing import Any
from typing import cast
from typing import Dict
from typing import final
from typing import Iterable
from typing import Iterator
from typing import List
@ -29,7 +30,6 @@ from _pytest._code.code import ReprLocals
from _pytest._code.code import ReprTraceback
from _pytest._code.code import TerminalRepr
from _pytest._io import TerminalWriter
from _pytest.compat import final
from _pytest.config import Config
from _pytest.nodes import Collector
from _pytest.nodes import Item

View File

@ -6,6 +6,7 @@ import sys
from typing import Callable
from typing import cast
from typing import Dict
from typing import final
from typing import Generic
from typing import List
from typing import Optional
@ -23,7 +24,6 @@ from _pytest import timing
from _pytest._code.code import ExceptionChainRepr
from _pytest._code.code import ExceptionInfo
from _pytest._code.code import TerminalRepr
from _pytest.compat import final
from _pytest.config.argparsing import Parser
from _pytest.deprecated import check_ispytest
from _pytest.nodes import Collector

View File

@ -18,6 +18,7 @@ from typing import Callable
from typing import cast
from typing import ClassVar
from typing import Dict
from typing import final
from typing import Generator
from typing import List
from typing import Mapping
@ -40,7 +41,6 @@ from _pytest._code.code import ExceptionRepr
from _pytest._io import TerminalWriter
from _pytest._io.wcwidth import wcswidth
from _pytest.assertion.util import running_on_ci
from _pytest.compat import final
from _pytest.config import _PluggyPlugin
from _pytest.config import Config
from _pytest.config import ExitCode

View File

@ -7,38 +7,32 @@ from pathlib import Path
from shutil import rmtree
from typing import Any
from typing import Dict
from typing import final
from typing import Generator
from typing import Literal
from typing import Optional
from typing import TYPE_CHECKING
from typing import Union
from _pytest.nodes import Item
from _pytest.reports import CollectReport
from _pytest.stash import StashKey
if TYPE_CHECKING:
from typing_extensions import Literal
RetentionType = Literal["all", "failed", "none"]
from _pytest.config.argparsing import Parser
from .pathlib import cleanup_dead_symlinks
from .pathlib import LOCK_TIMEOUT
from .pathlib import make_numbered_dir
from .pathlib import make_numbered_dir_with_cleanup
from .pathlib import rm_rf
from .pathlib import cleanup_dead_symlinks
from _pytest.compat import final, get_user_id
from _pytest.compat import get_user_id
from _pytest.config import Config
from _pytest.config import ExitCode
from _pytest.config import hookimpl
from _pytest.config.argparsing import Parser
from _pytest.deprecated import check_ispytest
from _pytest.fixtures import fixture
from _pytest.fixtures import FixtureRequest
from _pytest.monkeypatch import MonkeyPatch
from _pytest.nodes import Item
from _pytest.reports import CollectReport
from _pytest.stash import StashKey
tmppath_result_key = StashKey[Dict[str, bool]]()
RetentionType = Literal["all", "failed", "none"]
@final

View File

@ -3,12 +3,11 @@ import inspect
import warnings
from types import FunctionType
from typing import Any
from typing import final
from typing import Generic
from typing import Type
from typing import TypeVar
from _pytest.compat import final
class PytestWarning(UserWarning):
"""Base class for all warnings emitted by pytest."""

View File

@ -1,10 +1,10 @@
import dataclasses
import importlib.metadata
import os
import sys
import types
import pytest
from _pytest.compat import importlib_metadata
from _pytest.config import ExitCode
from _pytest.pathlib import symlink_or_skip
from _pytest.pytester import Pytester
@ -139,7 +139,7 @@ class TestGeneralUsage:
def my_dists():
return (DummyDist(entry_points),)
monkeypatch.setattr(importlib_metadata, "distributions", my_dists)
monkeypatch.setattr(importlib.metadata, "distributions", my_dists)
params = ("-p", "mycov") if load_cov_early else ()
pytester.runpytest_inprocess(*params)
if load_cov_early:
@ -1315,3 +1315,38 @@ def test_function_return_non_none_warning(pytester: Pytester) -> None:
)
res = pytester.runpytest()
res.stdout.fnmatch_lines(["*Did you mean to use `assert` instead of `return`?*"])
def test_doctest_and_normal_imports_with_importlib(pytester: Pytester) -> None:
"""
Regression test for #10811: previously import_path with ImportMode.importlib would
not return a module if already in sys.modules, resulting in modules being imported
multiple times, which causes problems with modules that have import side effects.
"""
# Uses the exact reproducer form #10811, given it is very minimal
# and illustrates the problem well.
pytester.makepyfile(
**{
"pmxbot/commands.py": "from . import logging",
"pmxbot/logging.py": "",
"tests/__init__.py": "",
"tests/test_commands.py": """
import importlib
from pmxbot import logging
class TestCommands:
def test_boo(self):
assert importlib.import_module('pmxbot.logging') is logging
""",
}
)
pytester.makeini(
"""
[pytest]
addopts=
--doctest-modules
--import-mode importlib
"""
)
result = pytester.runpytest_subprocess()
result.stdout.fnmatch_lines("*1 passed*")

View File

@ -439,14 +439,9 @@ comment 4
'''
for line in range(2, 6):
assert str(getstatement(line, source)) == " x = 1"
if sys.version_info >= (3, 8) or hasattr(sys, "pypy_version_info"):
tqs_start = 8
else:
tqs_start = 10
assert str(getstatement(10, source)) == '"""'
for line in range(6, tqs_start):
for line in range(6, 8):
assert str(getstatement(line, source)) == " assert False"
for line in range(tqs_start, 10):
for line in range(8, 10):
assert str(getstatement(line, source)) == '"""\ncomment 4\n"""'

View File

@ -19,7 +19,6 @@ from hypothesis import strategies
import pytest
from _pytest import fixtures
from _pytest import python
from _pytest.compat import _format_args
from _pytest.compat import getfuncargnames
from _pytest.compat import NOTSET
from _pytest.outcomes import fail
@ -1036,27 +1035,6 @@ class TestMetafunc:
"""
)
def test_format_args(self) -> None:
def function1():
pass
assert _format_args(function1) == "()"
def function2(arg1):
pass
assert _format_args(function2) == "(arg1)"
def function3(arg1, arg2="qwe"):
pass
assert _format_args(function3) == "(arg1, arg2='qwe')"
def function4(arg1, *args, **kwargs):
pass
assert _format_args(function4) == "(arg1, *args, **kwargs)"
class TestMetafuncFunctional:
def test_attributes(self, pytester: Pytester) -> None:

View File

@ -199,8 +199,8 @@ class TestImportHookInstallation:
return check
""",
"mainwrapper.py": """\
import importlib.metadata
import pytest
from _pytest.compat import importlib_metadata
class DummyEntryPoint(object):
name = 'spam'
@ -220,7 +220,7 @@ class TestImportHookInstallation:
def distributions():
return (DummyDistInfo(),)
importlib_metadata.distributions = distributions
importlib.metadata.distributions = distributions
pytest.main()
""",
"test_foo.py": """\

View File

@ -131,9 +131,8 @@ class TestAssertionRewrite:
for n in [node, *ast.iter_child_nodes(node)]:
assert n.lineno == 3
assert n.col_offset == 0
if sys.version_info >= (3, 8):
assert n.end_lineno == 6
assert n.end_col_offset == 3
assert n.end_lineno == 6
assert n.end_col_offset == 3
def test_dont_rewrite(self) -> None:
s = """'PYTEST_DONT_REWRITE'\nassert 14"""
@ -1270,9 +1269,6 @@ class TestIssue2121:
result.stdout.fnmatch_lines(["*E*assert (1 + 1) == 3"])
@pytest.mark.skipif(
sys.version_info < (3, 8), reason="walrus operator not available in py<38"
)
class TestIssue10743:
def test_assertion_walrus_operator(self, pytester: Pytester) -> None:
pytester.makepyfile(
@ -1441,9 +1437,6 @@ class TestIssue10743:
assert result.ret == 0
@pytest.mark.skipif(
sys.version_info < (3, 8), reason="walrus operator not available in py<38"
)
class TestIssue11028:
def test_assertion_walrus_operator_in_operand(self, pytester: Pytester) -> None:
pytester.makepyfile(
@ -1957,16 +1950,10 @@ class TestPyCacheDir:
)
def test_get_cache_dir(self, monkeypatch, prefix, source, expected) -> None:
monkeypatch.delenv("PYTHONPYCACHEPREFIX", raising=False)
if prefix is not None and sys.version_info < (3, 8):
pytest.skip("pycache_prefix not available in py<38")
monkeypatch.setattr(sys, "pycache_prefix", prefix, raising=False)
assert get_cache_dir(Path(source)) == Path(expected)
@pytest.mark.skipif(
sys.version_info < (3, 8), reason="pycache_prefix not available in py<38"
)
@pytest.mark.skipif(
sys.version_info[:2] == (3, 9) and sys.platform.startswith("win"),
reason="#9298",

View File

@ -1,5 +1,6 @@
import enum
import sys
from functools import cached_property
from functools import partial
from functools import wraps
from typing import TYPE_CHECKING
@ -8,7 +9,6 @@ from typing import Union
import pytest
from _pytest.compat import _PytestWrapper
from _pytest.compat import assert_never
from _pytest.compat import cached_property
from _pytest.compat import get_real_func
from _pytest.compat import is_generator
from _pytest.compat import safe_getattr

View File

@ -1,4 +1,5 @@
import dataclasses
import importlib.metadata
import os
import re
import sys
@ -13,7 +14,6 @@ from typing import Union
import _pytest._code
import pytest
from _pytest.compat import importlib_metadata
from _pytest.config import _get_plugin_specs_as_list
from _pytest.config import _iter_rewritable_modules
from _pytest.config import _strtobool
@ -475,7 +475,7 @@ class TestParseIni:
pytester.makepyfile(myplugin1_module="# my plugin module")
pytester.syspathinsert()
monkeypatch.setattr(importlib_metadata, "distributions", my_dists)
monkeypatch.setattr(importlib.metadata, "distributions", my_dists)
monkeypatch.delenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", raising=False)
pytester.makeini(ini_file_text)
@ -1003,7 +1003,7 @@ def test_preparse_ordering_with_setuptools(
def my_dists():
return (Dist,)
monkeypatch.setattr(importlib_metadata, "distributions", my_dists)
monkeypatch.setattr(importlib.metadata, "distributions", my_dists)
pytester.makeconftest(
"""
pytest_plugins = "mytestplugin",
@ -1036,7 +1036,7 @@ def test_setuptools_importerror_issue1479(
def distributions():
return (Distribution(),)
monkeypatch.setattr(importlib_metadata, "distributions", distributions)
monkeypatch.setattr(importlib.metadata, "distributions", distributions)
with pytest.raises(ImportError):
pytester.parseconfig()
@ -1063,7 +1063,7 @@ def test_importlib_metadata_broken_distribution(
def distributions():
return (Distribution(),)
monkeypatch.setattr(importlib_metadata, "distributions", distributions)
monkeypatch.setattr(importlib.metadata, "distributions", distributions)
pytester.parseconfig()
@ -1091,7 +1091,7 @@ def test_plugin_preparse_prevents_setuptools_loading(
def distributions():
return (Distribution(),)
monkeypatch.setattr(importlib_metadata, "distributions", distributions)
monkeypatch.setattr(importlib.metadata, "distributions", distributions)
args = ("-p", "no:mytestplugin") if block_it else ()
config = pytester.parseconfig(*args)
config.pluginmanager.import_plugin("mytestplugin")
@ -1140,7 +1140,7 @@ def test_disable_plugin_autoload(
return (Distribution(),)
monkeypatch.setenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", "1")
monkeypatch.setattr(importlib_metadata, "distributions", distributions)
monkeypatch.setattr(importlib.metadata, "distributions", distributions)
monkeypatch.setitem(sys.modules, "mytestplugin", PseudoPlugin()) # type: ignore[misc]
config = pytester.parseconfig(*parse_args)
has_loaded = config.pluginmanager.get_plugin("mytestplugin") is not None

View File

@ -1,7 +1,7 @@
from _pytest.compat import importlib_metadata
import importlib.metadata
def test_pytest_entry_points_are_identical():
dist = importlib_metadata.distribution("pytest")
dist = importlib.metadata.distribution("pytest")
entry_map = {ep.name: ep for ep in dist.entry_points}
assert entry_map["pytest"].value == entry_map["py.test"].value

View File

@ -1130,6 +1130,41 @@ def test_mark_mro() -> None:
all_marks = get_unpacked_marks(C)
assert all_marks == [xfail("c").mark, xfail("a").mark, xfail("b").mark]
assert all_marks == [xfail("b").mark, xfail("a").mark, xfail("c").mark]
assert get_unpacked_marks(C, consider_mro=False) == [xfail("c").mark]
# @pytest.mark.issue("https://github.com/pytest-dev/pytest/issues/10447")
def test_mark_fixture_order_mro(pytester: Pytester):
"""This ensures we walk marks of the mro starting with the base classes
the action at a distance fixtures are taken as minimal example from a real project
"""
foo = pytester.makepyfile(
"""
import pytest
@pytest.fixture
def add_attr1(request):
request.instance.attr1 = object()
@pytest.fixture
def add_attr2(request):
request.instance.attr2 = request.instance.attr1
@pytest.mark.usefixtures('add_attr1')
class Parent:
pass
@pytest.mark.usefixtures('add_attr2')
class TestThings(Parent):
def test_attrs(self):
assert self.attr1 == self.attr2
"""
)
result = pytester.runpytest(foo)
result.assert_outcomes(passed=1)

View File

@ -7,6 +7,7 @@ from textwrap import dedent
from types import ModuleType
from typing import Any
from typing import Generator
from typing import Iterator
import pytest
from _pytest.monkeypatch import MonkeyPatch
@ -282,29 +283,36 @@ class TestImportPath:
import_path(tmp_path / "invalid.py", root=tmp_path)
@pytest.fixture
def simple_module(self, tmp_path: Path) -> Path:
fn = tmp_path / "_src/tests/mymod.py"
def simple_module(
self, tmp_path: Path, request: pytest.FixtureRequest
) -> Iterator[Path]:
name = f"mymod_{request.node.name}"
fn = tmp_path / f"_src/tests/{name}.py"
fn.parent.mkdir(parents=True)
fn.write_text("def foo(x): return 40 + x", encoding="utf-8")
return fn
module_name = module_name_from_path(fn, root=tmp_path)
yield fn
sys.modules.pop(module_name, None)
def test_importmode_importlib(self, simple_module: Path, tmp_path: Path) -> None:
def test_importmode_importlib(
self, simple_module: Path, tmp_path: Path, request: pytest.FixtureRequest
) -> None:
"""`importlib` mode does not change sys.path."""
module = import_path(simple_module, mode="importlib", root=tmp_path)
assert module.foo(2) == 42 # type: ignore[attr-defined]
assert str(simple_module.parent) not in sys.path
assert module.__name__ in sys.modules
assert module.__name__ == "_src.tests.mymod"
assert module.__name__ == f"_src.tests.mymod_{request.node.name}"
assert "_src" in sys.modules
assert "_src.tests" in sys.modules
def test_importmode_twice_is_different_module(
def test_remembers_previous_imports(
self, simple_module: Path, tmp_path: Path
) -> None:
"""`importlib` mode always returns a new module."""
"""`importlib` mode called remembers previous module (#10341, #10811)."""
module1 = import_path(simple_module, mode="importlib", root=tmp_path)
module2 = import_path(simple_module, mode="importlib", root=tmp_path)
assert module1 is not module2
assert module1 is module2
def test_no_meta_path_found(
self, simple_module: Path, monkeypatch: MonkeyPatch, tmp_path: Path
@ -317,6 +325,9 @@ class TestImportPath:
# mode='importlib' fails if no spec is found to load the module
import importlib.util
# Force module to be re-imported.
del sys.modules[module.__name__]
monkeypatch.setattr(
importlib.util, "spec_from_file_location", lambda *args: None
)
@ -592,3 +603,15 @@ class TestImportLibMode:
modules = {}
insert_missing_modules(modules, "")
assert modules == {}
def test_parent_contains_child_module_attribute(
self, monkeypatch: MonkeyPatch, tmp_path: Path
):
monkeypatch.chdir(tmp_path)
# Use 'xxx' and 'xxy' as parent names as they are unlikely to exist and
# don't end up being imported.
modules = {"xxx.tests.foo": ModuleType("xxx.tests.foo")}
insert_missing_modules(modules, "xxx.tests.foo")
assert sorted(modules) == ["xxx", "xxx.tests", "xxx.tests.foo"]
assert modules["xxx"].tests is modules["xxx.tests"]
assert modules["xxx.tests"].foo is modules["xxx.tests.foo"]

View File

@ -172,22 +172,6 @@ class TestDeprecatedCall:
with pytest.deprecated_call():
assert f() == 10
@pytest.mark.parametrize("mode", ["context_manager", "call"])
def test_deprecated_call_exception_is_raised(self, mode) -> None:
"""If the block of the code being tested by deprecated_call() raises an exception,
it must raise the exception undisturbed.
"""
def f():
raise ValueError("some exception")
with pytest.raises(ValueError, match="some exception"):
if mode == "call":
pytest.deprecated_call(f)
else:
with pytest.deprecated_call():
f()
def test_deprecated_call_specificity(self) -> None:
other_warnings = [
Warning,
@ -203,19 +187,21 @@ class TestDeprecatedCall:
def f():
warnings.warn(warning("hi"))
with pytest.raises(pytest.fail.Exception):
pytest.deprecated_call(f)
with pytest.raises(pytest.fail.Exception):
with pytest.deprecated_call():
f()
with pytest.warns(warning):
with pytest.raises(pytest.fail.Exception):
pytest.deprecated_call(f)
with pytest.raises(pytest.fail.Exception):
with pytest.deprecated_call():
f()
def test_deprecated_call_supports_match(self) -> None:
with pytest.deprecated_call(match=r"must be \d+$"):
warnings.warn("value must be 42", DeprecationWarning)
with pytest.raises(pytest.fail.Exception):
with pytest.deprecated_call(match=r"must be \d+$"):
warnings.warn("this is not here", DeprecationWarning)
with pytest.deprecated_call():
with pytest.raises(pytest.fail.Exception, match="DID NOT WARN"):
with pytest.deprecated_call(match=r"must be \d+$"):
warnings.warn("this is not here", DeprecationWarning)
class TestWarns:
@ -227,8 +213,9 @@ class TestWarns:
def test_several_messages(self) -> None:
# different messages, b/c Python suppresses multiple identical warnings
pytest.warns(RuntimeWarning, lambda: warnings.warn("w1", RuntimeWarning))
with pytest.raises(pytest.fail.Exception):
pytest.warns(UserWarning, lambda: warnings.warn("w2", RuntimeWarning))
with pytest.warns(RuntimeWarning):
with pytest.raises(pytest.fail.Exception):
pytest.warns(UserWarning, lambda: warnings.warn("w2", RuntimeWarning))
pytest.warns(RuntimeWarning, lambda: warnings.warn("w3", RuntimeWarning))
def test_function(self) -> None:
@ -243,13 +230,14 @@ class TestWarns:
pytest.warns(
(RuntimeWarning, SyntaxWarning), lambda: warnings.warn("w2", SyntaxWarning)
)
pytest.raises(
pytest.fail.Exception,
lambda: pytest.warns(
(RuntimeWarning, SyntaxWarning),
lambda: warnings.warn("w3", UserWarning),
),
)
with pytest.warns():
pytest.raises(
pytest.fail.Exception,
lambda: pytest.warns(
(RuntimeWarning, SyntaxWarning),
lambda: warnings.warn("w3", UserWarning),
),
)
def test_as_contextmanager(self) -> None:
with pytest.warns(RuntimeWarning):
@ -258,20 +246,22 @@ class TestWarns:
with pytest.warns(UserWarning):
warnings.warn("user", UserWarning)
with pytest.raises(pytest.fail.Exception) as excinfo:
with pytest.warns(RuntimeWarning):
warnings.warn("user", UserWarning)
with pytest.warns():
with pytest.raises(pytest.fail.Exception) as excinfo:
with pytest.warns(RuntimeWarning):
warnings.warn("user", UserWarning)
excinfo.match(
r"DID NOT WARN. No warnings of type \(.+RuntimeWarning.+,\) were emitted.\n"
r"The list of emitted warnings is: \[UserWarning\('user',?\)\]."
r" Emitted warnings: \[UserWarning\('user',?\)\]."
)
with pytest.raises(pytest.fail.Exception) as excinfo:
with pytest.warns(UserWarning):
warnings.warn("runtime", RuntimeWarning)
with pytest.warns():
with pytest.raises(pytest.fail.Exception) as excinfo:
with pytest.warns(UserWarning):
warnings.warn("runtime", RuntimeWarning)
excinfo.match(
r"DID NOT WARN. No warnings of type \(.+UserWarning.+,\) were emitted.\n"
r"The list of emitted warnings is: \[RuntimeWarning\('runtime',?\)]."
r" Emitted warnings: \[RuntimeWarning\('runtime',?\)]."
)
with pytest.raises(pytest.fail.Exception) as excinfo:
@ -279,19 +269,20 @@ class TestWarns:
pass
excinfo.match(
r"DID NOT WARN. No warnings of type \(.+UserWarning.+,\) were emitted.\n"
r"The list of emitted warnings is: \[\]."
r" Emitted warnings: \[\]."
)
warning_classes = (UserWarning, FutureWarning)
with pytest.raises(pytest.fail.Exception) as excinfo:
with pytest.warns(warning_classes) as warninfo:
warnings.warn("runtime", RuntimeWarning)
warnings.warn("import", ImportWarning)
with pytest.warns():
with pytest.raises(pytest.fail.Exception) as excinfo:
with pytest.warns(warning_classes) as warninfo:
warnings.warn("runtime", RuntimeWarning)
warnings.warn("import", ImportWarning)
messages = [each.message for each in warninfo]
expected_str = (
f"DID NOT WARN. No warnings of type {warning_classes} were emitted.\n"
f"The list of emitted warnings is: {messages}."
f" Emitted warnings: {messages}."
)
assert str(excinfo.value) == expected_str
@ -367,25 +358,31 @@ class TestWarns:
with pytest.warns(UserWarning, match=r"must be \d+$"):
warnings.warn("value must be 42", UserWarning)
with pytest.raises(pytest.fail.Exception):
with pytest.warns(UserWarning, match=r"must be \d+$"):
warnings.warn("this is not here", UserWarning)
with pytest.warns():
with pytest.raises(pytest.fail.Exception):
with pytest.warns(UserWarning, match=r"must be \d+$"):
warnings.warn("this is not here", UserWarning)
with pytest.raises(pytest.fail.Exception):
with pytest.warns(FutureWarning, match=r"must be \d+$"):
warnings.warn("value must be 42", UserWarning)
with pytest.warns():
with pytest.raises(pytest.fail.Exception):
with pytest.warns(FutureWarning, match=r"must be \d+$"):
warnings.warn("value must be 42", UserWarning)
def test_one_from_multiple_warns(self) -> None:
with pytest.warns(UserWarning, match=r"aaa"):
warnings.warn("cccccccccc", UserWarning)
warnings.warn("bbbbbbbbbb", UserWarning)
warnings.warn("aaaaaaaaaa", UserWarning)
with pytest.warns():
with pytest.raises(pytest.fail.Exception, match="DID NOT WARN"):
with pytest.warns(UserWarning, match=r"aaa"):
with pytest.warns(UserWarning, match=r"aaa"):
warnings.warn("cccccccccc", UserWarning)
warnings.warn("bbbbbbbbbb", UserWarning)
warnings.warn("aaaaaaaaaa", UserWarning)
def test_none_of_multiple_warns(self) -> None:
with pytest.raises(pytest.fail.Exception):
with pytest.warns(UserWarning, match=r"aaa"):
warnings.warn("bbbbbbbbbb", UserWarning)
warnings.warn("cccccccccc", UserWarning)
with pytest.warns():
with pytest.raises(pytest.fail.Exception, match="DID NOT WARN"):
with pytest.warns(UserWarning, match=r"aaa"):
warnings.warn("bbbbbbbbbb", UserWarning)
warnings.warn("cccccccccc", UserWarning)
@pytest.mark.filterwarnings("ignore")
def test_can_capture_previously_warned(self) -> None:
@ -403,3 +400,45 @@ class TestWarns:
with pytest.warns(UserWarning, foo="bar"): # type: ignore
pass
assert "Unexpected keyword arguments" in str(excinfo.value)
def test_re_emit_single(self) -> None:
with pytest.warns(DeprecationWarning):
with pytest.warns(UserWarning):
warnings.warn("user warning", UserWarning)
warnings.warn("some deprecation warning", DeprecationWarning)
def test_re_emit_multiple(self) -> None:
with pytest.warns(UserWarning):
warnings.warn("first warning", UserWarning)
warnings.warn("second warning", UserWarning)
def test_re_emit_match_single(self) -> None:
with pytest.warns(DeprecationWarning):
with pytest.warns(UserWarning, match="user warning"):
warnings.warn("user warning", UserWarning)
warnings.warn("some deprecation warning", DeprecationWarning)
def test_re_emit_match_multiple(self) -> None:
with warnings.catch_warnings():
warnings.simplefilter("error") # if anything is re-emitted
with pytest.warns(UserWarning, match="user warning"):
warnings.warn("first user warning", UserWarning)
warnings.warn("second user warning", UserWarning)
def test_re_emit_non_match_single(self) -> None:
with pytest.warns(UserWarning, match="v2 warning"):
with pytest.warns(UserWarning, match="v1 warning"):
warnings.warn("v1 warning", UserWarning)
warnings.warn("non-matching v2 warning", UserWarning)
def test_catch_warning_within_raise(self) -> None:
# warns-in-raises works since https://github.com/pytest-dev/pytest/pull/11129
with pytest.raises(ValueError, match="some exception"):
with pytest.warns(FutureWarning, match="some warning"):
warnings.warn("some warning", category=FutureWarning)
raise ValueError("some exception")
# and raises-in-warns has always worked but we'll check for symmetry.
with pytest.warns(FutureWarning, match="some warning"):
with pytest.raises(ValueError, match="some exception"):
warnings.warn("some warning", category=FutureWarning)
raise ValueError("some exception")

View File

@ -1142,12 +1142,10 @@ def test_errors_in_xfail_skip_expressions(pytester: Pytester) -> None:
"""
)
result = pytester.runpytest()
markline = " ^"
markline = " ^"
pypy_version_info = getattr(sys, "pypy_version_info", None)
if pypy_version_info is not None and pypy_version_info < (6,):
markline = markline[5:]
elif sys.version_info >= (3, 8) or hasattr(sys, "pypy_version_info"):
markline = markline[4:]
markline = markline[1:]
if sys.version_info[:2] >= (3, 10):
expected = [

View File

@ -1,13 +1,7 @@
import sys
import pytest
from _pytest.pytester import Pytester
if sys.version_info < (3, 8):
pytest.skip("threadexception plugin needs Python>=3.8", allow_module_level=True)
@pytest.mark.filterwarnings("default::pytest.PytestUnhandledThreadExceptionWarning")
def test_unhandled_thread_exception(pytester: Pytester) -> None:
pytester.makepyfile(

View File

@ -1354,9 +1354,6 @@ def test_plain_unittest_does_not_support_async(pytester: Pytester) -> None:
result.stdout.fnmatch_lines(expected_lines)
@pytest.mark.skipif(
sys.version_info < (3, 8), reason="Feature introduced in Python 3.8"
)
def test_do_class_cleanups_on_success(pytester: Pytester) -> None:
testpath = pytester.makepyfile(
"""
@ -1382,9 +1379,6 @@ def test_do_class_cleanups_on_success(pytester: Pytester) -> None:
assert passed == 3
@pytest.mark.skipif(
sys.version_info < (3, 8), reason="Feature introduced in Python 3.8"
)
def test_do_class_cleanups_on_setupclass_failure(pytester: Pytester) -> None:
testpath = pytester.makepyfile(
"""
@ -1409,9 +1403,6 @@ def test_do_class_cleanups_on_setupclass_failure(pytester: Pytester) -> None:
assert passed == 1
@pytest.mark.skipif(
sys.version_info < (3, 8), reason="Feature introduced in Python 3.8"
)
def test_do_class_cleanups_on_teardownclass_failure(pytester: Pytester) -> None:
testpath = pytester.makepyfile(
"""

View File

@ -3,11 +3,10 @@ import sys
import pytest
from _pytest.pytester import Pytester
if sys.version_info < (3, 8):
pytest.skip("unraisableexception plugin needs Python>=3.8", allow_module_level=True)
PYPY = hasattr(sys, "pypy_version_info")
@pytest.mark.skipif(PYPY, reason="garbage-collection differences make this flaky")
@pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning")
def test_unraisable(pytester: Pytester) -> None:
pytester.makepyfile(
@ -40,6 +39,7 @@ def test_unraisable(pytester: Pytester) -> None:
)
@pytest.mark.skipif(PYPY, reason="garbage-collection differences make this flaky")
@pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning")
def test_unraisable_in_setup(pytester: Pytester) -> None:
pytester.makepyfile(
@ -76,6 +76,7 @@ def test_unraisable_in_setup(pytester: Pytester) -> None:
)
@pytest.mark.skipif(PYPY, reason="garbage-collection differences make this flaky")
@pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning")
def test_unraisable_in_teardown(pytester: Pytester) -> None:
pytester.makepyfile(
@ -116,7 +117,7 @@ def test_unraisable_in_teardown(pytester: Pytester) -> None:
@pytest.mark.filterwarnings("error::pytest.PytestUnraisableExceptionWarning")
def test_unraisable_warning_error(pytester: Pytester) -> None:
pytester.makepyfile(
test_it="""
test_it=f"""
class BrokenDel:
def __del__(self) -> None:
raise ValueError("del is broken")
@ -124,6 +125,7 @@ def test_unraisable_warning_error(pytester: Pytester) -> None:
def test_it() -> None:
obj = BrokenDel()
del obj
{"import gc; gc.collect()" * PYPY}
def test_2(): pass
"""

View File

@ -4,17 +4,16 @@ minversion = 3.20.0
distshare = {homedir}/.tox/distshare
envlist =
linting
py37
py38
py39
py310
py311
py312
pypy3
py37-{pexpect,xdist,unittestextras,numpy,pluggymain,pylib}
py38-{pexpect,xdist,unittestextras,numpy,pluggymain,pylib}
doctesting
plugins
py37-freeze
py38-freeze
docs
docs-checklinks
@ -43,7 +42,7 @@ setenv =
PYTHONWARNDEFAULTENCODING=1
# Configuration to run with coverage similar to CI, e.g.
# "tox -e py37-coverage".
# "tox -e py38-coverage".
coverage: _PYTEST_TOX_COVERAGE_RUN=coverage run -m
coverage: _PYTEST_TOX_EXTRA_DEP=coverage-enable-subprocess
coverage: COVERAGE_FILE={toxinidir}/.coverage
@ -136,7 +135,7 @@ commands =
pytest pytest_twisted_integration.py
pytest simple_integration.py --force-sugar --flakes
[testenv:py37-freeze]
[testenv:py38-freeze]
changedir = testing/freeze
deps =
pyinstaller