Merge branch 'main' into improve-high-scope-fixtures-teardown-issue-3806
This commit is contained in:
commit
14ff2abb06
3
AUTHORS
3
AUTHORS
|
@ -72,6 +72,7 @@ Charles Cloud
|
|||
Charles Machalow
|
||||
Charnjit SiNGH (CCSJ)
|
||||
Cheuk Ting Ho
|
||||
Chris Mahoney
|
||||
Chris Lamb
|
||||
Chris NeJame
|
||||
Chris Rose
|
||||
|
@ -130,6 +131,7 @@ Eric Siegerman
|
|||
Erik Aronesty
|
||||
Erik M. Bray
|
||||
Evan Kepner
|
||||
Evgeny Seliverstov
|
||||
Fabien Zarifian
|
||||
Fabio Zadrozny
|
||||
Felix Hofstätter
|
||||
|
@ -196,6 +198,7 @@ Justice Ndou
|
|||
Justyna Janczyszyn
|
||||
Kale Kundert
|
||||
Kamran Ahmad
|
||||
Kenny Y
|
||||
Karl O. Pinc
|
||||
Karthikeyan Singaravelan
|
||||
Katarzyna Jachim
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Added handling of ``%f`` directive to print microseconds in log format options, such as ``log-date-format``.
|
|
@ -0,0 +1 @@
|
|||
Added warning when :confval:`testpaths` is set, but paths are not found by glob. In this case, pytest will fall back to searching from the current directory.
|
|
@ -0,0 +1 @@
|
|||
Fixed bug in assertion rewriting where a variable assigned with the walrus operator could not be used later in a function call.
|
|
@ -0,0 +1 @@
|
|||
Enhanced the CLI flag for ``-c`` to now include ``--config-file`` to make it clear that this flag applies to the usage of a custom config file.
|
|
@ -0,0 +1,3 @@
|
|||
When `--confcutdir` is not specified, and there is no config file present, the conftest cutoff directory (`--confcutdir`) is now set to the :ref:`rootdir`.
|
||||
Previously in such cases, `conftest.py` files would be probed all the way to the root directory of the filesystem.
|
||||
If you are badly affected by this change, consider adding an empty config file to your desired cutoff directory, or explicitly set `--confcutdir`.
|
|
@ -0,0 +1 @@
|
|||
Fixed ``--last-failed``'s "(skipped N files)" functionality for files inside of packages (directories with `__init__.py` files).
|
|
@ -0,0 +1 @@
|
|||
Fixed traceback entries hidden with ``__tracebackhide__ = True`` still being shown for chained exceptions (parts after "... the above exception ..." message).
|
|
@ -11,7 +11,7 @@ automatically. Packages classified as inactive are excluded.
|
|||
creating a PDF, because otherwise the table gets far too wide for the
|
||||
page.
|
||||
|
||||
This list contains 1256 plugins.
|
||||
This list contains 1259 plugins.
|
||||
|
||||
.. only:: not latex
|
||||
|
||||
|
@ -38,7 +38,7 @@ This list contains 1256 plugins.
|
|||
: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. Apr 18, 2023 N/A pytest (>=6.0)
|
||||
:pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. May 23, 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)
|
||||
|
@ -213,7 +213,7 @@ This list contains 1256 plugins.
|
|||
: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 Mar 18, 2022 4 - Beta N/A
|
||||
:pypi:`pytest-console-scripts` Pytest plugin for testing console scripts May 22, 2023 4 - Beta N/A
|
||||
: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-contextfixture` Define pytest fixtures as context managers. Mar 12, 2013 4 - Beta N/A
|
||||
|
@ -221,14 +221,14 @@ This list contains 1256 plugins.
|
|||
:pypi:`pytest-cookies` The pytest plugin for your Cookiecutter templates. 🍪 Mar 22, 2023 5 - Production/Stable pytest (>=3.9.0)
|
||||
: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. Sep 28, 2022 5 - Production/Stable pytest (>=4.6)
|
||||
: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-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 Apr 20, 2023 N/A N/A
|
||||
:pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types May 25, 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)
|
||||
|
@ -304,7 +304,7 @@ This list contains 1256 plugins.
|
|||
:pypi:`pytest-django-filefield` Replaces FileField.storage with something you can patch globally. May 09, 2022 5 - Production/Stable pytest >= 5.2
|
||||
:pypi:`pytest-django-gcir` A Django plugin for pytest. Mar 06, 2018 5 - Production/Stable N/A
|
||||
:pypi:`pytest-django-haystack` Cleanup your Haystack indexes between tests Sep 03, 2017 5 - Production/Stable pytest (>=2.3.4)
|
||||
:pypi:`pytest-django-ifactory` A model instance factory for pytest-django Feb 09, 2022 3 - Alpha N/A
|
||||
:pypi:`pytest-django-ifactory` A model instance factory for pytest-django May 21, 2023 5 - Production/Stable N/A
|
||||
:pypi:`pytest-django-lite` The bare minimum to integrate py.test with Django. Jan 30, 2014 N/A N/A
|
||||
:pypi:`pytest-django-liveserver-ssl` Jan 20, 2022 3 - Alpha N/A
|
||||
:pypi:`pytest-django-model` A Simple Way to Test your Django Models Feb 14, 2019 4 - Beta N/A
|
||||
|
@ -486,7 +486,7 @@ This list contains 1256 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. May 20, 2023 N/A N/A
|
||||
:pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. May 22, 2023 N/A N/A
|
||||
:pypi:`pytest-git` Git repository fixture for py.test May 28, 2019 5 - Production/Stable pytest
|
||||
: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
|
||||
|
@ -499,7 +499,7 @@ This list contains 1256 plugins.
|
|||
:pypi:`pytest-glamor-allure` Extends allure-pytest functionality Jul 22, 2022 4 - Beta pytest
|
||||
:pypi:`pytest-gnupg-fixtures` Pytest fixtures for testing with gnupg. Mar 04, 2021 4 - Beta pytest
|
||||
:pypi:`pytest-golden` Plugin for pytest that offloads expected outputs to data files Jul 18, 2022 N/A pytest (>=6.1.2)
|
||||
:pypi:`pytest-goldie` A plugin to support golden tests with pytest. Apr 12, 2023 4 - Beta pytest (>=3.5.0)
|
||||
:pypi:`pytest-goldie` A plugin to support golden tests with pytest. May 23, 2023 4 - Beta pytest (>=3.5.0)
|
||||
: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
|
||||
|
@ -518,7 +518,7 @@ This list contains 1256 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 May 15, 2023 3 - Alpha pytest (==7.3.1)
|
||||
:pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components May 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` May 18, 2023 N/A N/A
|
||||
|
@ -539,7 +539,7 @@ This list contains 1256 plugins.
|
|||
:pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace May 09, 2023 3 - Alpha pytest (>=7.0.0)
|
||||
:pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A
|
||||
:pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A
|
||||
:pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 16, 2023 3 - Alpha N/A
|
||||
:pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 22, 2023 3 - Alpha N/A
|
||||
:pypi:`pytest-httptesting` http_testing framework on top of pytest Apr 19, 2023 N/A pytest (>=7.2.0,<8.0.0)
|
||||
:pypi:`pytest-httpx` Send responses to httpx. Apr 12, 2023 5 - Production/Stable pytest (<8.0,>=6.0)
|
||||
:pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1)
|
||||
|
@ -569,7 +569,7 @@ This list contains 1256 plugins.
|
|||
:pypi:`pytest-instafail` pytest plugin to show failures instantly Mar 31, 2023 4 - Beta pytest (>=5)
|
||||
:pypi:`pytest-instrument` pytest plugin to instrument tests Apr 05, 2020 5 - Production/Stable pytest (>=5.1.0)
|
||||
:pypi:`pytest-integration` Organizing pytests by integration or not Nov 17, 2022 N/A N/A
|
||||
:pypi:`pytest-integration-mark` Automatic integration test marking and excluding plugin for pytest Jul 19, 2021 N/A pytest (>=5.2,<7.0)
|
||||
:pypi:`pytest-integration-mark` Automatic integration test marking and excluding plugin for pytest 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
|
||||
|
@ -649,7 +649,7 @@ This list contains 1256 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 May 15, 2023 5 - Production/Stable pytest (==7.3.1)
|
||||
:pypi:`pytest-logikal` Common testing environment May 27, 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)
|
||||
|
@ -680,9 +680,9 @@ This list contains 1256 plugins.
|
|||
:pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2)
|
||||
:pypi:`pytest-message` Pytest plugin for sending report message of marked tests execution Aug 04, 2022 N/A pytest (>=6.2.5)
|
||||
:pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A
|
||||
:pypi:`pytest-metadata` pytest plugin for test session metadata Oct 30, 2022 5 - Production/Stable pytest (>=3.0.0,<8.0.0)
|
||||
:pypi:`pytest-metadata` pytest plugin for test session metadata May 27, 2023 5 - Production/Stable pytest>=7.0.0
|
||||
:pypi:`pytest-metrics` Custom metrics report for pytest Apr 04, 2020 N/A pytest
|
||||
:pypi:`pytest-mh` Pytest multihost plugin May 04, 2023 N/A pytest
|
||||
:pypi:`pytest-mh` Pytest multihost plugin May 25, 2023 N/A pytest
|
||||
:pypi:`pytest-mimesis` Mimesis integration with the pytest test runner Mar 21, 2020 5 - Production/Stable pytest (>=4.2)
|
||||
:pypi:`pytest-minecraft` A pytest plugin for running tests against Minecraft releases Apr 06, 2022 N/A pytest (>=6.0.1)
|
||||
:pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0)
|
||||
|
@ -695,7 +695,7 @@ This list contains 1256 plugins.
|
|||
:pypi:`pytest-mock-helper` Help you mock HTTP call and generate mock code Jan 24, 2018 N/A pytest
|
||||
:pypi:`pytest-mockito` Base fixtures for mockito Jul 11, 2018 4 - Beta N/A
|
||||
:pypi:`pytest-mockredis` An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. Jan 02, 2018 2 - Pre-Alpha N/A
|
||||
:pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. May 03, 2023 N/A pytest (>=1.0)
|
||||
:pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. May 23, 2023 N/A pytest (>=1.0)
|
||||
:pypi:`pytest-mock-server` Mock server plugin for pytest Jan 09, 2022 4 - Beta pytest (>=3.5.0)
|
||||
:pypi:`pytest-mockservers` A set of fixtures to test your requests to HTTP/UDP servers Mar 31, 2020 N/A pytest (>=4.3.0)
|
||||
:pypi:`pytest-mocktcp` A pytest plugin for testing TCP clients Oct 11, 2022 N/A pytest
|
||||
|
@ -825,6 +825,7 @@ This list contains 1256 plugins.
|
|||
:pypi:`pytest-plus` PyTest Plus Plugin :: extends pytest functionality Dec 24, 2022 5 - Production/Stable pytest (>=6.0.1)
|
||||
:pypi:`pytest-pmisc` Mar 21, 2019 5 - Production/Stable N/A
|
||||
:pypi:`pytest-pointers` Pytest plugin to define functions you test with special marks for better navigation and reports Dec 26, 2022 N/A N/A
|
||||
:pypi:`pytest-pokie` Pokie plugin for pytest May 22, 2023 5 - Production/Stable N/A
|
||||
:pypi:`pytest-polarion-cfme` pytest plugin for collecting test cases and recording test results Nov 13, 2017 3 - Alpha N/A
|
||||
:pypi:`pytest-polarion-collect` pytest plugin for collecting polarion test cases data Jun 18, 2020 3 - Alpha pytest
|
||||
:pypi:`pytest-polecat` Provides Polecat pytest fixtures Aug 12, 2019 4 - Beta N/A
|
||||
|
@ -910,11 +911,12 @@ This list contains 1256 plugins.
|
|||
:pypi:`pytest-redmine` Pytest plugin for redmine Mar 19, 2018 1 - Planning N/A
|
||||
:pypi:`pytest-ref` A plugin to store reference files to ease regression testing Nov 23, 2019 4 - Beta pytest (>=3.5.0)
|
||||
:pypi:`pytest-reference-formatter` Conveniently run pytest with a dot-formatted test reference. Oct 01, 2019 4 - Beta N/A
|
||||
:pypi:`pytest-regex` Select pytest tests with regular expressions May 23, 2023 4 - Beta pytest (>=3.5.0)
|
||||
:pypi:`pytest-regex-dependency` Management of Pytest dependencies via regex patterns Jun 12, 2022 N/A pytest
|
||||
:pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Jan 13, 2023 5 - Production/Stable pytest (>=6.2.0)
|
||||
:pypi:`pytest-regtest` pytest plugin for regression tests Jul 08, 2022 N/A N/A
|
||||
:pypi:`pytest-relative-order` a pytest plugin that sorts tests using "before" and "after" markers May 17, 2021 4 - Beta N/A
|
||||
:pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest Dec 31, 2022 5 - Production/Stable pytest (>=7)
|
||||
:pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest May 23, 2023 5 - Production/Stable pytest (>=7)
|
||||
:pypi:`pytest-remfiles` Pytest plugin to create a temporary directory with remote files Jul 01, 2019 5 - Production/Stable N/A
|
||||
:pypi:`pytest-remotedata` Pytest plugin for controlling remote data access. Dec 12, 2022 3 - Alpha pytest (>=4.6)
|
||||
:pypi:`pytest-remote-response` Pytest plugin for capturing and mocking connection requests. Apr 26, 2023 5 - Production/Stable pytest (>=4.6)
|
||||
|
@ -929,10 +931,10 @@ This list contains 1256 plugins.
|
|||
:pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Jan 22, 2023 N/A N/A
|
||||
:pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A
|
||||
:pypi:`pytest-reporting` A plugin to report summarized results in a table format Oct 25, 2019 4 - Beta pytest (>=3.5.0)
|
||||
:pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility Apr 26, 2023 3 - Alpha pytest
|
||||
: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 Apr 21, 2023 N/A pytest (>=3.8.0)
|
||||
:pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal May 24, 2023 N/A pytest (>=3.8.0)
|
||||
: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)
|
||||
:pypi:`pytest-requestselapsed` collect and show http requests elapsed time Aug 14, 2022 N/A N/A
|
||||
|
@ -989,18 +991,19 @@ This list contains 1256 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. May 12, 2023 5 - Production/Stable N/A
|
||||
:pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. May 25, 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 Sep 21, 2022 5 - Production/Stable pytest (>=6.0.0,<7.0.0)
|
||||
:pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. May 12, 2023 5 - Production/Stable N/A
|
||||
:pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. May 25, 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
|
||||
:pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Jan 05, 2023 N/A N/A
|
||||
:pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A
|
||||
:pypi:`pytest-server-fixtures` Extensible server fixures for py.test May 28, 2019 5 - Production/Stable pytest
|
||||
:pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A
|
||||
:pypi:`pytest-servers` pytest servers Apr 15, 2023 3 - Alpha pytest (>=6.2)
|
||||
|
@ -1102,7 +1105,7 @@ This list contains 1256 plugins.
|
|||
:pypi:`pytest-tagging` a pytest plugin to tag tests Apr 01, 2023 N/A pytest (>=7.1.3,<8.0.0)
|
||||
:pypi:`pytest-takeltest` Fixtures for ansible, testinfra and molecule Feb 15, 2023 N/A N/A
|
||||
:pypi:`pytest-talisker` Nov 28, 2021 N/A N/A
|
||||
:pypi:`pytest-tally` A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. May 20, 2023 4 - Beta pytest (>=6.2.5)
|
||||
:pypi:`pytest-tally` A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. May 22, 2023 4 - Beta pytest (>=6.2.5)
|
||||
:pypi:`pytest-tap` Test Anything Protocol (TAP) reporting plugin for pytest Oct 27, 2021 5 - Production/Stable pytest (>=3.0)
|
||||
:pypi:`pytest-tape` easy assertion with expected results saved to yaml files Mar 17, 2021 4 - Beta N/A
|
||||
:pypi:`pytest-target` Pytest plugin for remote target orchestration. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0)
|
||||
|
@ -1121,7 +1124,7 @@ This list contains 1256 plugins.
|
|||
:pypi:`pytest-testdox` A testdox format reporter for pytest Apr 19, 2022 5 - Production/Stable pytest (>=4.6.0)
|
||||
:pypi:`pytest-test-grouping` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Feb 01, 2023 5 - Production/Stable pytest (>=2.5)
|
||||
:pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Oct 25, 2016 5 - Production/Stable N/A
|
||||
:pypi:`pytest-testinfra` Test infrastructures May 19, 2023 5 - Production/Stable pytest (!=3.0.2)
|
||||
:pypi:`pytest-testinfra` Test infrastructures May 21, 2023 5 - Production/Stable pytest (!=3.0.2)
|
||||
:pypi:`pytest-testlink-adaptor` pytest reporting plugin for testlink Dec 20, 2018 4 - Beta pytest (>=2.6)
|
||||
:pypi:`pytest-testmon` selects tests affected by changed files and methods May 18, 2023 4 - Beta pytest (<8,>=5)
|
||||
:pypi:`pytest-testmon-dev` selects tests affected by changed files and methods Mar 30, 2023 4 - Beta pytest (<8,>=5)
|
||||
|
@ -1208,7 +1211,7 @@ This list contains 1256 plugins.
|
|||
: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
|
||||
:pypi:`pytest-valgrind` May 19, 2021 N/A N/A
|
||||
:pypi:`pytest-variables` pytest plugin for providing variables to tests/fixtures Mar 27, 2022 5 - Production/Stable pytest (>=3.0.0,<8.0.0)
|
||||
:pypi:`pytest-variables` pytest plugin for providing variables to tests/fixtures May 27, 2023 5 - Production/Stable pytest>=7.0.0
|
||||
:pypi:`pytest-variant` Variant support for Pytest Jun 06, 2022 N/A N/A
|
||||
:pypi:`pytest-vcr` Plugin for managing VCR.py cassettes Apr 26, 2019 5 - Production/Stable pytest (>=3.6.0)
|
||||
:pypi:`pytest-vcr-delete-on-fail` A pytest plugin that automates vcrpy cassettes deletion on test failure. Jun 20, 2022 5 - Production/Stable pytest (>=6.2.2)
|
||||
|
@ -1235,7 +1238,7 @@ This list contains 1256 plugins.
|
|||
: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
|
||||
:pypi:`pytest-wetest` Welian API Automation test framework pytest plugin Nov 10, 2018 4 - Beta N/A
|
||||
:pypi:`pytest-when` Utility which makes mocking more readable and controllable May 19, 2023 N/A N/A
|
||||
:pypi:`pytest-when` Utility which makes mocking more readable and controllable May 22, 2023 N/A pytest>=7.3.1
|
||||
:pypi:`pytest-whirlwind` Testing Tornado. Jun 12, 2020 N/A N/A
|
||||
:pypi:`pytest-wholenodeid` pytest addon for displaying the whole node id for failures Aug 26, 2015 4 - Beta pytest (>=2.0)
|
||||
:pypi:`pytest-win32consoletitle` Pytest progress in console title (Win32 only) Aug 08, 2021 N/A N/A
|
||||
|
@ -1262,7 +1265,7 @@ This list contains 1256 plugins.
|
|||
:pypi:`pytest-yaml-sanmu` pytest plugin for generating test cases by yaml Mar 17, 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 May 20, 2023 N/A pytest (>=7.2.0)
|
||||
:pypi:`pytest-yaml-yoyo` http/https API run by yaml May 22, 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
|
||||
|
@ -1420,7 +1423,7 @@ This list contains 1256 plugins.
|
|||
|
||||
|
||||
:pypi:`pytest-alembic`
|
||||
*last release*: Apr 18, 2023,
|
||||
*last release*: May 23, 2023,
|
||||
*status*: N/A,
|
||||
*requires*: pytest (>=6.0)
|
||||
|
||||
|
@ -2645,7 +2648,7 @@ This list contains 1256 plugins.
|
|||
Package stands for pytest plugin to upload results into Confluence page.
|
||||
|
||||
:pypi:`pytest-console-scripts`
|
||||
*last release*: Mar 18, 2022,
|
||||
*last release*: May 22, 2023,
|
||||
*status*: 4 - Beta,
|
||||
*requires*: N/A
|
||||
|
||||
|
@ -2701,7 +2704,7 @@ This list contains 1256 plugins.
|
|||
count erros and send email
|
||||
|
||||
:pypi:`pytest-cov`
|
||||
*last release*: Sep 28, 2022,
|
||||
*last release*: May 24, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: pytest (>=4.6)
|
||||
|
||||
|
@ -2750,7 +2753,7 @@ This list contains 1256 plugins.
|
|||
Use pytest's runner to discover and execute C++ tests
|
||||
|
||||
:pypi:`pytest-cppython`
|
||||
*last release*: Apr 20, 2023,
|
||||
*last release*: May 25, 2023,
|
||||
*status*: N/A,
|
||||
*requires*: N/A
|
||||
|
||||
|
@ -3282,8 +3285,8 @@ This list contains 1256 plugins.
|
|||
Cleanup your Haystack indexes between tests
|
||||
|
||||
:pypi:`pytest-django-ifactory`
|
||||
*last release*: Feb 09, 2022,
|
||||
*status*: 3 - Alpha,
|
||||
*last release*: May 21, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: N/A
|
||||
|
||||
A model instance factory for pytest-django
|
||||
|
@ -4556,7 +4559,7 @@ This list contains 1256 plugins.
|
|||
For finding/executing Ghost Inspector tests
|
||||
|
||||
:pypi:`pytest-girder`
|
||||
*last release*: May 20, 2023,
|
||||
*last release*: May 22, 2023,
|
||||
*status*: N/A,
|
||||
*requires*: N/A
|
||||
|
||||
|
@ -4647,7 +4650,7 @@ This list contains 1256 plugins.
|
|||
Plugin for pytest that offloads expected outputs to data files
|
||||
|
||||
:pypi:`pytest-goldie`
|
||||
*last release*: Apr 12, 2023,
|
||||
*last release*: May 23, 2023,
|
||||
*status*: 4 - Beta,
|
||||
*requires*: pytest (>=3.5.0)
|
||||
|
||||
|
@ -4780,7 +4783,7 @@ This list contains 1256 plugins.
|
|||
A pytest plugin for use with homeassistant custom components.
|
||||
|
||||
:pypi:`pytest-homeassistant-custom-component`
|
||||
*last release*: May 15, 2023,
|
||||
*last release*: May 24, 2023,
|
||||
*status*: 3 - Alpha,
|
||||
*requires*: pytest (==7.3.1)
|
||||
|
||||
|
@ -4927,7 +4930,7 @@ This list contains 1256 plugins.
|
|||
A thin wrapper of HTTPretty for pytest
|
||||
|
||||
:pypi:`pytest-httpserver`
|
||||
*last release*: May 16, 2023,
|
||||
*last release*: May 22, 2023,
|
||||
*status*: 3 - Alpha,
|
||||
*requires*: N/A
|
||||
|
||||
|
@ -5137,9 +5140,9 @@ This list contains 1256 plugins.
|
|||
Organizing pytests by integration or not
|
||||
|
||||
:pypi:`pytest-integration-mark`
|
||||
*last release*: Jul 19, 2021,
|
||||
*last release*: May 22, 2023,
|
||||
*status*: N/A,
|
||||
*requires*: pytest (>=5.2,<7.0)
|
||||
*requires*: pytest (>=5.2)
|
||||
|
||||
Automatic integration test marking and excluding plugin for pytest
|
||||
|
||||
|
@ -5697,7 +5700,7 @@ This list contains 1256 plugins.
|
|||
|
||||
|
||||
:pypi:`pytest-logikal`
|
||||
*last release*: May 15, 2023,
|
||||
*last release*: May 27, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: pytest (==7.3.1)
|
||||
|
||||
|
@ -5914,9 +5917,9 @@ This list contains 1256 plugins.
|
|||
Pytest to Slack reporting plugin
|
||||
|
||||
:pypi:`pytest-metadata`
|
||||
*last release*: Oct 30, 2022,
|
||||
*last release*: May 27, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: pytest (>=3.0.0,<8.0.0)
|
||||
*requires*: pytest>=7.0.0
|
||||
|
||||
pytest plugin for test session metadata
|
||||
|
||||
|
@ -5928,7 +5931,7 @@ This list contains 1256 plugins.
|
|||
Custom metrics report for pytest
|
||||
|
||||
:pypi:`pytest-mh`
|
||||
*last release*: May 04, 2023,
|
||||
*last release*: May 25, 2023,
|
||||
*status*: N/A,
|
||||
*requires*: pytest
|
||||
|
||||
|
@ -6019,7 +6022,7 @@ This list contains 1256 plugins.
|
|||
An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database.
|
||||
|
||||
:pypi:`pytest-mock-resources`
|
||||
*last release*: May 03, 2023,
|
||||
*last release*: May 23, 2023,
|
||||
*status*: N/A,
|
||||
*requires*: pytest (>=1.0)
|
||||
|
||||
|
@ -6928,6 +6931,13 @@ This list contains 1256 plugins.
|
|||
|
||||
Pytest plugin to define functions you test with special marks for better navigation and reports
|
||||
|
||||
:pypi:`pytest-pokie`
|
||||
*last release*: May 22, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: N/A
|
||||
|
||||
Pokie plugin for pytest
|
||||
|
||||
:pypi:`pytest-polarion-cfme`
|
||||
*last release*: Nov 13, 2017,
|
||||
*status*: 3 - Alpha,
|
||||
|
@ -7523,6 +7533,13 @@ This list contains 1256 plugins.
|
|||
|
||||
Conveniently run pytest with a dot-formatted test reference.
|
||||
|
||||
:pypi:`pytest-regex`
|
||||
*last release*: May 23, 2023,
|
||||
*status*: 4 - Beta,
|
||||
*requires*: pytest (>=3.5.0)
|
||||
|
||||
Select pytest tests with regular expressions
|
||||
|
||||
:pypi:`pytest-regex-dependency`
|
||||
*last release*: Jun 12, 2022,
|
||||
*status*: N/A,
|
||||
|
@ -7552,7 +7569,7 @@ This list contains 1256 plugins.
|
|||
a pytest plugin that sorts tests using "before" and "after" markers
|
||||
|
||||
:pypi:`pytest-relaxed`
|
||||
*last release*: Dec 31, 2022,
|
||||
*last release*: May 23, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: pytest (>=7)
|
||||
|
||||
|
@ -7657,7 +7674,7 @@ This list contains 1256 plugins.
|
|||
A plugin to report summarized results in a table format
|
||||
|
||||
:pypi:`pytest-reportlog`
|
||||
*last release*: Apr 26, 2023,
|
||||
*last release*: May 22, 2023,
|
||||
*status*: 3 - Alpha,
|
||||
*requires*: pytest
|
||||
|
||||
|
@ -7678,7 +7695,7 @@ This list contains 1256 plugins.
|
|||
pytest plugin for adding tests' parameters to junit report
|
||||
|
||||
:pypi:`pytest-reportportal`
|
||||
*last release*: Apr 21, 2023,
|
||||
*last release*: May 24, 2023,
|
||||
*status*: N/A,
|
||||
*requires*: pytest (>=3.8.0)
|
||||
|
||||
|
@ -8077,7 +8094,7 @@ This list contains 1256 plugins.
|
|||
|
||||
|
||||
:pypi:`pytest-sbase`
|
||||
*last release*: May 12, 2023,
|
||||
*last release*: May 25, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: N/A
|
||||
|
||||
|
@ -8126,7 +8143,7 @@ This list contains 1256 plugins.
|
|||
pytest plugin for Selenium
|
||||
|
||||
:pypi:`pytest-seleniumbase`
|
||||
*last release*: May 12, 2023,
|
||||
*last release*: May 25, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: N/A
|
||||
|
||||
|
@ -8160,6 +8177,13 @@ This list contains 1256 plugins.
|
|||
|
||||
A pytest plugin to send testrun information to Sentry.io
|
||||
|
||||
:pypi:`pytest-sequence-markers`
|
||||
*last release*: May 23, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: N/A
|
||||
|
||||
Pytest plugin for sequencing markers for execution of tests
|
||||
|
||||
:pypi:`pytest-server-fixtures`
|
||||
*last release*: May 28, 2019,
|
||||
*status*: 5 - Production/Stable,
|
||||
|
@ -8868,7 +8892,7 @@ This list contains 1256 plugins.
|
|||
|
||||
|
||||
:pypi:`pytest-tally`
|
||||
*last release*: May 20, 2023,
|
||||
*last release*: May 22, 2023,
|
||||
*status*: 4 - Beta,
|
||||
*requires*: pytest (>=6.2.5)
|
||||
|
||||
|
@ -9001,7 +9025,7 @@ This list contains 1256 plugins.
|
|||
A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups.
|
||||
|
||||
:pypi:`pytest-testinfra`
|
||||
*last release*: May 19, 2023,
|
||||
*last release*: May 21, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: pytest (!=3.0.2)
|
||||
|
||||
|
@ -9610,9 +9634,9 @@ This list contains 1256 plugins.
|
|||
|
||||
|
||||
:pypi:`pytest-variables`
|
||||
*last release*: Mar 27, 2022,
|
||||
*last release*: May 27, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: pytest (>=3.0.0,<8.0.0)
|
||||
*requires*: pytest>=7.0.0
|
||||
|
||||
pytest plugin for providing variables to tests/fixtures
|
||||
|
||||
|
@ -9799,9 +9823,9 @@ This list contains 1256 plugins.
|
|||
Welian API Automation test framework pytest plugin
|
||||
|
||||
:pypi:`pytest-when`
|
||||
*last release*: May 19, 2023,
|
||||
*last release*: May 22, 2023,
|
||||
*status*: N/A,
|
||||
*requires*: N/A
|
||||
*requires*: pytest>=7.3.1
|
||||
|
||||
Utility which makes mocking more readable and controllable
|
||||
|
||||
|
@ -9988,7 +10012,7 @@ This list contains 1256 plugins.
|
|||
Run tests against wsgi apps defined in yaml
|
||||
|
||||
:pypi:`pytest-yaml-yoyo`
|
||||
*last release*: May 20, 2023,
|
||||
*last release*: May 22, 2023,
|
||||
*status*: N/A,
|
||||
*requires*: pytest (>=7.2.0)
|
||||
|
||||
|
|
|
@ -1918,7 +1918,8 @@ All the command-line flags can be obtained by running ``pytest --help``::
|
|||
--strict-markers Markers not registered in the `markers` section of
|
||||
the configuration file raise errors
|
||||
--strict (Deprecated) alias to --strict-markers
|
||||
-c file Load configuration from `file` instead of trying to
|
||||
-c, --config-file FILE
|
||||
Load configuration from `FILE` instead of trying to
|
||||
locate one of the implicit configuration files
|
||||
--continue-on-collection-errors
|
||||
Force test execution even if collection errors occur
|
||||
|
|
|
@ -31,7 +31,6 @@ from typing import Type
|
|||
from typing import TYPE_CHECKING
|
||||
from typing import TypeVar
|
||||
from typing import Union
|
||||
from weakref import ref
|
||||
|
||||
import pluggy
|
||||
|
||||
|
@ -50,9 +49,9 @@ 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
|
||||
from weakref import ReferenceType
|
||||
|
||||
_TracebackStyle = Literal["long", "short", "line", "no", "native", "value", "auto"]
|
||||
|
||||
|
@ -194,25 +193,25 @@ class Frame:
|
|||
class TracebackEntry:
|
||||
"""A single entry in a Traceback."""
|
||||
|
||||
__slots__ = ("_rawentry", "_excinfo", "_repr_style")
|
||||
__slots__ = ("_rawentry", "_repr_style")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
rawentry: TracebackType,
|
||||
excinfo: Optional["ReferenceType[ExceptionInfo[BaseException]]"] = None,
|
||||
repr_style: Optional['Literal["short", "long"]'] = None,
|
||||
) -> None:
|
||||
self._rawentry = rawentry
|
||||
self._excinfo = excinfo
|
||||
self._repr_style: Optional['Literal["short", "long"]'] = None
|
||||
self._rawentry: "Final" = rawentry
|
||||
self._repr_style: "Final" = repr_style
|
||||
|
||||
def with_repr_style(
|
||||
self, repr_style: Optional['Literal["short", "long"]']
|
||||
) -> "TracebackEntry":
|
||||
return TracebackEntry(self._rawentry, repr_style)
|
||||
|
||||
@property
|
||||
def lineno(self) -> int:
|
||||
return self._rawentry.tb_lineno - 1
|
||||
|
||||
def set_repr_style(self, mode: "Literal['short', 'long']") -> None:
|
||||
assert mode in ("short", "long")
|
||||
self._repr_style = mode
|
||||
|
||||
@property
|
||||
def frame(self) -> Frame:
|
||||
return Frame(self._rawentry.tb_frame)
|
||||
|
@ -272,7 +271,7 @@ class TracebackEntry:
|
|||
|
||||
source = property(getsource)
|
||||
|
||||
def ishidden(self) -> bool:
|
||||
def ishidden(self, excinfo: Optional["ExceptionInfo[BaseException]"]) -> bool:
|
||||
"""Return True if the current frame has a var __tracebackhide__
|
||||
resolving to True.
|
||||
|
||||
|
@ -296,7 +295,7 @@ class TracebackEntry:
|
|||
else:
|
||||
break
|
||||
if tbh and callable(tbh):
|
||||
return tbh(None if self._excinfo is None else self._excinfo())
|
||||
return tbh(excinfo)
|
||||
return tbh
|
||||
|
||||
def __str__(self) -> str:
|
||||
|
@ -329,16 +328,14 @@ class Traceback(List[TracebackEntry]):
|
|||
def __init__(
|
||||
self,
|
||||
tb: Union[TracebackType, Iterable[TracebackEntry]],
|
||||
excinfo: Optional["ReferenceType[ExceptionInfo[BaseException]]"] = None,
|
||||
) -> None:
|
||||
"""Initialize from given python traceback object and ExceptionInfo."""
|
||||
self._excinfo = excinfo
|
||||
if isinstance(tb, TracebackType):
|
||||
|
||||
def f(cur: TracebackType) -> Iterable[TracebackEntry]:
|
||||
cur_: Optional[TracebackType] = cur
|
||||
while cur_ is not None:
|
||||
yield TracebackEntry(cur_, excinfo=excinfo)
|
||||
yield TracebackEntry(cur_)
|
||||
cur_ = cur_.tb_next
|
||||
|
||||
super().__init__(f(tb))
|
||||
|
@ -378,7 +375,7 @@ class Traceback(List[TracebackEntry]):
|
|||
continue
|
||||
if firstlineno is not None and x.frame.code.firstlineno != firstlineno:
|
||||
continue
|
||||
return Traceback(x._rawentry, self._excinfo)
|
||||
return Traceback(x._rawentry)
|
||||
return self
|
||||
|
||||
@overload
|
||||
|
@ -398,27 +395,27 @@ class Traceback(List[TracebackEntry]):
|
|||
return super().__getitem__(key)
|
||||
|
||||
def filter(
|
||||
self, fn: Callable[[TracebackEntry], bool] = lambda x: not x.ishidden()
|
||||
self,
|
||||
# TODO(py38): change to positional only.
|
||||
_excinfo_or_fn: Union[
|
||||
"ExceptionInfo[BaseException]",
|
||||
Callable[[TracebackEntry], bool],
|
||||
],
|
||||
) -> "Traceback":
|
||||
"""Return a Traceback instance with certain items removed
|
||||
"""Return a Traceback instance with certain items removed.
|
||||
|
||||
fn is a function that gets a single argument, a TracebackEntry
|
||||
instance, and should return True when the item should be added
|
||||
to the Traceback, False when not.
|
||||
If the filter is an `ExceptionInfo`, removes all the ``TracebackEntry``s
|
||||
which are hidden (see ishidden() above).
|
||||
|
||||
By default this removes all the TracebackEntries which are hidden
|
||||
(see ishidden() above).
|
||||
Otherwise, the filter is a function that gets a single argument, a
|
||||
``TracebackEntry`` instance, and should return True when the item should
|
||||
be added to the ``Traceback``, False when not.
|
||||
"""
|
||||
return Traceback(filter(fn, self), self._excinfo)
|
||||
|
||||
def getcrashentry(self) -> Optional[TracebackEntry]:
|
||||
"""Return last non-hidden traceback entry that lead to the exception of
|
||||
a traceback, or None if all hidden."""
|
||||
for i in range(-1, -len(self) - 1, -1):
|
||||
entry = self[i]
|
||||
if not entry.ishidden():
|
||||
return entry
|
||||
return None
|
||||
if isinstance(_excinfo_or_fn, ExceptionInfo):
|
||||
fn = lambda x: not x.ishidden(_excinfo_or_fn) # noqa: E731
|
||||
else:
|
||||
fn = _excinfo_or_fn
|
||||
return Traceback(filter(fn, self))
|
||||
|
||||
def recursionindex(self) -> Optional[int]:
|
||||
"""Return the index of the frame/TracebackEntry where recursion originates if
|
||||
|
@ -583,7 +580,7 @@ class ExceptionInfo(Generic[E]):
|
|||
def traceback(self) -> Traceback:
|
||||
"""The traceback."""
|
||||
if self._traceback is None:
|
||||
self._traceback = Traceback(self.tb, excinfo=ref(self))
|
||||
self._traceback = Traceback(self.tb)
|
||||
return self._traceback
|
||||
|
||||
@traceback.setter
|
||||
|
@ -623,19 +620,24 @@ class ExceptionInfo(Generic[E]):
|
|||
return isinstance(self.value, exc)
|
||||
|
||||
def _getreprcrash(self) -> Optional["ReprFileLocation"]:
|
||||
exconly = self.exconly(tryshort=True)
|
||||
entry = self.traceback.getcrashentry()
|
||||
if entry is None:
|
||||
return None
|
||||
# Find last non-hidden traceback entry that led to the exception of the
|
||||
# traceback, or None if all hidden.
|
||||
for i in range(-1, -len(self.traceback) - 1, -1):
|
||||
entry = self.traceback[i]
|
||||
if not entry.ishidden(self):
|
||||
path, lineno = entry.frame.code.raw.co_filename, entry.lineno
|
||||
exconly = self.exconly(tryshort=True)
|
||||
return ReprFileLocation(path, lineno + 1, exconly)
|
||||
return None
|
||||
|
||||
def getrepr(
|
||||
self,
|
||||
showlocals: bool = False,
|
||||
style: "_TracebackStyle" = "long",
|
||||
abspath: bool = False,
|
||||
tbfilter: bool = True,
|
||||
tbfilter: Union[
|
||||
bool, Callable[["ExceptionInfo[BaseException]"], Traceback]
|
||||
] = True,
|
||||
funcargs: bool = False,
|
||||
truncate_locals: bool = True,
|
||||
chain: bool = True,
|
||||
|
@ -652,9 +654,15 @@ class ExceptionInfo(Generic[E]):
|
|||
:param bool abspath:
|
||||
If paths should be changed to absolute or left unchanged.
|
||||
|
||||
:param bool tbfilter:
|
||||
Hide entries that contain a local variable ``__tracebackhide__==True``.
|
||||
Ignored if ``style=="native"``.
|
||||
:param tbfilter:
|
||||
A filter for traceback entries.
|
||||
|
||||
* If false, don't hide any entries.
|
||||
* If true, hide internal entries and entries that contain a local
|
||||
variable ``__tracebackhide__ = True``.
|
||||
* If a callable, delegates the filtering to the callable.
|
||||
|
||||
Ignored if ``style`` is ``"native"``.
|
||||
|
||||
:param bool funcargs:
|
||||
Show fixtures ("funcargs" for legacy purposes) per traceback entry.
|
||||
|
@ -719,7 +727,7 @@ class FormattedExcinfo:
|
|||
showlocals: bool = False
|
||||
style: "_TracebackStyle" = "long"
|
||||
abspath: bool = True
|
||||
tbfilter: bool = True
|
||||
tbfilter: Union[bool, Callable[[ExceptionInfo[BaseException]], Traceback]] = True
|
||||
funcargs: bool = False
|
||||
truncate_locals: bool = True
|
||||
chain: bool = True
|
||||
|
@ -881,8 +889,10 @@ class FormattedExcinfo:
|
|||
|
||||
def repr_traceback(self, excinfo: ExceptionInfo[BaseException]) -> "ReprTraceback":
|
||||
traceback = excinfo.traceback
|
||||
if self.tbfilter:
|
||||
traceback = traceback.filter()
|
||||
if callable(self.tbfilter):
|
||||
traceback = self.tbfilter(excinfo)
|
||||
elif self.tbfilter:
|
||||
traceback = traceback.filter(excinfo)
|
||||
|
||||
if isinstance(excinfo.value, RecursionError):
|
||||
traceback, extraline = self._truncate_recursive_traceback(traceback)
|
||||
|
|
|
@ -996,7 +996,9 @@ class AssertionRewriter(ast.NodeVisitor):
|
|||
]
|
||||
):
|
||||
pytest_temp = self.variable()
|
||||
self.variables_overwrite[v.left.target.id] = pytest_temp
|
||||
self.variables_overwrite[
|
||||
v.left.target.id
|
||||
] = v.left # type:ignore[assignment]
|
||||
v.left.target.id = pytest_temp
|
||||
self.push_format_context()
|
||||
res, expl = self.visit(v)
|
||||
|
@ -1037,10 +1039,19 @@ class AssertionRewriter(ast.NodeVisitor):
|
|||
new_args = []
|
||||
new_kwargs = []
|
||||
for arg in call.args:
|
||||
if isinstance(arg, ast.Name) and arg.id in self.variables_overwrite:
|
||||
arg = self.variables_overwrite[arg.id] # type:ignore[assignment]
|
||||
res, expl = self.visit(arg)
|
||||
arg_expls.append(expl)
|
||||
new_args.append(res)
|
||||
for keyword in call.keywords:
|
||||
if (
|
||||
isinstance(keyword.value, ast.Name)
|
||||
and keyword.value.id in self.variables_overwrite
|
||||
):
|
||||
keyword.value = self.variables_overwrite[
|
||||
keyword.value.id
|
||||
] # type:ignore[assignment]
|
||||
res, expl = self.visit(keyword.value)
|
||||
new_kwargs.append(ast.keyword(keyword.arg, res))
|
||||
if keyword.arg:
|
||||
|
@ -1075,7 +1086,13 @@ class AssertionRewriter(ast.NodeVisitor):
|
|||
self.push_format_context()
|
||||
# We first check if we have overwritten a variable in the previous assert
|
||||
if isinstance(comp.left, ast.Name) and comp.left.id in self.variables_overwrite:
|
||||
comp.left.id = self.variables_overwrite[comp.left.id]
|
||||
comp.left = self.variables_overwrite[
|
||||
comp.left.id
|
||||
] # type:ignore[assignment]
|
||||
if isinstance(comp.left, namedExpr):
|
||||
self.variables_overwrite[
|
||||
comp.left.target.id
|
||||
] = comp.left # type:ignore[assignment]
|
||||
left_res, left_expl = self.visit(comp.left)
|
||||
if isinstance(comp.left, (ast.Compare, ast.BoolOp)):
|
||||
left_expl = f"({left_expl})"
|
||||
|
@ -1093,7 +1110,9 @@ class AssertionRewriter(ast.NodeVisitor):
|
|||
and next_operand.target.id == left_res.id
|
||||
):
|
||||
next_operand.target.id = self.variable()
|
||||
self.variables_overwrite[left_res.id] = next_operand.target.id
|
||||
self.variables_overwrite[
|
||||
left_res.id
|
||||
] = next_operand # type:ignore[assignment]
|
||||
next_res, next_expl = self.visit(next_operand)
|
||||
if isinstance(next_operand, (ast.Compare, ast.BoolOp)):
|
||||
next_expl = f"({next_expl})"
|
||||
|
|
|
@ -219,7 +219,7 @@ class LFPluginCollWrapper:
|
|||
|
||||
@hookimpl(hookwrapper=True)
|
||||
def pytest_make_collect_report(self, collector: nodes.Collector):
|
||||
if isinstance(collector, Session):
|
||||
if isinstance(collector, (Session, Package)):
|
||||
out = yield
|
||||
res: CollectReport = out.get_result()
|
||||
|
||||
|
|
|
@ -1261,8 +1261,11 @@ class Config:
|
|||
_pytest.deprecated.STRICT_OPTION, stacklevel=2
|
||||
)
|
||||
|
||||
if self.known_args_namespace.confcutdir is None and self.inipath is not None:
|
||||
if self.known_args_namespace.confcutdir is None:
|
||||
if self.inipath is not None:
|
||||
confcutdir = str(self.inipath.parent)
|
||||
else:
|
||||
confcutdir = str(self.rootpath)
|
||||
self.known_args_namespace.confcutdir = confcutdir
|
||||
try:
|
||||
self.hook.pytest_load_initial_conftests(
|
||||
|
@ -1382,6 +1385,15 @@ class Config:
|
|||
args = []
|
||||
for path in testpaths:
|
||||
args.extend(sorted(glob.iglob(path, recursive=True)))
|
||||
if testpaths and not args:
|
||||
warning_text = (
|
||||
"No files were found in testpaths; "
|
||||
"consider removing or adjusting your testpaths configuration. "
|
||||
"Searching recursively from the current directory instead."
|
||||
)
|
||||
self.issue_config_time_warning(
|
||||
PytestConfigWarning(warning_text), stacklevel=3
|
||||
)
|
||||
if not args:
|
||||
source = Config.ArgsSource.INCOVATION_DIR
|
||||
args = [str(self.invocation_params.dir)]
|
||||
|
|
|
@ -5,7 +5,11 @@ import os
|
|||
import re
|
||||
from contextlib import contextmanager
|
||||
from contextlib import nullcontext
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
from datetime import timezone
|
||||
from io import StringIO
|
||||
from logging import LogRecord
|
||||
from pathlib import Path
|
||||
from typing import AbstractSet
|
||||
from typing import Dict
|
||||
|
@ -53,7 +57,25 @@ def _remove_ansi_escape_sequences(text: str) -> str:
|
|||
return _ANSI_ESCAPE_SEQ.sub("", text)
|
||||
|
||||
|
||||
class ColoredLevelFormatter(logging.Formatter):
|
||||
class DatetimeFormatter(logging.Formatter):
|
||||
"""A logging formatter which formats record with
|
||||
:func:`datetime.datetime.strftime` formatter instead of
|
||||
:func:`time.strftime` in case of microseconds in format string.
|
||||
"""
|
||||
|
||||
def formatTime(self, record: LogRecord, datefmt=None) -> str:
|
||||
if datefmt and "%f" in datefmt:
|
||||
ct = self.converter(record.created)
|
||||
tz = timezone(timedelta(seconds=ct.tm_gmtoff), ct.tm_zone)
|
||||
# Construct `datetime.datetime` object from `struct_time`
|
||||
# and msecs information from `record`
|
||||
dt = datetime(*ct[0:6], microsecond=round(record.msecs * 1000), tzinfo=tz)
|
||||
return dt.strftime(datefmt)
|
||||
# Use `logging.Formatter` for non-microsecond formats
|
||||
return super().formatTime(record, datefmt)
|
||||
|
||||
|
||||
class ColoredLevelFormatter(DatetimeFormatter):
|
||||
"""A logging formatter which colorizes the %(levelname)..s part of the
|
||||
log format passed to __init__."""
|
||||
|
||||
|
@ -625,7 +647,7 @@ class LoggingPlugin:
|
|||
config, "log_file_date_format", "log_date_format"
|
||||
)
|
||||
|
||||
log_file_formatter = logging.Formatter(
|
||||
log_file_formatter = DatetimeFormatter(
|
||||
log_file_format, datefmt=log_file_date_format
|
||||
)
|
||||
self.log_file_handler.setFormatter(log_file_formatter)
|
||||
|
@ -669,7 +691,7 @@ class LoggingPlugin:
|
|||
create_terminal_writer(self._config), log_format, log_date_format
|
||||
)
|
||||
else:
|
||||
formatter = logging.Formatter(log_format, log_date_format)
|
||||
formatter = DatetimeFormatter(log_format, log_date_format)
|
||||
|
||||
formatter._style = PercentStyleMultiline(
|
||||
formatter._style._fmt, auto_indent=auto_indent
|
||||
|
|
|
@ -122,11 +122,12 @@ def pytest_addoption(parser: Parser) -> None:
|
|||
)
|
||||
group._addoption(
|
||||
"-c",
|
||||
metavar="file",
|
||||
"--config-file",
|
||||
metavar="FILE",
|
||||
type=str,
|
||||
dest="inifilename",
|
||||
help="Load configuration from `file` instead of trying to locate one of the "
|
||||
"implicit configuration files",
|
||||
help="Load configuration from `FILE` instead of trying to locate one of the "
|
||||
"implicit configuration files.",
|
||||
)
|
||||
group._addoption(
|
||||
"--continue-on-collection-errors",
|
||||
|
|
|
@ -22,6 +22,7 @@ import _pytest._code
|
|||
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
|
||||
|
@ -432,8 +433,8 @@ class Node(metaclass=NodeMeta):
|
|||
assert current is None or isinstance(current, cls)
|
||||
return current
|
||||
|
||||
def _prunetraceback(self, excinfo: ExceptionInfo[BaseException]) -> None:
|
||||
pass
|
||||
def _traceback_filter(self, excinfo: ExceptionInfo[BaseException]) -> Traceback:
|
||||
return excinfo.traceback
|
||||
|
||||
def _repr_failure_py(
|
||||
self,
|
||||
|
@ -449,10 +450,13 @@ class Node(metaclass=NodeMeta):
|
|||
style = "value"
|
||||
if isinstance(excinfo.value, FixtureLookupError):
|
||||
return excinfo.value.formatrepr()
|
||||
|
||||
tbfilter: Union[bool, Callable[[ExceptionInfo[BaseException]], Traceback]]
|
||||
if self.config.getoption("fulltrace", False):
|
||||
style = "long"
|
||||
tbfilter = False
|
||||
else:
|
||||
self._prunetraceback(excinfo)
|
||||
tbfilter = self._traceback_filter
|
||||
if style == "auto":
|
||||
style = "long"
|
||||
# XXX should excinfo.getrepr record all data and toterminal() process it?
|
||||
|
@ -483,7 +487,7 @@ class Node(metaclass=NodeMeta):
|
|||
abspath=abspath,
|
||||
showlocals=self.config.getoption("showlocals", False),
|
||||
style=style,
|
||||
tbfilter=False, # pruned already, or in --fulltrace mode.
|
||||
tbfilter=tbfilter,
|
||||
truncate_locals=truncate_locals,
|
||||
)
|
||||
|
||||
|
@ -554,13 +558,14 @@ class Collector(Node):
|
|||
|
||||
return self._repr_failure_py(excinfo, style=tbstyle)
|
||||
|
||||
def _prunetraceback(self, excinfo: ExceptionInfo[BaseException]) -> None:
|
||||
def _traceback_filter(self, excinfo: ExceptionInfo[BaseException]) -> Traceback:
|
||||
if hasattr(self, "path"):
|
||||
traceback = excinfo.traceback
|
||||
ntraceback = traceback.cut(path=self.path)
|
||||
if ntraceback == traceback:
|
||||
ntraceback = ntraceback.cut(excludepath=tracebackcutdir)
|
||||
excinfo.traceback = ntraceback.filter()
|
||||
return excinfo.traceback.filter(excinfo)
|
||||
return excinfo.traceback
|
||||
|
||||
|
||||
def _check_initialpaths_for_relpath(session: "Session", path: Path) -> Optional[str]:
|
||||
|
|
|
@ -35,6 +35,7 @@ from _pytest._code import filter_traceback
|
|||
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._io import TerminalWriter
|
||||
from _pytest._io.saferepr import saferepr
|
||||
from _pytest.compat import ascii_escaped
|
||||
|
@ -1838,7 +1839,7 @@ class Function(PyobjMixin, nodes.Item):
|
|||
def setup(self) -> None:
|
||||
self._request._fillfixtures()
|
||||
|
||||
def _prunetraceback(self, excinfo: ExceptionInfo[BaseException]) -> None:
|
||||
def _traceback_filter(self, excinfo: ExceptionInfo[BaseException]) -> Traceback:
|
||||
if hasattr(self, "_obj") and not self.config.getoption("fulltrace", False):
|
||||
code = _pytest._code.Code.from_function(get_real_func(self.obj))
|
||||
path, firstlineno = code.path, code.firstlineno
|
||||
|
@ -1850,14 +1851,21 @@ class Function(PyobjMixin, nodes.Item):
|
|||
ntraceback = ntraceback.filter(filter_traceback)
|
||||
if not ntraceback:
|
||||
ntraceback = traceback
|
||||
ntraceback = ntraceback.filter(excinfo)
|
||||
|
||||
excinfo.traceback = ntraceback.filter()
|
||||
# issue364: mark all but first and last frames to
|
||||
# only show a single-line message for each frame.
|
||||
if self.config.getoption("tbstyle", "auto") == "auto":
|
||||
if len(excinfo.traceback) > 2:
|
||||
for entry in excinfo.traceback[1:-1]:
|
||||
entry.set_repr_style("short")
|
||||
if len(ntraceback) > 2:
|
||||
ntraceback = Traceback(
|
||||
entry
|
||||
if i == 0 or i == len(ntraceback) - 1
|
||||
else entry.with_repr_style("short")
|
||||
for i, entry in enumerate(ntraceback)
|
||||
)
|
||||
|
||||
return ntraceback
|
||||
return excinfo.traceback
|
||||
|
||||
# TODO: Type ignored -- breaks Liskov Substitution.
|
||||
def repr_failure( # type: ignore[override]
|
||||
|
|
|
@ -334,15 +334,16 @@ class TestCaseFunction(Function):
|
|||
finally:
|
||||
delattr(self._testcase, self.name)
|
||||
|
||||
def _prunetraceback(
|
||||
def _traceback_filter(
|
||||
self, excinfo: _pytest._code.ExceptionInfo[BaseException]
|
||||
) -> None:
|
||||
super()._prunetraceback(excinfo)
|
||||
traceback = excinfo.traceback.filter(
|
||||
lambda x: not x.frame.f_globals.get("__unittest")
|
||||
) -> _pytest._code.Traceback:
|
||||
traceback = super()._traceback_filter(excinfo)
|
||||
ntraceback = traceback.filter(
|
||||
lambda x: not x.frame.f_globals.get("__unittest"),
|
||||
)
|
||||
if traceback:
|
||||
excinfo.traceback = traceback
|
||||
if not ntraceback:
|
||||
ntraceback = traceback
|
||||
return ntraceback
|
||||
|
||||
|
||||
@hookimpl(tryfirst=True)
|
||||
|
|
|
@ -11,7 +11,7 @@ from typing import Tuple
|
|||
from typing import TYPE_CHECKING
|
||||
from typing import Union
|
||||
|
||||
import _pytest
|
||||
import _pytest._code
|
||||
import pytest
|
||||
from _pytest._code.code import ExceptionChainRepr
|
||||
from _pytest._code.code import ExceptionInfo
|
||||
|
@ -186,7 +186,7 @@ class TestTraceback_f_g_h:
|
|||
|
||||
def test_traceback_filter(self):
|
||||
traceback = self.excinfo.traceback
|
||||
ntraceback = traceback.filter()
|
||||
ntraceback = traceback.filter(self.excinfo)
|
||||
assert len(ntraceback) == len(traceback) - 1
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
@ -217,7 +217,7 @@ class TestTraceback_f_g_h:
|
|||
|
||||
excinfo = pytest.raises(ValueError, h)
|
||||
traceback = excinfo.traceback
|
||||
ntraceback = traceback.filter()
|
||||
ntraceback = traceback.filter(excinfo)
|
||||
print(f"old: {traceback!r}")
|
||||
print(f"new: {ntraceback!r}")
|
||||
|
||||
|
@ -290,7 +290,7 @@ class TestTraceback_f_g_h:
|
|||
excinfo = pytest.raises(ValueError, fail)
|
||||
assert excinfo.traceback.recursionindex() is None
|
||||
|
||||
def test_traceback_getcrashentry(self):
|
||||
def test_getreprcrash(self):
|
||||
def i():
|
||||
__tracebackhide__ = True
|
||||
raise ValueError
|
||||
|
@ -306,15 +306,13 @@ class TestTraceback_f_g_h:
|
|||
g()
|
||||
|
||||
excinfo = pytest.raises(ValueError, f)
|
||||
tb = excinfo.traceback
|
||||
entry = tb.getcrashentry()
|
||||
assert entry is not None
|
||||
reprcrash = excinfo._getreprcrash()
|
||||
assert reprcrash is not None
|
||||
co = _pytest._code.Code.from_function(h)
|
||||
assert entry.frame.code.path == co.path
|
||||
assert entry.lineno == co.firstlineno + 1
|
||||
assert entry.frame.code.name == "h"
|
||||
assert reprcrash.path == str(co.path)
|
||||
assert reprcrash.lineno == co.firstlineno + 1 + 1
|
||||
|
||||
def test_traceback_getcrashentry_empty(self):
|
||||
def test_getreprcrash_empty(self):
|
||||
def g():
|
||||
__tracebackhide__ = True
|
||||
raise ValueError
|
||||
|
@ -324,7 +322,7 @@ class TestTraceback_f_g_h:
|
|||
g()
|
||||
|
||||
excinfo = pytest.raises(ValueError, f)
|
||||
assert excinfo.traceback.getcrashentry() is None
|
||||
assert excinfo._getreprcrash() is None
|
||||
|
||||
|
||||
def test_excinfo_exconly():
|
||||
|
@ -626,7 +624,7 @@ raise ValueError()
|
|||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.func1)
|
||||
excinfo.traceback = excinfo.traceback.filter()
|
||||
excinfo.traceback = excinfo.traceback.filter(excinfo)
|
||||
p = FormattedExcinfo()
|
||||
reprtb = p.repr_traceback_entry(excinfo.traceback[-1])
|
||||
|
||||
|
@ -659,7 +657,7 @@ raise ValueError()
|
|||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.func1, "m" * 90, 5, 13, "z" * 120)
|
||||
excinfo.traceback = excinfo.traceback.filter()
|
||||
excinfo.traceback = excinfo.traceback.filter(excinfo)
|
||||
entry = excinfo.traceback[-1]
|
||||
p = FormattedExcinfo(funcargs=True)
|
||||
reprfuncargs = p.repr_args(entry)
|
||||
|
@ -686,7 +684,7 @@ raise ValueError()
|
|||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.func1, "a", "b", c="d")
|
||||
excinfo.traceback = excinfo.traceback.filter()
|
||||
excinfo.traceback = excinfo.traceback.filter(excinfo)
|
||||
entry = excinfo.traceback[-1]
|
||||
p = FormattedExcinfo(funcargs=True)
|
||||
reprfuncargs = p.repr_args(entry)
|
||||
|
@ -960,7 +958,7 @@ raise ValueError()
|
|||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.f)
|
||||
excinfo.traceback = excinfo.traceback.filter()
|
||||
excinfo.traceback = excinfo.traceback.filter(excinfo)
|
||||
repr = excinfo.getrepr()
|
||||
repr.toterminal(tw_mock)
|
||||
assert tw_mock.lines[0] == ""
|
||||
|
@ -994,7 +992,7 @@ raise ValueError()
|
|||
)
|
||||
excinfo = pytest.raises(ValueError, mod.f)
|
||||
tmp_path.joinpath("mod.py").unlink()
|
||||
excinfo.traceback = excinfo.traceback.filter()
|
||||
excinfo.traceback = excinfo.traceback.filter(excinfo)
|
||||
repr = excinfo.getrepr()
|
||||
repr.toterminal(tw_mock)
|
||||
assert tw_mock.lines[0] == ""
|
||||
|
@ -1026,7 +1024,7 @@ raise ValueError()
|
|||
)
|
||||
excinfo = pytest.raises(ValueError, mod.f)
|
||||
tmp_path.joinpath("mod.py").write_text("asdf")
|
||||
excinfo.traceback = excinfo.traceback.filter()
|
||||
excinfo.traceback = excinfo.traceback.filter(excinfo)
|
||||
repr = excinfo.getrepr()
|
||||
repr.toterminal(tw_mock)
|
||||
assert tw_mock.lines[0] == ""
|
||||
|
@ -1123,9 +1121,11 @@ raise ValueError()
|
|||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.f)
|
||||
excinfo.traceback = excinfo.traceback.filter()
|
||||
excinfo.traceback[1].set_repr_style("short")
|
||||
excinfo.traceback[2].set_repr_style("short")
|
||||
excinfo.traceback = excinfo.traceback.filter(excinfo)
|
||||
excinfo.traceback = _pytest._code.Traceback(
|
||||
entry if i not in (1, 2) else entry.with_repr_style("short")
|
||||
for i, entry in enumerate(excinfo.traceback)
|
||||
)
|
||||
r = excinfo.getrepr(style="long")
|
||||
r.toterminal(tw_mock)
|
||||
for line in tw_mock.lines:
|
||||
|
@ -1391,7 +1391,7 @@ raise ValueError()
|
|||
with pytest.raises(TypeError) as excinfo:
|
||||
mod.f()
|
||||
# previously crashed with `AttributeError: list has no attribute get`
|
||||
excinfo.traceback.filter()
|
||||
excinfo.traceback.filter(excinfo)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("style", ["short", "long"])
|
||||
|
@ -1603,3 +1603,48 @@ def test_all_entries_hidden(pytester: Pytester, tbstyle: str) -> None:
|
|||
result.stdout.fnmatch_lines(["*ZeroDivisionError: division by zero"])
|
||||
if tbstyle not in ("line", "native"):
|
||||
result.stdout.fnmatch_lines(["All traceback entries are hidden.*"])
|
||||
|
||||
|
||||
def test_hidden_entries_of_chained_exceptions_are_not_shown(pytester: Pytester) -> None:
|
||||
"""Hidden entries of chained exceptions are not shown (#1904)."""
|
||||
p = pytester.makepyfile(
|
||||
"""
|
||||
def g1():
|
||||
__tracebackhide__ = True
|
||||
str.does_not_exist
|
||||
|
||||
def f3():
|
||||
__tracebackhide__ = True
|
||||
1 / 0
|
||||
|
||||
def f2():
|
||||
try:
|
||||
f3()
|
||||
except Exception:
|
||||
g1()
|
||||
|
||||
def f1():
|
||||
__tracebackhide__ = True
|
||||
f2()
|
||||
|
||||
def test():
|
||||
f1()
|
||||
"""
|
||||
)
|
||||
result = pytester.runpytest(str(p), "--tb=short")
|
||||
assert result.ret == 1
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*.py:11: in f2",
|
||||
" f3()",
|
||||
"E ZeroDivisionError: division by zero",
|
||||
"",
|
||||
"During handling of the above exception, another exception occurred:",
|
||||
"*.py:20: in test",
|
||||
" f1()",
|
||||
"*.py:13: in f2",
|
||||
" g1()",
|
||||
"E AttributeError:*'does_not_exist'",
|
||||
],
|
||||
consecutive=True,
|
||||
)
|
||||
|
|
|
@ -1234,3 +1234,100 @@ def test_log_disabling_works_with_log_cli(pytester: Pytester) -> None:
|
|||
"WARNING disabled:test_log_disabling_works_with_log_cli.py:7 This string will be suppressed."
|
||||
)
|
||||
assert not result.stderr.lines
|
||||
|
||||
|
||||
def test_without_date_format_log(pytester: Pytester) -> None:
|
||||
"""Check that date is not printed by default."""
|
||||
pytester.makepyfile(
|
||||
"""
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def test_foo():
|
||||
logger.warning('text')
|
||||
assert False
|
||||
"""
|
||||
)
|
||||
result = pytester.runpytest()
|
||||
assert result.ret == 1
|
||||
result.stdout.fnmatch_lines(
|
||||
["WARNING test_without_date_format_log:test_without_date_format_log.py:6 text"]
|
||||
)
|
||||
|
||||
|
||||
def test_date_format_log(pytester: Pytester) -> None:
|
||||
"""Check that log_date_format affects output."""
|
||||
pytester.makepyfile(
|
||||
"""
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def test_foo():
|
||||
logger.warning('text')
|
||||
assert False
|
||||
"""
|
||||
)
|
||||
pytester.makeini(
|
||||
"""
|
||||
[pytest]
|
||||
log_format=%(asctime)s; %(levelname)s; %(message)s
|
||||
log_date_format=%Y-%m-%d %H:%M:%S
|
||||
"""
|
||||
)
|
||||
result = pytester.runpytest()
|
||||
assert result.ret == 1
|
||||
result.stdout.re_match_lines([r"^[0-9-]{10} [0-9:]{8}; WARNING; text"])
|
||||
|
||||
|
||||
def test_date_format_percentf_log(pytester: Pytester) -> None:
|
||||
"""Make sure that microseconds are printed in log."""
|
||||
pytester.makepyfile(
|
||||
"""
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def test_foo():
|
||||
logger.warning('text')
|
||||
assert False
|
||||
"""
|
||||
)
|
||||
pytester.makeini(
|
||||
"""
|
||||
[pytest]
|
||||
log_format=%(asctime)s; %(levelname)s; %(message)s
|
||||
log_date_format=%Y-%m-%d %H:%M:%S.%f
|
||||
"""
|
||||
)
|
||||
result = pytester.runpytest()
|
||||
assert result.ret == 1
|
||||
result.stdout.re_match_lines([r"^[0-9-]{10} [0-9:]{8}.[0-9]{6}; WARNING; text"])
|
||||
|
||||
|
||||
def test_date_format_percentf_tz_log(pytester: Pytester) -> None:
|
||||
"""Make sure that timezone and microseconds are properly formatted together."""
|
||||
pytester.makepyfile(
|
||||
"""
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def test_foo():
|
||||
logger.warning('text')
|
||||
assert False
|
||||
"""
|
||||
)
|
||||
pytester.makeini(
|
||||
"""
|
||||
[pytest]
|
||||
log_format=%(asctime)s; %(levelname)s; %(message)s
|
||||
log_date_format=%Y-%m-%d %H:%M:%S.%f%z
|
||||
"""
|
||||
)
|
||||
result = pytester.runpytest()
|
||||
assert result.ret == 1
|
||||
result.stdout.re_match_lines(
|
||||
[r"^[0-9-]{10} [0-9:]{8}.[0-9]{6}[+-][0-9\.]+; WARNING; text"]
|
||||
)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
anyio[curio,trio]==3.6.2
|
||||
anyio[curio,trio]==3.7.0
|
||||
django==4.2.1
|
||||
pytest-asyncio==0.21.0
|
||||
pytest-bdd==6.1.1
|
||||
pytest-cov==4.0.0
|
||||
pytest-cov==4.1.0
|
||||
pytest-django==4.5.2
|
||||
pytest-flakes==4.0.5
|
||||
pytest-html==3.2.0
|
||||
|
|
|
@ -1003,9 +1003,9 @@ class TestTracebackCutting:
|
|||
with pytest.raises(pytest.skip.Exception) as excinfo:
|
||||
pytest.skip("xxx")
|
||||
assert excinfo.traceback[-1].frame.code.name == "skip"
|
||||
assert excinfo.traceback[-1].ishidden()
|
||||
assert excinfo.traceback[-1].ishidden(excinfo)
|
||||
assert excinfo.traceback[-2].frame.code.name == "test_skip_simple"
|
||||
assert not excinfo.traceback[-2].ishidden()
|
||||
assert not excinfo.traceback[-2].ishidden(excinfo)
|
||||
|
||||
def test_traceback_argsetup(self, pytester: Pytester) -> None:
|
||||
pytester.makeconftest(
|
||||
|
|
|
@ -1436,6 +1436,96 @@ 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(
|
||||
"""
|
||||
def test_in_string():
|
||||
assert (obj := "foo") in obj
|
||||
"""
|
||||
)
|
||||
result = pytester.runpytest()
|
||||
assert result.ret == 0
|
||||
|
||||
def test_assertion_walrus_operator_in_operand_json_dumps(
|
||||
self, pytester: Pytester
|
||||
) -> None:
|
||||
pytester.makepyfile(
|
||||
"""
|
||||
import json
|
||||
|
||||
def test_json_encoder():
|
||||
assert (obj := "foo") in json.dumps(obj)
|
||||
"""
|
||||
)
|
||||
result = pytester.runpytest()
|
||||
assert result.ret == 0
|
||||
|
||||
def test_assertion_walrus_operator_equals_operand_function(
|
||||
self, pytester: Pytester
|
||||
) -> None:
|
||||
pytester.makepyfile(
|
||||
"""
|
||||
def f(a):
|
||||
return a
|
||||
|
||||
def test_call_other_function_arg():
|
||||
assert (obj := "foo") == f(obj)
|
||||
"""
|
||||
)
|
||||
result = pytester.runpytest()
|
||||
assert result.ret == 0
|
||||
|
||||
def test_assertion_walrus_operator_equals_operand_function_keyword_arg(
|
||||
self, pytester: Pytester
|
||||
) -> None:
|
||||
pytester.makepyfile(
|
||||
"""
|
||||
def f(a='test'):
|
||||
return a
|
||||
|
||||
def test_call_other_function_k_arg():
|
||||
assert (obj := "foo") == f(a=obj)
|
||||
"""
|
||||
)
|
||||
result = pytester.runpytest()
|
||||
assert result.ret == 0
|
||||
|
||||
def test_assertion_walrus_operator_equals_operand_function_arg_as_function(
|
||||
self, pytester: Pytester
|
||||
) -> None:
|
||||
pytester.makepyfile(
|
||||
"""
|
||||
def f(a='test'):
|
||||
return a
|
||||
|
||||
def test_function_of_function():
|
||||
assert (obj := "foo") == f(f(obj))
|
||||
"""
|
||||
)
|
||||
result = pytester.runpytest()
|
||||
assert result.ret == 0
|
||||
|
||||
def test_assertion_walrus_operator_gt_operand_function(
|
||||
self, pytester: Pytester
|
||||
) -> None:
|
||||
pytester.makepyfile(
|
||||
"""
|
||||
def add_one(a):
|
||||
return a + 1
|
||||
|
||||
def test_gt():
|
||||
assert (obj := 4) > add_one(obj)
|
||||
"""
|
||||
)
|
||||
result = pytester.runpytest()
|
||||
assert result.ret == 1
|
||||
result.stdout.fnmatch_lines(["*assert 4 > 5", "*where 5 = add_one(4)"])
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
sys.maxsize <= (2**31 - 1), reason="Causes OverflowError on 32bit systems"
|
||||
)
|
||||
|
|
|
@ -420,7 +420,13 @@ class TestLastFailed:
|
|||
result = pytester.runpytest()
|
||||
result.stdout.fnmatch_lines(["*1 failed in*"])
|
||||
|
||||
def test_terminal_report_lastfailed(self, pytester: Pytester) -> None:
|
||||
@pytest.mark.parametrize("parent", ("session", "package"))
|
||||
def test_terminal_report_lastfailed(self, pytester: Pytester, parent: str) -> None:
|
||||
if parent == "package":
|
||||
pytester.makepyfile(
|
||||
__init__="",
|
||||
)
|
||||
|
||||
test_a = pytester.makepyfile(
|
||||
test_a="""
|
||||
def test_a1(): pass
|
||||
|
|
|
@ -179,6 +179,23 @@ class TestParseIni:
|
|||
assert result.ret != 0
|
||||
result.stderr.fnmatch_lines("ERROR: *pyproject.toml: Invalid statement*")
|
||||
|
||||
def test_confcutdir_default_without_configfile(self, pytester: Pytester) -> None:
|
||||
# If --confcutdir is not specified, and there is no configfile, default
|
||||
# to the roothpath.
|
||||
sub = pytester.mkdir("sub")
|
||||
os.chdir(sub)
|
||||
config = pytester.parseconfigure()
|
||||
assert config.pluginmanager._confcutdir == sub
|
||||
|
||||
def test_confcutdir_default_with_configfile(self, pytester: Pytester) -> None:
|
||||
# If --confcutdir is not specified, and there is a configfile, default
|
||||
# to the configfile's directory.
|
||||
pytester.makeini("[pytest]")
|
||||
sub = pytester.mkdir("sub")
|
||||
os.chdir(sub)
|
||||
config = pytester.parseconfigure()
|
||||
assert config.pluginmanager._confcutdir == pytester.path
|
||||
|
||||
@pytest.mark.xfail(reason="probably not needed")
|
||||
def test_confcutdir(self, pytester: Pytester) -> None:
|
||||
sub = pytester.mkdir("sub")
|
||||
|
@ -514,6 +531,8 @@ class TestConfigCmdlineParsing:
|
|||
)
|
||||
config = pytester.parseconfig("-c", "custom.ini")
|
||||
assert config.getini("custom") == "1"
|
||||
config = pytester.parseconfig("--config-file", "custom.ini")
|
||||
assert config.getini("custom") == "1"
|
||||
|
||||
pytester.makefile(
|
||||
".cfg",
|
||||
|
@ -524,6 +543,8 @@ class TestConfigCmdlineParsing:
|
|||
)
|
||||
config = pytester.parseconfig("-c", "custom_tool_pytest_section.cfg")
|
||||
assert config.getini("custom") == "1"
|
||||
config = pytester.parseconfig("--config-file", "custom_tool_pytest_section.cfg")
|
||||
assert config.getini("custom") == "1"
|
||||
|
||||
pytester.makefile(
|
||||
".toml",
|
||||
|
@ -536,6 +557,8 @@ class TestConfigCmdlineParsing:
|
|||
)
|
||||
config = pytester.parseconfig("-c", "custom.toml")
|
||||
assert config.getini("custom") == "1"
|
||||
config = pytester.parseconfig("--config-file", "custom.toml")
|
||||
assert config.getini("custom") == "1"
|
||||
|
||||
def test_absolute_win32_path(self, pytester: Pytester) -> None:
|
||||
temp_ini_file = pytester.makefile(
|
||||
|
@ -550,6 +573,8 @@ class TestConfigCmdlineParsing:
|
|||
temp_ini_file_norm = normpath(str(temp_ini_file))
|
||||
ret = pytest.main(["-c", temp_ini_file_norm])
|
||||
assert ret == ExitCode.OK
|
||||
ret = pytest.main(["--config-file", temp_ini_file_norm])
|
||||
assert ret == ExitCode.OK
|
||||
|
||||
|
||||
class TestConfigAPI:
|
||||
|
@ -1907,6 +1932,9 @@ class TestSetupCfg:
|
|||
with pytest.raises(pytest.fail.Exception):
|
||||
pytester.runpytest("-c", "custom.cfg")
|
||||
|
||||
with pytest.raises(pytest.fail.Exception):
|
||||
pytester.runpytest("--config-file", "custom.cfg")
|
||||
|
||||
|
||||
class TestPytestPluginsVariable:
|
||||
def test_pytest_plugins_in_non_top_level_conftest_unsupported(
|
||||
|
|
|
@ -594,7 +594,13 @@ class TestConftestVisibility:
|
|||
print("pytestarg : %s" % testarg)
|
||||
print("expected pass : %s" % expect_ntests_passed)
|
||||
os.chdir(dirs[chdir])
|
||||
reprec = pytester.inline_run(testarg, "-q", "--traceconfig")
|
||||
reprec = pytester.inline_run(
|
||||
testarg,
|
||||
"-q",
|
||||
"--traceconfig",
|
||||
"--confcutdir",
|
||||
pytester.path,
|
||||
)
|
||||
reprec.assertoutcome(passed=expect_ntests_passed)
|
||||
|
||||
|
||||
|
|
|
@ -777,6 +777,20 @@ class TestStackLevel:
|
|||
)
|
||||
|
||||
|
||||
def test_warning_on_testpaths_not_found(pytester: Pytester) -> None:
|
||||
# Check for warning when testpaths set, but not found by glob
|
||||
pytester.makeini(
|
||||
"""
|
||||
[pytest]
|
||||
testpaths = absent
|
||||
"""
|
||||
)
|
||||
result = pytester.runpytest()
|
||||
result.stdout.fnmatch_lines(
|
||||
["*ConfigWarning: No files were found in testpaths*", "*1 warning*"]
|
||||
)
|
||||
|
||||
|
||||
def test_resource_warning(pytester: Pytester, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
# Some platforms (notably PyPy) don't have tracemalloc.
|
||||
# We choose to explicitly not skip this in case tracemalloc is not
|
||||
|
|
Loading…
Reference in New Issue