Merge branch 'main' into raisesgroup
This commit is contained in:
commit
7d90cb64b7
|
@ -26,7 +26,7 @@ jobs:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Build and Check Package
|
- name: Build and Check Package
|
||||||
uses: hynek/build-and-inspect-python-package@v1.5.4
|
uses: hynek/build-and-inspect-python-package@v2.0.0
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
if: github.repository == 'pytest-dev/pytest'
|
if: github.repository == 'pytest-dev/pytest'
|
||||||
|
@ -41,13 +41,13 @@ jobs:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Download Package
|
- name: Download Package
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: Packages
|
name: Packages
|
||||||
path: dist
|
path: dist
|
||||||
|
|
||||||
- name: Publish package to PyPI
|
- name: Publish package to PyPI
|
||||||
uses: pypa/gh-action-pypi-publish@v1.8.10
|
uses: pypa/gh-action-pypi-publish@v1.8.11
|
||||||
|
|
||||||
- name: Push tag
|
- name: Push tag
|
||||||
run: |
|
run: |
|
||||||
|
@ -72,8 +72,14 @@ jobs:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Download Package
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: Packages
|
||||||
|
path: dist
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v4
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: "3.11"
|
python-version: "3.11"
|
||||||
|
|
||||||
|
@ -82,9 +88,14 @@ jobs:
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install --upgrade tox
|
pip install --upgrade tox
|
||||||
|
|
||||||
- name: Publish GitHub release notes
|
- name: Generate release notes
|
||||||
env:
|
|
||||||
GH_RELEASE_NOTES_TOKEN: ${{ github.token }}
|
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get install pandoc
|
sudo apt-get install pandoc
|
||||||
tox -e publish-gh-release-notes
|
tox -e generate-gh-release-notes -- ${{ github.event.inputs.version }} scripts/latest-release-notes.md
|
||||||
|
|
||||||
|
- name: Publish GitHub Release
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
body_path: scripts/latest-release-notes.md
|
||||||
|
files: dist/*
|
||||||
|
tag_name: ${{ github.event.inputs.version }}
|
||||||
|
|
|
@ -32,7 +32,7 @@ jobs:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v4
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: "3.8"
|
python-version: "3.8"
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ jobs:
|
||||||
permissions:
|
permissions:
|
||||||
issues: write
|
issues: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/stale@v8
|
- uses: actions/stale@v9
|
||||||
with:
|
with:
|
||||||
debug-only: false
|
debug-only: false
|
||||||
days-before-issue-stale: 14
|
days-before-issue-stale: 14
|
||||||
|
|
|
@ -35,7 +35,7 @@ jobs:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Build and Check Package
|
- name: Build and Check Package
|
||||||
uses: hynek/build-and-inspect-python-package@v1.5.4
|
uses: hynek/build-and-inspect-python-package@v2.0.0
|
||||||
|
|
||||||
build:
|
build:
|
||||||
needs: [package]
|
needs: [package]
|
||||||
|
@ -156,7 +156,7 @@ jobs:
|
||||||
tox_env: "py312-xdist"
|
tox_env: "py312-xdist"
|
||||||
|
|
||||||
- name: "plugins"
|
- name: "plugins"
|
||||||
python: "3.9"
|
python: "3.12"
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
tox_env: "plugins"
|
tox_env: "plugins"
|
||||||
|
|
||||||
|
@ -173,13 +173,13 @@ jobs:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Download Package
|
- name: Download Package
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: Packages
|
name: Packages
|
||||||
path: dist
|
path: dist
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python }}
|
- name: Set up Python ${{ matrix.python }}
|
||||||
uses: actions/setup-python@v4
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python }}
|
python-version: ${{ matrix.python }}
|
||||||
check-latest: ${{ endsWith(matrix.python, '-dev') }}
|
check-latest: ${{ endsWith(matrix.python, '-dev') }}
|
||||||
|
|
|
@ -25,7 +25,7 @@ jobs:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v4
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: "3.11"
|
python-version: "3.11"
|
||||||
cache: pip
|
cache: pip
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/psf/black
|
- repo: https://github.com/psf/black
|
||||||
rev: 23.11.0
|
rev: 23.12.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
args: [--safe, --quiet]
|
args: [--safe, --quiet]
|
||||||
|
@ -29,7 +29,7 @@ repos:
|
||||||
language: python
|
language: python
|
||||||
files: \.py$
|
files: \.py$
|
||||||
- repo: https://github.com/PyCQA/flake8
|
- repo: https://github.com/PyCQA/flake8
|
||||||
rev: 6.1.0
|
rev: 7.0.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: flake8
|
- id: flake8
|
||||||
language_version: python3
|
language_version: python3
|
||||||
|
@ -56,17 +56,19 @@ repos:
|
||||||
hooks:
|
hooks:
|
||||||
- id: python-use-type-annotations
|
- id: python-use-type-annotations
|
||||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||||
rev: v1.7.1
|
rev: v1.8.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: mypy
|
- id: mypy
|
||||||
files: ^(src/|testing/)
|
files: ^(src/|testing/|scripts/)
|
||||||
args: []
|
args: []
|
||||||
additional_dependencies:
|
additional_dependencies:
|
||||||
- iniconfig>=1.1.0
|
- iniconfig>=1.1.0
|
||||||
- attrs>=19.2.0
|
- attrs>=19.2.0
|
||||||
|
- pluggy
|
||||||
- packaging
|
- packaging
|
||||||
- tomli
|
- tomli
|
||||||
- types-pkg_resources
|
- types-pkg_resources
|
||||||
|
- types-tabulate
|
||||||
# for mypy running on python>=3.11 since exceptiongroup is only a dependency
|
# for mypy running on python>=3.11 since exceptiongroup is only a dependency
|
||||||
# on <3.11
|
# on <3.11
|
||||||
- exceptiongroup>=1.0.0rc8
|
- exceptiongroup>=1.0.0rc8
|
||||||
|
|
6
AUTHORS
6
AUTHORS
|
@ -48,11 +48,13 @@ Ariel Pillemer
|
||||||
Armin Rigo
|
Armin Rigo
|
||||||
Aron Coyle
|
Aron Coyle
|
||||||
Aron Curzon
|
Aron Curzon
|
||||||
|
Arthur Richard
|
||||||
Ashish Kurmi
|
Ashish Kurmi
|
||||||
Aviral Verma
|
Aviral Verma
|
||||||
Aviv Palivoda
|
Aviv Palivoda
|
||||||
Babak Keyvani
|
Babak Keyvani
|
||||||
Barney Gale
|
Barney Gale
|
||||||
|
Ben Brown
|
||||||
Ben Gartner
|
Ben Gartner
|
||||||
Ben Webb
|
Ben Webb
|
||||||
Benjamin Peterson
|
Benjamin Peterson
|
||||||
|
@ -136,8 +138,10 @@ Erik Hasse
|
||||||
Erik M. Bray
|
Erik M. Bray
|
||||||
Evan Kepner
|
Evan Kepner
|
||||||
Evgeny Seliverstov
|
Evgeny Seliverstov
|
||||||
|
Fabian Sturm
|
||||||
Fabien Zarifian
|
Fabien Zarifian
|
||||||
Fabio Zadrozny
|
Fabio Zadrozny
|
||||||
|
faph
|
||||||
Felix Hofstätter
|
Felix Hofstätter
|
||||||
Felix Nieuwenhuizen
|
Felix Nieuwenhuizen
|
||||||
Feng Ma
|
Feng Ma
|
||||||
|
@ -241,6 +245,7 @@ Marc Mueller
|
||||||
Marc Schlaich
|
Marc Schlaich
|
||||||
Marcelo Duarte Trevisani
|
Marcelo Duarte Trevisani
|
||||||
Marcin Bachry
|
Marcin Bachry
|
||||||
|
Marc Bresson
|
||||||
Marco Gorelli
|
Marco Gorelli
|
||||||
Mark Abramowitz
|
Mark Abramowitz
|
||||||
Mark Dickinson
|
Mark Dickinson
|
||||||
|
@ -265,6 +270,7 @@ Michael Goerz
|
||||||
Michael Krebs
|
Michael Krebs
|
||||||
Michael Seifert
|
Michael Seifert
|
||||||
Michal Wajszczuk
|
Michal Wajszczuk
|
||||||
|
Michał Górny
|
||||||
Michał Zięba
|
Michał Zięba
|
||||||
Mickey Pashov
|
Mickey Pashov
|
||||||
Mihai Capotă
|
Mihai Capotă
|
||||||
|
|
|
@ -97,8 +97,8 @@ Features
|
||||||
- `Modular fixtures <https://docs.pytest.org/en/stable/explanation/fixtures.html>`_ for
|
- `Modular fixtures <https://docs.pytest.org/en/stable/explanation/fixtures.html>`_ for
|
||||||
managing small or parametrized long-lived test resources
|
managing small or parametrized long-lived test resources
|
||||||
|
|
||||||
- Can run `unittest <https://docs.pytest.org/en/stable/how-to/unittest.html>`_ (or trial),
|
- 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
|
test suites out of the box
|
||||||
|
|
||||||
- Python 3.8+ or PyPy3
|
- Python 3.8+ or PyPy3
|
||||||
|
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
Added :func:`ExceptionInfo.group_contains() <pytest.ExceptionInfo.group_contains>`, an assertion
|
|
||||||
helper that tests if an `ExceptionGroup` contains a matching exception.
|
|
|
@ -1 +0,0 @@
|
||||||
Test functions returning a value other than None will now issue a :class:`pytest.PytestWarning` instead of :class:`pytest.PytestRemovedIn8Warning`, meaning this will stay a warning instead of becoming an error in the future.
|
|
|
@ -1,2 +0,0 @@
|
||||||
Added more comprehensive set assertion rewrites for comparisons other than equality ``==``, with
|
|
||||||
the following operations now providing better failure messages: ``!=``, ``<=``, ``>=``, ``<``, and ``>``.
|
|
|
@ -1,2 +0,0 @@
|
||||||
:meth:`pytest.WarningsRecorder.pop` will return the most-closely-matched warning in the list,
|
|
||||||
rather than the first warning which is an instance of the requested type.
|
|
|
@ -1 +0,0 @@
|
||||||
Added a warning about modifying the root logger during tests when using ``caplog``.
|
|
|
@ -1,3 +0,0 @@
|
||||||
Use pytestconfig instead of request.config in cache example
|
|
||||||
|
|
||||||
to be consistent with the API documentation.
|
|
|
@ -1 +0,0 @@
|
||||||
Updated documentation and tests to refer to hyphonated options: replaced ``--junitxml`` with ``--junit-xml`` and ``--collectonly`` with ``--collect-only``.
|
|
|
@ -1,6 +0,0 @@
|
||||||
``pluggy>=1.2.0`` is now required.
|
|
||||||
|
|
||||||
pytest now uses "new-style" hook wrappers internally, available since pluggy 1.2.0.
|
|
||||||
See `pluggy's 1.2.0 changelog <https://pluggy.readthedocs.io/en/latest/changelog.html#pluggy-1-2-0-2023-06-21>`_ and the :ref:`updated docs <hookwrapper>` for details.
|
|
||||||
|
|
||||||
Plugins which want to use new-style wrappers can do so if they require this version of pytest or later.
|
|
|
@ -1,11 +0,0 @@
|
||||||
:class:`pytest.Package` is no longer a :class:`pytest.Module` or :class:`pytest.File`.
|
|
||||||
|
|
||||||
The ``Package`` collector node designates a Python package, that is, a directory with an `__init__.py` file.
|
|
||||||
Previously ``Package`` was a subtype of ``pytest.Module`` (which represents a single Python module),
|
|
||||||
the module being the `__init__.py` file.
|
|
||||||
This has been deemed a design mistake (see :issue:`11137` and :issue:`7777` for details).
|
|
||||||
|
|
||||||
The ``path`` property of ``Package`` nodes now points to the package directory instead of the ``__init__.py`` file.
|
|
||||||
|
|
||||||
Note that a ``Module`` node for ``__init__.py`` (which is not a ``Package``) may still exist,
|
|
||||||
if it is picked up during collection (e.g. if you configured :confval:`python_files` to include ``__init__.py`` files).
|
|
|
@ -1 +0,0 @@
|
||||||
- Prevent constants at the top of file from being detected as docstrings.
|
|
|
@ -1 +0,0 @@
|
||||||
Dropped support for Python 3.7, which `reached end-of-life on 2023-06-27 <https://devguide.python.org/versions/>`__.
|
|
|
@ -1,2 +0,0 @@
|
||||||
The (internal) ``FixtureDef.cached_result`` type has changed.
|
|
||||||
Now the third item ``cached_result[2]``, when set, is an exception instance instead of an exception triplet.
|
|
|
@ -1 +0,0 @@
|
||||||
If a test is skipped from inside an :ref:`xunit setup fixture <classic xunit>`, the test summary now shows the test location instead of the fixture location.
|
|
|
@ -1,5 +0,0 @@
|
||||||
(This entry is meant to assist plugins which access private pytest internals to instantiate ``FixtureRequest`` objects.)
|
|
||||||
|
|
||||||
:class:`~pytest.FixtureRequest` is now an abstract class which can't be instantiated directly.
|
|
||||||
A new concrete ``TopRequest`` subclass of ``FixtureRequest`` has been added for the ``request`` fixture in test functions,
|
|
||||||
as counterpart to the existing ``SubRequest`` subclass for the ``request`` fixture in fixture functions.
|
|
|
@ -1 +0,0 @@
|
||||||
Allow :func:`pytest.raises` ``match`` argument to match against `PEP-678 <https://peps.python.org/pep-0678/>` ``__notes__``.
|
|
|
@ -1 +0,0 @@
|
||||||
Fixed crash on `parametrize(..., scope="package")` without a package present.
|
|
|
@ -1,2 +0,0 @@
|
||||||
Fixed a bug that when there are multiple fixtures for an indirect parameter,
|
|
||||||
the scope of the highest-scope fixture is picked for the parameter set, instead of that of the one with the narrowest scope.
|
|
|
@ -1,11 +0,0 @@
|
||||||
Sanitized the handling of the ``default`` parameter when defining configuration options.
|
|
||||||
|
|
||||||
Previously if ``default`` was not supplied for :meth:`parser.addini <pytest.Parser.addini>` and the configuration option value was not defined in a test session, then calls to :func:`config.getini <pytest.Config.getini>` returned an *empty list* or an *empty string* depending on whether ``type`` was supplied or not respectively, which is clearly incorrect. Also, ``None`` was not honored even if ``default=None`` was used explicitly while defining the option.
|
|
||||||
|
|
||||||
Now the behavior of :meth:`parser.addini <pytest.Parser.addini>` is as follows:
|
|
||||||
|
|
||||||
* If ``default`` is NOT passed but ``type`` is provided, then a type-specific default will be returned. For example ``type=bool`` will return ``False``, ``type=str`` will return ``""``, etc.
|
|
||||||
* If ``default=None`` is passed and the option is not defined in a test session, then ``None`` will be returned, regardless of the ``type``.
|
|
||||||
* If neither ``default`` nor ``type`` are provided, assume ``type=str`` and return ``""`` as default (this is as per previous behavior).
|
|
||||||
|
|
||||||
The team decided to not introduce a deprecation period for this change, as doing so would be complicated both in terms of communicating this to the community as well as implementing it, and also because the team believes this change should not break existing plugins except in rare cases.
|
|
|
@ -1,2 +0,0 @@
|
||||||
Logging to a file using the ``--log-file`` option will use ``--log-level``, ``--log-format`` and ``--log-date-format`` as fallback
|
|
||||||
if ``--log-file-level``, ``--log-file-format`` and ``--log-file-date-format`` are not provided respectively.
|
|
|
@ -1,3 +0,0 @@
|
||||||
The :fixture:`pytester` fixture now uses the :fixture:`monkeypatch` fixture to manage the current working directory.
|
|
||||||
If you use ``pytester`` in combination with :func:`monkeypatch.undo() <pytest.MonkeyPatch.undo>`, the CWD might get restored.
|
|
||||||
Use :func:`monkeypatch.context() <pytest.MonkeyPatch.context>` instead.
|
|
|
@ -1,2 +0,0 @@
|
||||||
Corrected the spelling of ``Config.ArgsSource.INVOCATION_DIR``.
|
|
||||||
The previous spelling ``INCOVATION_DIR`` remains as an alias.
|
|
|
@ -1 +0,0 @@
|
||||||
pluggy>=1.3.0 is now required. This adds typing to :class:`~pytest.PytestPluginManager`.
|
|
|
@ -1,5 +0,0 @@
|
||||||
Added the new :confval:`verbosity_assertions` configuration option for fine-grained control of failed assertions verbosity.
|
|
||||||
|
|
||||||
See :ref:`Fine-grained verbosity <pytest.fine_grained_verbosity>` for more details.
|
|
||||||
|
|
||||||
For plugin authors, :attr:`config.get_verbosity <pytest.Config.get_verbosity>` can be used to retrieve the verbosity level for a specific verbosity type.
|
|
|
@ -1 +0,0 @@
|
||||||
:func:`pytest.deprecated_call` now also considers warnings of type :class:`FutureWarning`.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Parametrized tests now *really do* ensure that the ids given to each input are unique - for
|
|
||||||
example, ``a, a, a0`` now results in ``a1, a2, a0`` instead of the previous (buggy) ``a0, a1, a0``.
|
|
||||||
This necessarily means changing nodeids where these were previously colliding, and for
|
|
||||||
readability adds an underscore when non-unique ids end in a number.
|
|
|
@ -1 +0,0 @@
|
||||||
Improved very verbose diff output to color it as a diff instead of only red.
|
|
|
@ -1 +0,0 @@
|
||||||
Fixed crash when using an empty string for the same parametrized value more than once.
|
|
|
@ -1 +0,0 @@
|
||||||
Handle an edge case where :data:`sys.stderr` and :data:`sys.__stderr__` might already be closed when :ref:`faulthandler` is tearing down.
|
|
|
@ -1 +0,0 @@
|
||||||
Improved the documentation and type signature for :func:`pytest.mark.xfail <pytest.mark.xfail>`'s ``condition`` param to use ``False`` as the default value.
|
|
|
@ -1,2 +0,0 @@
|
||||||
Added :func:`LogCaptureFixture.filtering() <pytest.LogCaptureFixture.filtering>` context manager that
|
|
||||||
adds a given :class:`logging.Filter` object to the caplog fixture.
|
|
|
@ -1 +0,0 @@
|
||||||
Fixed the selftests to pass correctly if ``FORCE_COLOR``, ``NO_COLOR`` or ``PY_COLORS`` is set in the calling environment.
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
Some changes were made to private functions which may affect plugins which access them:
|
||||||
|
|
||||||
|
- ``FixtureManager._getautousenames()`` now takes a ``Node`` itself instead of the nodeid.
|
||||||
|
- ``FixtureManager.getfixturedefs()`` now takes the ``Node`` itself instead of the nodeid.
|
||||||
|
- The ``_pytest.nodes.iterparentnodeids()`` function is removed without replacement.
|
||||||
|
Prefer to traverse the node hierarchy itself instead.
|
||||||
|
If you really need to, copy the function from the previous pytest release.
|
|
@ -0,0 +1 @@
|
||||||
|
Documented the retention of temporary directories created using the ``tmp_path`` fixture in more detail.
|
|
@ -0,0 +1,2 @@
|
||||||
|
Added the :func:`iter_parents() <_pytest.nodes.Node.iter_parents>` helper method on nodes.
|
||||||
|
It is similar to :func:`listchain <_pytest.nodes.Node.listchain>`, but goes from bottom to top, and returns an iterator, not a list.
|
|
@ -0,0 +1 @@
|
||||||
|
Properly escape the ``reason`` of a :ref:`skip <pytest.mark.skip ref>` mark when writing JUnit XML files.
|
|
@ -1,4 +0,0 @@
|
||||||
Improved the very verbose diff for every standard library container types: the indentation is now consistent and the markers are on their own separate lines, which should reduce the diffs shown to users.
|
|
||||||
|
|
||||||
Previously, the default python pretty printer was used to generate the output, which puts opening and closing
|
|
||||||
markers on the same line as the first/last entry, in addition to not having consistent indentation.
|
|
|
@ -1,3 +0,0 @@
|
||||||
Applying a mark to a fixture function now issues a warning: marks in fixtures never had any effect, but it is a common user error to apply a mark to a fixture (for example ``usefixtures``) and expect it to work.
|
|
||||||
|
|
||||||
This will become an error in the future.
|
|
|
@ -1,22 +0,0 @@
|
||||||
**PytestRemovedIn8Warning deprecation warnings are now errors by default.**
|
|
||||||
|
|
||||||
Following our plan to remove deprecated features with as little disruption as
|
|
||||||
possible, all warnings of type ``PytestRemovedIn8Warning`` now generate errors
|
|
||||||
instead of warning messages by default.
|
|
||||||
|
|
||||||
**The affected features will be effectively removed in pytest 8.1**, so please consult the
|
|
||||||
:ref:`deprecations` section in the docs for directions on how to update existing code.
|
|
||||||
|
|
||||||
In the pytest ``8.0.X`` series, it is possible to change the errors back into warnings as a
|
|
||||||
stopgap measure by adding this to your ``pytest.ini`` file:
|
|
||||||
|
|
||||||
.. code-block:: ini
|
|
||||||
|
|
||||||
[pytest]
|
|
||||||
filterwarnings =
|
|
||||||
ignore::pytest.PytestRemovedIn8Warning
|
|
||||||
|
|
||||||
But this will stop working when pytest ``8.1`` is released.
|
|
||||||
|
|
||||||
**If you have concerns** about the removal of a specific feature, please add a
|
|
||||||
comment to :issue:`7363`.
|
|
|
@ -1 +0,0 @@
|
||||||
:class:`~pytest.FixtureDef` is now exported as ``pytest.FixtureDef`` for typing purposes.
|
|
|
@ -1 +0,0 @@
|
||||||
Removes unhelpful error message from assertion rewrite mechanism when exceptions raised in __iter__ methods, and instead treats them as un-iterable.
|
|
|
@ -1,5 +0,0 @@
|
||||||
Running `pytest pkg/__init__.py` now collects the `pkg/__init__.py` file (module) only.
|
|
||||||
Previously, it collected the entire `pkg` package, including other test files in the directory, but excluding tests in the `__init__.py` file itself
|
|
||||||
(unless :confval:`python_files` was changed to allow `__init__.py` file).
|
|
||||||
|
|
||||||
To collect the entire package, specify just the directory: `pytest pkg`.
|
|
|
@ -1 +0,0 @@
|
||||||
``pytest.warns`` and similar functions now capture warnings when an exception is raised inside a ``with`` block.
|
|
|
@ -1,7 +0,0 @@
|
||||||
: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.
|
|
|
@ -44,7 +44,7 @@ Partner projects, sign up here! (by 22 March)
|
||||||
What does it mean to "adopt pytest"?
|
What does it mean to "adopt pytest"?
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
|
||||||
There can be many different definitions of "success". Pytest can run many nose_ and unittest_ tests by default, so using pytest as your testrunner may be possible from day 1. Job done, right?
|
There can be many different definitions of "success". Pytest can run many unittest_ tests by default, so using pytest as your testrunner may be possible from day 1. Job done, right?
|
||||||
|
|
||||||
Progressive success might look like:
|
Progressive success might look like:
|
||||||
|
|
||||||
|
@ -62,7 +62,6 @@ Progressive success might look like:
|
||||||
|
|
||||||
It may be after the month is up, the partner project decides that pytest is not right for it. That's okay - hopefully the pytest team will also learn something about its weaknesses or deficiencies.
|
It may be after the month is up, the partner project decides that pytest is not right for it. That's okay - hopefully the pytest team will also learn something about its weaknesses or deficiencies.
|
||||||
|
|
||||||
.. _nose: nose.html
|
|
||||||
.. _unittest: unittest.html
|
.. _unittest: unittest.html
|
||||||
.. _assert: assert.html
|
.. _assert: assert.html
|
||||||
.. _pycmd: https://bitbucket.org/hpk42/pycmd/overview
|
.. _pycmd: https://bitbucket.org/hpk42/pycmd/overview
|
||||||
|
|
|
@ -6,6 +6,9 @@ Release announcements
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
|
|
||||||
|
release-8.0.0rc2
|
||||||
|
release-8.0.0rc1
|
||||||
|
release-7.4.4
|
||||||
release-7.4.3
|
release-7.4.3
|
||||||
release-7.4.2
|
release-7.4.2
|
||||||
release-7.4.1
|
release-7.4.1
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
pytest-7.4.4
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
pytest 7.4.4 has just been released to PyPI.
|
||||||
|
|
||||||
|
This is a bug-fix release, being a drop-in replacement. To upgrade::
|
||||||
|
|
||||||
|
pip install --upgrade pytest
|
||||||
|
|
||||||
|
The full changelog is available at https://docs.pytest.org/en/stable/changelog.html.
|
||||||
|
|
||||||
|
Thanks to all of the contributors to this release:
|
||||||
|
|
||||||
|
* Bruno Oliveira
|
||||||
|
* Ran Benita
|
||||||
|
* Zac Hatfield-Dodds
|
||||||
|
|
||||||
|
|
||||||
|
Happy testing,
|
||||||
|
The pytest Development Team
|
|
@ -0,0 +1,82 @@
|
||||||
|
pytest-8.0.0rc1
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
The pytest team is proud to announce the 8.0.0rc1 release!
|
||||||
|
|
||||||
|
This release contains new features, improvements, bug fixes, and breaking changes, so users
|
||||||
|
are encouraged to take a look at the CHANGELOG carefully:
|
||||||
|
|
||||||
|
https://docs.pytest.org/en/stable/changelog.html
|
||||||
|
|
||||||
|
For complete documentation, please visit:
|
||||||
|
|
||||||
|
https://docs.pytest.org/en/stable/
|
||||||
|
|
||||||
|
As usual, you can upgrade from PyPI via:
|
||||||
|
|
||||||
|
pip install -U pytest
|
||||||
|
|
||||||
|
Thanks to all of the contributors to this release:
|
||||||
|
|
||||||
|
* Akhilesh Ramakrishnan
|
||||||
|
* Aleksandr Brodin
|
||||||
|
* Anthony Sottile
|
||||||
|
* Arthur Richard
|
||||||
|
* Avasam
|
||||||
|
* Benjamin Schubert
|
||||||
|
* Bruno Oliveira
|
||||||
|
* Carsten Grohmann
|
||||||
|
* Cheukting
|
||||||
|
* Chris Mahoney
|
||||||
|
* Christoph Anton Mitterer
|
||||||
|
* DetachHead
|
||||||
|
* Erik Hasse
|
||||||
|
* Florian Bruhin
|
||||||
|
* Fraser Stark
|
||||||
|
* Ha Pam
|
||||||
|
* Hugo van Kemenade
|
||||||
|
* Isaac Virshup
|
||||||
|
* Israel Fruchter
|
||||||
|
* Jens Tröger
|
||||||
|
* Jon Parise
|
||||||
|
* Kenny Y
|
||||||
|
* Lesnek
|
||||||
|
* Marc Mueller
|
||||||
|
* Michał Górny
|
||||||
|
* Mihail Milushev
|
||||||
|
* Milan Lesnek
|
||||||
|
* Miro Hrončok
|
||||||
|
* Patrick Lannigan
|
||||||
|
* Ran Benita
|
||||||
|
* Reagan Lee
|
||||||
|
* Ronny Pfannschmidt
|
||||||
|
* Sadra Barikbin
|
||||||
|
* Sean Malloy
|
||||||
|
* Sean Patrick Malloy
|
||||||
|
* Sharad Nair
|
||||||
|
* Simon Blanchard
|
||||||
|
* Sourabh Beniwal
|
||||||
|
* Stefaan Lippens
|
||||||
|
* Tanya Agarwal
|
||||||
|
* Thomas Grainger
|
||||||
|
* Tom Mortimer-Jones
|
||||||
|
* Tushar Sadhwani
|
||||||
|
* Tyler Smart
|
||||||
|
* Uday Kumar
|
||||||
|
* Warren Markham
|
||||||
|
* WarrenTheRabbit
|
||||||
|
* Zac Hatfield-Dodds
|
||||||
|
* Ziad Kermadi
|
||||||
|
* akhilramkee
|
||||||
|
* antosikv
|
||||||
|
* bowugit
|
||||||
|
* mickeypash
|
||||||
|
* neilmartin2000
|
||||||
|
* pomponchik
|
||||||
|
* ryanpudd
|
||||||
|
* touilleWoman
|
||||||
|
* ubaumann
|
||||||
|
|
||||||
|
|
||||||
|
Happy testing,
|
||||||
|
The pytest Development Team
|
|
@ -0,0 +1,32 @@
|
||||||
|
pytest-8.0.0rc2
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
The pytest team is proud to announce the 8.0.0rc2 prerelease!
|
||||||
|
|
||||||
|
This is a prerelease, not intended for production use, but to test the upcoming features and improvements
|
||||||
|
in order to catch any major problems before the final version is released to the major public.
|
||||||
|
|
||||||
|
We appreciate your help testing this out before the final release, making sure to report any
|
||||||
|
regressions to our issue tracker:
|
||||||
|
|
||||||
|
https://github.com/pytest-dev/pytest/issues
|
||||||
|
|
||||||
|
When doing so, please include the string ``[prerelease]`` in the title.
|
||||||
|
|
||||||
|
You can upgrade from PyPI via:
|
||||||
|
|
||||||
|
pip install pytest==8.0.0rc2
|
||||||
|
|
||||||
|
Users are encouraged to take a look at the CHANGELOG carefully:
|
||||||
|
|
||||||
|
https://docs.pytest.org/en/release-8.0.0rc2/changelog.html
|
||||||
|
|
||||||
|
Thanks to all the contributors to this release:
|
||||||
|
|
||||||
|
* Ben Brown
|
||||||
|
* Bruno Oliveira
|
||||||
|
* Ran Benita
|
||||||
|
|
||||||
|
|
||||||
|
Happy testing,
|
||||||
|
The pytest Development Team
|
|
@ -22,7 +22,7 @@ b) transitional: the old and new API don't conflict
|
||||||
|
|
||||||
We will only start the removal of deprecated functionality in major releases (e.g. if we deprecate something in 3.0 we will start to remove it in 4.0), and keep it around for at least two minor releases (e.g. if we deprecate something in 3.9 and 4.0 is the next release, we start to remove it in 5.0, not in 4.0).
|
We will only start the removal of deprecated functionality in major releases (e.g. if we deprecate something in 3.0 we will start to remove it in 4.0), and keep it around for at least two minor releases (e.g. if we deprecate something in 3.9 and 4.0 is the next release, we start to remove it in 5.0, not in 4.0).
|
||||||
|
|
||||||
A deprecated feature scheduled to be removed in major version X will use the warning class `PytestRemovedInXWarning` (a subclass of :class:`~pytest.PytestDeprecationwarning`).
|
A deprecated feature scheduled to be removed in major version X will use the warning class `PytestRemovedInXWarning` (a subclass of :class:`~pytest.PytestDeprecationWarning`).
|
||||||
|
|
||||||
When the deprecation expires (e.g. 4.0 is released), we won't remove the deprecated functionality immediately, but will use the standard warning filters to turn `PytestRemovedInXWarning` (e.g. `PytestRemovedIn4Warning`) into **errors** by default. This approach makes it explicit that removal is imminent, and still gives you time to turn the deprecated feature into a warning instead of an error so it can be dealt with in your own time. In the next minor release (e.g. 4.1), the feature will be effectively removed.
|
When the deprecation expires (e.g. 4.0 is released), we won't remove the deprecated functionality immediately, but will use the standard warning filters to turn `PytestRemovedInXWarning` (e.g. `PytestRemovedIn4Warning`) into **errors** by default. This approach makes it explicit that removal is imminent, and still gives you time to turn the deprecated feature into a warning instead of an error so it can be dealt with in your own time. In the next minor release (e.g. 4.1), the feature will be effectively removed.
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,11 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
|
||||||
|
|
||||||
$ pytest --fixtures -v
|
$ pytest --fixtures -v
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
||||||
cachedir: .pytest_cache
|
cachedir: .pytest_cache
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 0 items
|
collected 0 items
|
||||||
cache -- .../_pytest/cacheprovider.py:532
|
cache -- .../_pytest/cacheprovider.py:526
|
||||||
Return a cache object that can persist state between testing sessions.
|
Return a cache object that can persist state between testing sessions.
|
||||||
|
|
||||||
cache.get(key, default)
|
cache.get(key, default)
|
||||||
|
@ -33,7 +33,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
|
||||||
|
|
||||||
Values can be any object handled by the json stdlib module.
|
Values can be any object handled by the json stdlib module.
|
||||||
|
|
||||||
capsysbinary -- .../_pytest/capture.py:1001
|
capsysbinary -- .../_pytest/capture.py:1008
|
||||||
Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``.
|
Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``.
|
||||||
|
|
||||||
The captured output is made available via ``capsysbinary.readouterr()``
|
The captured output is made available via ``capsysbinary.readouterr()``
|
||||||
|
@ -51,7 +51,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
|
||||||
captured = capsysbinary.readouterr()
|
captured = capsysbinary.readouterr()
|
||||||
assert captured.out == b"hello\n"
|
assert captured.out == b"hello\n"
|
||||||
|
|
||||||
capfd -- .../_pytest/capture.py:1029
|
capfd -- .../_pytest/capture.py:1036
|
||||||
Enable text capturing of writes to file descriptors ``1`` and ``2``.
|
Enable text capturing of writes to file descriptors ``1`` and ``2``.
|
||||||
|
|
||||||
The captured output is made available via ``capfd.readouterr()`` method
|
The captured output is made available via ``capfd.readouterr()`` method
|
||||||
|
@ -69,7 +69,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
|
||||||
captured = capfd.readouterr()
|
captured = capfd.readouterr()
|
||||||
assert captured.out == "hello\n"
|
assert captured.out == "hello\n"
|
||||||
|
|
||||||
capfdbinary -- .../_pytest/capture.py:1057
|
capfdbinary -- .../_pytest/capture.py:1064
|
||||||
Enable bytes capturing of writes to file descriptors ``1`` and ``2``.
|
Enable bytes capturing of writes to file descriptors ``1`` and ``2``.
|
||||||
|
|
||||||
The captured output is made available via ``capfd.readouterr()`` method
|
The captured output is made available via ``capfd.readouterr()`` method
|
||||||
|
@ -87,7 +87,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
|
||||||
captured = capfdbinary.readouterr()
|
captured = capfdbinary.readouterr()
|
||||||
assert captured.out == b"hello\n"
|
assert captured.out == b"hello\n"
|
||||||
|
|
||||||
capsys -- .../_pytest/capture.py:973
|
capsys -- .../_pytest/capture.py:980
|
||||||
Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``.
|
Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``.
|
||||||
|
|
||||||
The captured output is made available via ``capsys.readouterr()`` method
|
The captured output is made available via ``capsys.readouterr()`` method
|
||||||
|
@ -105,7 +105,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
|
||||||
captured = capsys.readouterr()
|
captured = capsys.readouterr()
|
||||||
assert captured.out == "hello\n"
|
assert captured.out == "hello\n"
|
||||||
|
|
||||||
doctest_namespace [session scope] -- .../_pytest/doctest.py:757
|
doctest_namespace [session scope] -- .../_pytest/doctest.py:743
|
||||||
Fixture that returns a :py:class:`dict` that will be injected into the
|
Fixture that returns a :py:class:`dict` that will be injected into the
|
||||||
namespace of doctests.
|
namespace of doctests.
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
|
||||||
|
|
||||||
For more details: :ref:`doctest_namespace`.
|
For more details: :ref:`doctest_namespace`.
|
||||||
|
|
||||||
pytestconfig [session scope] -- .../_pytest/fixtures.py:1353
|
pytestconfig [session scope] -- .../_pytest/fixtures.py:1365
|
||||||
Session-scoped fixture that returns the session's :class:`pytest.Config`
|
Session-scoped fixture that returns the session's :class:`pytest.Config`
|
||||||
object.
|
object.
|
||||||
|
|
||||||
|
@ -174,10 +174,10 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
|
||||||
`pytest-xdist <https://github.com/pytest-dev/pytest-xdist>`__ plugin. See
|
`pytest-xdist <https://github.com/pytest-dev/pytest-xdist>`__ plugin. See
|
||||||
:issue:`7767` for details.
|
:issue:`7767` for details.
|
||||||
|
|
||||||
tmpdir_factory [session scope] -- .../_pytest/legacypath.py:302
|
tmpdir_factory [session scope] -- .../_pytest/legacypath.py:300
|
||||||
Return a :class:`pytest.TempdirFactory` instance for the test session.
|
Return a :class:`pytest.TempdirFactory` instance for the test session.
|
||||||
|
|
||||||
tmpdir -- .../_pytest/legacypath.py:309
|
tmpdir -- .../_pytest/legacypath.py:307
|
||||||
Return a temporary directory path object which is unique to each test
|
Return a temporary directory path object which is unique to each test
|
||||||
function invocation, created as a sub directory of the base temporary
|
function invocation, created as a sub directory of the base temporary
|
||||||
directory.
|
directory.
|
||||||
|
@ -196,7 +196,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
|
||||||
|
|
||||||
.. _legacy_path: https://py.readthedocs.io/en/latest/path.html
|
.. _legacy_path: https://py.readthedocs.io/en/latest/path.html
|
||||||
|
|
||||||
caplog -- .../_pytest/logging.py:570
|
caplog -- .../_pytest/logging.py:593
|
||||||
Access and control log capturing.
|
Access and control log capturing.
|
||||||
|
|
||||||
Captured logs are available through the following properties/methods::
|
Captured logs are available through the following properties/methods::
|
||||||
|
@ -237,10 +237,10 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
|
||||||
See https://docs.pytest.org/en/latest/how-to/capture-warnings.html for information
|
See https://docs.pytest.org/en/latest/how-to/capture-warnings.html for information
|
||||||
on warning categories.
|
on warning categories.
|
||||||
|
|
||||||
tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:245
|
tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:239
|
||||||
Return a :class:`pytest.TempPathFactory` instance for the test session.
|
Return a :class:`pytest.TempPathFactory` instance for the test session.
|
||||||
|
|
||||||
tmp_path -- .../_pytest/tmpdir.py:260
|
tmp_path -- .../_pytest/tmpdir.py:254
|
||||||
Return a temporary directory path object which is unique to each test
|
Return a temporary directory path object which is unique to each test
|
||||||
function invocation, created as a sub directory of the base temporary
|
function invocation, created as a sub directory of the base temporary
|
||||||
directory.
|
directory.
|
||||||
|
|
|
@ -28,6 +28,433 @@ with advance notice in the **Deprecations** section of releases.
|
||||||
|
|
||||||
.. towncrier release notes start
|
.. towncrier release notes start
|
||||||
|
|
||||||
|
pytest 8.0.0rc2 (2024-01-17)
|
||||||
|
============================
|
||||||
|
|
||||||
|
|
||||||
|
Improvements
|
||||||
|
------------
|
||||||
|
|
||||||
|
- `#11233 <https://github.com/pytest-dev/pytest/issues/11233>`_: Improvements to ``-r`` for xfailures and xpasses:
|
||||||
|
|
||||||
|
* Report tracebacks for xfailures when ``-rx`` is set.
|
||||||
|
* Report captured output for xpasses when ``-rX`` is set.
|
||||||
|
* For xpasses, add ``-`` in summary between test name and reason, to match how xfail is displayed.
|
||||||
|
|
||||||
|
- `#11825 <https://github.com/pytest-dev/pytest/issues/11825>`_: The :hook:`pytest_plugin_registered` hook has a new ``plugin_name`` parameter containing the name by which ``plugin`` is registered.
|
||||||
|
|
||||||
|
|
||||||
|
Bug Fixes
|
||||||
|
---------
|
||||||
|
|
||||||
|
- `#11706 <https://github.com/pytest-dev/pytest/issues/11706>`_: Fix reporting of teardown errors in higher-scoped fixtures when using `--maxfail` or `--stepwise`.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11758 <https://github.com/pytest-dev/pytest/issues/11758>`_: Fixed ``IndexError: string index out of range`` crash in ``if highlighted[-1] == "\n" and source[-1] != "\n"``.
|
||||||
|
This bug was introduced in pytest 8.0.0rc1.
|
||||||
|
|
||||||
|
|
||||||
|
- `#9765 <https://github.com/pytest-dev/pytest/issues/9765>`_, `#11816 <https://github.com/pytest-dev/pytest/issues/11816>`_: Fixed a frustrating bug that afflicted some users with the only error being ``assert mod not in mods``. The issue was caused by the fact that ``str(Path(mod))`` and ``mod.__file__`` don't necessarily produce the same string, and was being erroneously used interchangably in some places in the code.
|
||||||
|
|
||||||
|
This fix also broke the internal API of ``PytestPluginManager.consider_conftest`` by introducing a new parameter -- we mention this in case it is being used by external code, even if marked as *private*.
|
||||||
|
|
||||||
|
|
||||||
|
pytest 8.0.0rc1 (2023-12-30)
|
||||||
|
============================
|
||||||
|
|
||||||
|
Breaking Changes
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Old Deprecations Are Now Errors
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
- `#7363 <https://github.com/pytest-dev/pytest/issues/7363>`_: **PytestRemovedIn8Warning deprecation warnings are now errors by default.**
|
||||||
|
|
||||||
|
Following our plan to remove deprecated features with as little disruption as
|
||||||
|
possible, all warnings of type ``PytestRemovedIn8Warning`` now generate errors
|
||||||
|
instead of warning messages by default.
|
||||||
|
|
||||||
|
**The affected features will be effectively removed in pytest 8.1**, so please consult the
|
||||||
|
:ref:`deprecations` section in the docs for directions on how to update existing code.
|
||||||
|
|
||||||
|
In the pytest ``8.0.X`` series, it is possible to change the errors back into warnings as a
|
||||||
|
stopgap measure by adding this to your ``pytest.ini`` file:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
[pytest]
|
||||||
|
filterwarnings =
|
||||||
|
ignore::pytest.PytestRemovedIn8Warning
|
||||||
|
|
||||||
|
But this will stop working when pytest ``8.1`` is released.
|
||||||
|
|
||||||
|
**If you have concerns** about the removal of a specific feature, please add a
|
||||||
|
comment to :issue:`7363`.
|
||||||
|
|
||||||
|
|
||||||
|
Version Compatibility
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
- `#11151 <https://github.com/pytest-dev/pytest/issues/11151>`_: Dropped support for Python 3.7, which `reached end-of-life on 2023-06-27 <https://devguide.python.org/versions/>`__.
|
||||||
|
|
||||||
|
|
||||||
|
- ``pluggy>=1.3.0`` is now required.
|
||||||
|
|
||||||
|
|
||||||
|
Collection Changes
|
||||||
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
In this version we've made several breaking changes to pytest's collection phase,
|
||||||
|
particularly around how filesystem directories and Python packages are collected,
|
||||||
|
fixing deficiencies and allowing for cleanups and improvements to pytest's internals.
|
||||||
|
A deprecation period for these changes was not possible.
|
||||||
|
|
||||||
|
|
||||||
|
- `#7777 <https://github.com/pytest-dev/pytest/issues/7777>`_: Files and directories are now collected in alphabetical order jointly, unless changed by a plugin.
|
||||||
|
Previously, files were collected before directories.
|
||||||
|
See below for an example.
|
||||||
|
|
||||||
|
|
||||||
|
- `#8976 <https://github.com/pytest-dev/pytest/issues/8976>`_: Running `pytest pkg/__init__.py` now collects the `pkg/__init__.py` file (module) only.
|
||||||
|
Previously, it collected the entire `pkg` package, including other test files in the directory, but excluding tests in the `__init__.py` file itself
|
||||||
|
(unless :confval:`python_files` was changed to allow `__init__.py` file).
|
||||||
|
|
||||||
|
To collect the entire package, specify just the directory: `pytest pkg`.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11137 <https://github.com/pytest-dev/pytest/issues/11137>`_: :class:`pytest.Package` is no longer a :class:`pytest.Module` or :class:`pytest.File`.
|
||||||
|
|
||||||
|
The ``Package`` collector node designates a Python package, that is, a directory with an `__init__.py` file.
|
||||||
|
Previously ``Package`` was a subtype of ``pytest.Module`` (which represents a single Python module),
|
||||||
|
the module being the `__init__.py` file.
|
||||||
|
This has been deemed a design mistake (see :issue:`11137` and :issue:`7777` for details).
|
||||||
|
|
||||||
|
The ``path`` property of ``Package`` nodes now points to the package directory instead of the ``__init__.py`` file.
|
||||||
|
|
||||||
|
Note that a ``Module`` node for ``__init__.py`` (which is not a ``Package``) may still exist,
|
||||||
|
if it is picked up during collection (e.g. if you configured :confval:`python_files` to include ``__init__.py`` files).
|
||||||
|
|
||||||
|
|
||||||
|
- `#7777 <https://github.com/pytest-dev/pytest/issues/7777>`_: Added a new :class:`pytest.Directory` base collection node, which all collector nodes for filesystem directories are expected to subclass.
|
||||||
|
This is analogous to the existing :class:`pytest.File` for file nodes.
|
||||||
|
|
||||||
|
Changed :class:`pytest.Package` to be a subclass of :class:`pytest.Directory`.
|
||||||
|
A ``Package`` represents a filesystem directory which is a Python package,
|
||||||
|
i.e. contains an ``__init__.py`` file.
|
||||||
|
|
||||||
|
:class:`pytest.Package` now only collects files in its own directory; previously it collected recursively.
|
||||||
|
Sub-directories are collected as their own collector nodes, which then collect themselves, thus creating a collection tree which mirrors the filesystem hierarchy.
|
||||||
|
|
||||||
|
Added a new :class:`pytest.Dir` concrete collection node, a subclass of :class:`pytest.Directory`.
|
||||||
|
This node represents a filesystem directory, which is not a :class:`pytest.Package`,
|
||||||
|
that is, does not contain an ``__init__.py`` file.
|
||||||
|
Similarly to ``Package``, it only collects the files in its own directory.
|
||||||
|
|
||||||
|
:class:`pytest.Session` now only collects the initial arguments, without recursing into directories.
|
||||||
|
This work is now done by the :func:`recursive expansion process <pytest.Collector.collect>` of directory collector nodes.
|
||||||
|
|
||||||
|
:attr:`session.name <pytest.Session.name>` is now ``""``; previously it was the rootdir directory name.
|
||||||
|
This matches :attr:`session.nodeid <_pytest.nodes.Node.nodeid>` which has always been `""`.
|
||||||
|
|
||||||
|
The collection tree now contains directories/packages up to the :ref:`rootdir <rootdir>`,
|
||||||
|
for initial arguments that are found within the rootdir.
|
||||||
|
For files outside the rootdir, only the immediate directory/package is collected --
|
||||||
|
note however that collecting from outside the rootdir is discouraged.
|
||||||
|
|
||||||
|
As an example, given the following filesystem tree::
|
||||||
|
|
||||||
|
myroot/
|
||||||
|
pytest.ini
|
||||||
|
top/
|
||||||
|
├── aaa
|
||||||
|
│ └── test_aaa.py
|
||||||
|
├── test_a.py
|
||||||
|
├── test_b
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ └── test_b.py
|
||||||
|
├── test_c.py
|
||||||
|
└── zzz
|
||||||
|
├── __init__.py
|
||||||
|
└── test_zzz.py
|
||||||
|
|
||||||
|
the collection tree, as shown by `pytest --collect-only top/` but with the otherwise-hidden :class:`~pytest.Session` node added for clarity,
|
||||||
|
is now the following::
|
||||||
|
|
||||||
|
<Session>
|
||||||
|
<Dir myroot>
|
||||||
|
<Dir top>
|
||||||
|
<Dir aaa>
|
||||||
|
<Module test_aaa.py>
|
||||||
|
<Function test_it>
|
||||||
|
<Module test_a.py>
|
||||||
|
<Function test_it>
|
||||||
|
<Package test_b>
|
||||||
|
<Module test_b.py>
|
||||||
|
<Function test_it>
|
||||||
|
<Module test_c.py>
|
||||||
|
<Function test_it>
|
||||||
|
<Package zzz>
|
||||||
|
<Module test_zzz.py>
|
||||||
|
<Function test_it>
|
||||||
|
|
||||||
|
Previously, it was::
|
||||||
|
|
||||||
|
<Session>
|
||||||
|
<Module top/test_a.py>
|
||||||
|
<Function test_it>
|
||||||
|
<Module top/test_c.py>
|
||||||
|
<Function test_it>
|
||||||
|
<Module top/aaa/test_aaa.py>
|
||||||
|
<Function test_it>
|
||||||
|
<Package test_b>
|
||||||
|
<Module test_b.py>
|
||||||
|
<Function test_it>
|
||||||
|
<Package zzz>
|
||||||
|
<Module test_zzz.py>
|
||||||
|
<Function test_it>
|
||||||
|
|
||||||
|
Code/plugins which rely on a specific shape of the collection tree might need to update.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11676 <https://github.com/pytest-dev/pytest/issues/11676>`_: The classes :class:`~_pytest.nodes.Node`, :class:`~pytest.Collector`, :class:`~pytest.Item`, :class:`~pytest.File`, :class:`~_pytest.nodes.FSCollector` are now marked abstract (see :mod:`abc`).
|
||||||
|
|
||||||
|
We do not expect this change to affect users and plugin authors, it will only cause errors when the code is already wrong or problematic.
|
||||||
|
|
||||||
|
|
||||||
|
Other breaking changes
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
These are breaking changes where deprecation was not possible.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11282 <https://github.com/pytest-dev/pytest/issues/11282>`_: Sanitized the handling of the ``default`` parameter when defining configuration options.
|
||||||
|
|
||||||
|
Previously if ``default`` was not supplied for :meth:`parser.addini <pytest.Parser.addini>` and the configuration option value was not defined in a test session, then calls to :func:`config.getini <pytest.Config.getini>` returned an *empty list* or an *empty string* depending on whether ``type`` was supplied or not respectively, which is clearly incorrect. Also, ``None`` was not honored even if ``default=None`` was used explicitly while defining the option.
|
||||||
|
|
||||||
|
Now the behavior of :meth:`parser.addini <pytest.Parser.addini>` is as follows:
|
||||||
|
|
||||||
|
* If ``default`` is NOT passed but ``type`` is provided, then a type-specific default will be returned. For example ``type=bool`` will return ``False``, ``type=str`` will return ``""``, etc.
|
||||||
|
* If ``default=None`` is passed and the option is not defined in a test session, then ``None`` will be returned, regardless of the ``type``.
|
||||||
|
* If neither ``default`` nor ``type`` are provided, assume ``type=str`` and return ``""`` as default (this is as per previous behavior).
|
||||||
|
|
||||||
|
The team decided to not introduce a deprecation period for this change, as doing so would be complicated both in terms of communicating this to the community as well as implementing it, and also because the team believes this change should not break existing plugins except in rare cases.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11667 <https://github.com/pytest-dev/pytest/issues/11667>`_: pytest's ``setup.py`` file is removed.
|
||||||
|
If you relied on this file, e.g. to install pytest using ``setup.py install``,
|
||||||
|
please see `Why you shouldn't invoke setup.py directly <https://blog.ganssle.io/articles/2021/10/setup-py-deprecated.html#summary>`_ for alternatives.
|
||||||
|
|
||||||
|
|
||||||
|
- `#9288 <https://github.com/pytest-dev/pytest/issues/9288>`_: :func:`~pytest.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 announce it 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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Deprecations
|
||||||
|
------------
|
||||||
|
|
||||||
|
- `#10465 <https://github.com/pytest-dev/pytest/issues/10465>`_: Test functions returning a value other than ``None`` will now issue a :class:`pytest.PytestWarning` instead of ``pytest.PytestRemovedIn8Warning``, meaning this will stay a warning instead of becoming an error in the future.
|
||||||
|
|
||||||
|
|
||||||
|
- `#3664 <https://github.com/pytest-dev/pytest/issues/3664>`_: Applying a mark to a fixture function now issues a warning: marks in fixtures never had any effect, but it is a common user error to apply a mark to a fixture (for example ``usefixtures``) and expect it to work.
|
||||||
|
|
||||||
|
This will become an error in pytest 9.0.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Features and Improvements
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Improved Diffs
|
||||||
|
^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
These changes improve the diffs that pytest prints when an assertion fails.
|
||||||
|
Note that syntax highlighting requires the ``pygments`` package.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11520 <https://github.com/pytest-dev/pytest/issues/11520>`_: The very verbose (``-vv``) diff output is now colored as a diff instead of a big chunk of red.
|
||||||
|
|
||||||
|
Python code in error reports is now syntax-highlighted as Python.
|
||||||
|
|
||||||
|
The sections in the error reports are now better separated.
|
||||||
|
|
||||||
|
|
||||||
|
- `#1531 <https://github.com/pytest-dev/pytest/issues/1531>`_: The very verbose diff (``-vv``) for every standard library container type is improved. The indentation is now consistent and the markers are on their own separate lines, which should reduce the diffs shown to users.
|
||||||
|
|
||||||
|
Previously, the standard Python pretty printer was used to generate the output, which puts opening and closing
|
||||||
|
markers on the same line as the first/last entry, in addition to not having consistent indentation.
|
||||||
|
|
||||||
|
|
||||||
|
- `#10617 <https://github.com/pytest-dev/pytest/issues/10617>`_: Added more comprehensive set assertion rewrites for comparisons other than equality ``==``, with
|
||||||
|
the following operations now providing better failure messages: ``!=``, ``<=``, ``>=``, ``<``, and ``>``.
|
||||||
|
|
||||||
|
|
||||||
|
Separate Control For Assertion Verbosity
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
- `#11387 <https://github.com/pytest-dev/pytest/issues/11387>`_: Added the new :confval:`verbosity_assertions` configuration option for fine-grained control of failed assertions verbosity.
|
||||||
|
|
||||||
|
If you've ever wished that pytest always show you full diffs, but without making everything else verbose, this is for you.
|
||||||
|
|
||||||
|
See :ref:`Fine-grained verbosity <pytest.fine_grained_verbosity>` for more details.
|
||||||
|
|
||||||
|
For plugin authors, :attr:`config.get_verbosity <pytest.Config.get_verbosity>` can be used to retrieve the verbosity level for a specific verbosity type.
|
||||||
|
|
||||||
|
|
||||||
|
Additional Support For Exception Groups and ``__notes__``
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
These changes improve pytest's support for exception groups.
|
||||||
|
|
||||||
|
|
||||||
|
- `#10441 <https://github.com/pytest-dev/pytest/issues/10441>`_: Added :func:`ExceptionInfo.group_contains() <pytest.ExceptionInfo.group_contains>`, an assertion helper that tests if an :class:`ExceptionGroup` contains a matching exception.
|
||||||
|
|
||||||
|
See :ref:`assert-matching-exception-groups` for an example.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11227 <https://github.com/pytest-dev/pytest/issues/11227>`_: Allow :func:`pytest.raises` ``match`` argument to match against `PEP-678 <https://peps.python.org/pep-0678/>` ``__notes__``.
|
||||||
|
|
||||||
|
|
||||||
|
Custom Directory collectors
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
- `#7777 <https://github.com/pytest-dev/pytest/issues/7777>`_: Added a new hook :hook:`pytest_collect_directory`,
|
||||||
|
which is called by filesystem-traversing collector nodes,
|
||||||
|
such as :class:`pytest.Session`, :class:`pytest.Dir` and :class:`pytest.Package`,
|
||||||
|
to create a collector node for a sub-directory.
|
||||||
|
It is expected to return a subclass of :class:`pytest.Directory`.
|
||||||
|
This hook allows plugins to :ref:`customize the collection of directories <custom directory collectors>`.
|
||||||
|
|
||||||
|
|
||||||
|
"New-style" Hook Wrappers
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
- `#11122 <https://github.com/pytest-dev/pytest/issues/11122>`_: pytest now uses "new-style" hook wrappers internally, available since pluggy 1.2.0.
|
||||||
|
See `pluggy's 1.2.0 changelog <https://pluggy.readthedocs.io/en/latest/changelog.html#pluggy-1-2-0-2023-06-21>`_ and the :ref:`updated docs <hookwrapper>` for details.
|
||||||
|
|
||||||
|
Plugins which want to use new-style wrappers can do so if they require ``pytest>=8``.
|
||||||
|
|
||||||
|
|
||||||
|
Other Improvements
|
||||||
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
- `#11216 <https://github.com/pytest-dev/pytest/issues/11216>`_: If a test is skipped from inside an :ref:`xunit setup fixture <classic xunit>`, the test summary now shows the test location instead of the fixture location.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11314 <https://github.com/pytest-dev/pytest/issues/11314>`_: Logging to a file using the ``--log-file`` option will use ``--log-level``, ``--log-format`` and ``--log-date-format`` as fallback
|
||||||
|
if ``--log-file-level``, ``--log-file-format`` and ``--log-file-date-format`` are not provided respectively.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11610 <https://github.com/pytest-dev/pytest/issues/11610>`_: Added the :func:`LogCaptureFixture.filtering() <pytest.LogCaptureFixture.filtering>` context manager which
|
||||||
|
adds a given :class:`logging.Filter` object to the :fixture:`caplog` fixture.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11447 <https://github.com/pytest-dev/pytest/issues/11447>`_: :func:`pytest.deprecated_call` now also considers warnings of type :class:`FutureWarning`.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11600 <https://github.com/pytest-dev/pytest/issues/11600>`_: Improved the documentation and type signature for :func:`pytest.mark.xfail <pytest.mark.xfail>`'s ``condition`` param to use ``False`` as the default value.
|
||||||
|
|
||||||
|
|
||||||
|
- `#7469 <https://github.com/pytest-dev/pytest/issues/7469>`_: :class:`~pytest.FixtureDef` is now exported as ``pytest.FixtureDef`` for typing purposes.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11353 <https://github.com/pytest-dev/pytest/issues/11353>`_: Added typing to :class:`~pytest.PytestPluginManager`.
|
||||||
|
|
||||||
|
|
||||||
|
Bug Fixes
|
||||||
|
---------
|
||||||
|
|
||||||
|
- `#10701 <https://github.com/pytest-dev/pytest/issues/10701>`_: :meth:`pytest.WarningsRecorder.pop` will return the most-closely-matched warning in the list,
|
||||||
|
rather than the first warning which is an instance of the requested type.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11255 <https://github.com/pytest-dev/pytest/issues/11255>`_: Fixed crash on `parametrize(..., scope="package")` without a package present.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11277 <https://github.com/pytest-dev/pytest/issues/11277>`_: Fixed a bug that when there are multiple fixtures for an indirect parameter,
|
||||||
|
the scope of the highest-scope fixture is picked for the parameter set, instead of that of the one with the narrowest scope.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11456 <https://github.com/pytest-dev/pytest/issues/11456>`_: Parametrized tests now *really do* ensure that the ids given to each input are unique - for
|
||||||
|
example, ``a, a, a0`` now results in ``a1, a2, a0`` instead of the previous (buggy) ``a0, a1, a0``.
|
||||||
|
This necessarily means changing nodeids where these were previously colliding, and for
|
||||||
|
readability adds an underscore when non-unique ids end in a number.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11563 <https://github.com/pytest-dev/pytest/issues/11563>`_: Fixed a crash when using an empty string for the same parametrized value more than once.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11712 <https://github.com/pytest-dev/pytest/issues/11712>`_: Fixed handling ``NO_COLOR`` and ``FORCE_COLOR`` to ignore an empty value.
|
||||||
|
|
||||||
|
|
||||||
|
- `#9036 <https://github.com/pytest-dev/pytest/issues/9036>`_: ``pytest.warns`` and similar functions now capture warnings when an exception is raised inside a ``with`` block.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Improved Documentation
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
- `#11011 <https://github.com/pytest-dev/pytest/issues/11011>`_: Added a warning about modifying the root logger during tests when using ``caplog``.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11065 <https://github.com/pytest-dev/pytest/issues/11065>`_: Use ``pytestconfig`` instead of ``request.config`` in cache example to be consistent with the API documentation.
|
||||||
|
|
||||||
|
|
||||||
|
Trivial/Internal Changes
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
- `#11208 <https://github.com/pytest-dev/pytest/issues/11208>`_: The (internal) ``FixtureDef.cached_result`` type has changed.
|
||||||
|
Now the third item ``cached_result[2]``, when set, is an exception instance instead of an exception triplet.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11218 <https://github.com/pytest-dev/pytest/issues/11218>`_: (This entry is meant to assist plugins which access private pytest internals to instantiate ``FixtureRequest`` objects.)
|
||||||
|
|
||||||
|
:class:`~pytest.FixtureRequest` is now an abstract class which can't be instantiated directly.
|
||||||
|
A new concrete ``TopRequest`` subclass of ``FixtureRequest`` has been added for the ``request`` fixture in test functions,
|
||||||
|
as counterpart to the existing ``SubRequest`` subclass for the ``request`` fixture in fixture functions.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11315 <https://github.com/pytest-dev/pytest/issues/11315>`_: The :fixture:`pytester` fixture now uses the :fixture:`monkeypatch` fixture to manage the current working directory.
|
||||||
|
If you use ``pytester`` in combination with :func:`monkeypatch.undo() <pytest.MonkeyPatch.undo>`, the CWD might get restored.
|
||||||
|
Use :func:`monkeypatch.context() <pytest.MonkeyPatch.context>` instead.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11333 <https://github.com/pytest-dev/pytest/issues/11333>`_: Corrected the spelling of ``Config.ArgsSource.INVOCATION_DIR``.
|
||||||
|
The previous spelling ``INCOVATION_DIR`` remains as an alias.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11638 <https://github.com/pytest-dev/pytest/issues/11638>`_: Fixed the selftests to pass correctly if ``FORCE_COLOR``, ``NO_COLOR`` or ``PY_COLORS`` is set in the calling environment.
|
||||||
|
|
||||||
|
pytest 7.4.4 (2023-12-31)
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Bug Fixes
|
||||||
|
---------
|
||||||
|
|
||||||
|
- `#11140 <https://github.com/pytest-dev/pytest/issues/11140>`_: Fix non-string constants at the top of file being detected as docstrings on Python>=3.8.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11572 <https://github.com/pytest-dev/pytest/issues/11572>`_: Handle an edge case where :data:`sys.stderr` and :data:`sys.__stderr__` might already be closed when :ref:`faulthandler` is tearing down.
|
||||||
|
|
||||||
|
|
||||||
|
- `#11710 <https://github.com/pytest-dev/pytest/issues/11710>`_: Fixed tracebacks from collection errors not getting pruned.
|
||||||
|
|
||||||
|
|
||||||
|
- `#7966 <https://github.com/pytest-dev/pytest/issues/7966>`_: Removed unhelpful error message from assertion rewrite mechanism when exceptions are raised in ``__iter__`` methods. Now they are treated un-iterable instead.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Improved Documentation
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
- `#11091 <https://github.com/pytest-dev/pytest/issues/11091>`_: Updated documentation to refer to hyphenated options: replaced ``--junitxml`` with ``--junit-xml`` and ``--collectonly`` with ``--collect-only``.
|
||||||
|
|
||||||
|
|
||||||
pytest 7.4.3 (2023-10-24)
|
pytest 7.4.3 (2023-10-24)
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
|
@ -413,7 +840,7 @@ Improvements
|
||||||
|
|
||||||
|
|
||||||
- `#8508 <https://github.com/pytest-dev/pytest/issues/8508>`_: Introduce multiline display for warning matching via :py:func:`pytest.warns` and
|
- `#8508 <https://github.com/pytest-dev/pytest/issues/8508>`_: Introduce multiline display for warning matching via :py:func:`pytest.warns` and
|
||||||
enhance match comparison for :py:func:`_pytest._code.ExceptionInfo.match` as returned by :py:func:`pytest.raises`.
|
enhance match comparison for :py:func:`pytest.ExceptionInfo.match` as returned by :py:func:`pytest.raises`.
|
||||||
|
|
||||||
|
|
||||||
- `#8646 <https://github.com/pytest-dev/pytest/issues/8646>`_: Improve :py:func:`pytest.raises`. Previously passing an empty tuple would give a confusing
|
- `#8646 <https://github.com/pytest-dev/pytest/issues/8646>`_: Improve :py:func:`pytest.raises`. Previously passing an empty tuple would give a confusing
|
||||||
|
@ -422,7 +849,7 @@ Improvements
|
||||||
|
|
||||||
- `#9741 <https://github.com/pytest-dev/pytest/issues/9741>`_: On Python 3.11, use the standard library's :mod:`tomllib` to parse TOML.
|
- `#9741 <https://github.com/pytest-dev/pytest/issues/9741>`_: On Python 3.11, use the standard library's :mod:`tomllib` to parse TOML.
|
||||||
|
|
||||||
:mod:`tomli` is no longer a dependency on Python 3.11.
|
`tomli` is no longer a dependency on Python 3.11.
|
||||||
|
|
||||||
|
|
||||||
- `#9742 <https://github.com/pytest-dev/pytest/issues/9742>`_: Display assertion message without escaped newline characters with ``-vv``.
|
- `#9742 <https://github.com/pytest-dev/pytest/issues/9742>`_: Display assertion message without escaped newline characters with ``-vv``.
|
||||||
|
@ -457,7 +884,7 @@ Bug Fixes
|
||||||
|
|
||||||
When inheriting marks from super-classes, marks from the sub-classes are now ordered before marks from the super-classes, in MRO order. Previously it was the reverse.
|
When inheriting marks from super-classes, marks from the sub-classes are now ordered before marks from the super-classes, in MRO order. Previously it was the reverse.
|
||||||
|
|
||||||
When inheriting marks from super-classes, the `pytestmark` attribute of the sub-class now only contains the marks directly applied to it. Previously, it also contained marks from its super-classes. Please note that this attribute should not normally be accessed directly; use :func:`pytest.Node.iter_markers` instead.
|
When inheriting marks from super-classes, the `pytestmark` attribute of the sub-class now only contains the marks directly applied to it. Previously, it also contained marks from its super-classes. Please note that this attribute should not normally be accessed directly; use :func:`Node.iter_markers <_pytest.nodes.Node.iter_markers>` instead.
|
||||||
|
|
||||||
|
|
||||||
- `#9159 <https://github.com/pytest-dev/pytest/issues/9159>`_: Showing inner exceptions by forcing native display in ``ExceptionGroups`` even when using display options other than ``--tb=native``. A temporary step before full implementation of pytest-native display for inner exceptions in ``ExceptionGroups``.
|
- `#9159 <https://github.com/pytest-dev/pytest/issues/9159>`_: Showing inner exceptions by forcing native display in ``ExceptionGroups`` even when using display options other than ``--tb=native``. A temporary step before full implementation of pytest-native display for inner exceptions in ``ExceptionGroups``.
|
||||||
|
@ -710,7 +1137,7 @@ Bug Fixes
|
||||||
- `#9355 <https://github.com/pytest-dev/pytest/issues/9355>`_: Fixed error message prints function decorators when using assert in Python 3.8 and above.
|
- `#9355 <https://github.com/pytest-dev/pytest/issues/9355>`_: Fixed error message prints function decorators when using assert in Python 3.8 and above.
|
||||||
|
|
||||||
|
|
||||||
- `#9396 <https://github.com/pytest-dev/pytest/issues/9396>`_: Ensure :attr:`pytest.Config.inifile` is available during the :func:`pytest_cmdline_main <_pytest.hookspec.pytest_cmdline_main>` hook (regression during ``7.0.0rc1``).
|
- `#9396 <https://github.com/pytest-dev/pytest/issues/9396>`_: Ensure `pytest.Config.inifile` is available during the :hook:`pytest_cmdline_main` hook (regression during ``7.0.0rc1``).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -855,13 +1282,13 @@ Deprecations
|
||||||
- ``parser.addoption(..., type="int/string/float/complex")`` - use ``type=int`` etc. instead.
|
- ``parser.addoption(..., type="int/string/float/complex")`` - use ``type=int`` etc. instead.
|
||||||
|
|
||||||
|
|
||||||
- `#8447 <https://github.com/pytest-dev/pytest/issues/8447>`_: Defining a custom pytest node type which is both an :class:`pytest.Item <Item>` and a :class:`pytest.Collector <Collector>` (e.g. :class:`pytest.File <File>`) now issues a warning.
|
- `#8447 <https://github.com/pytest-dev/pytest/issues/8447>`_: Defining a custom pytest node type which is both an :class:`~pytest.Item` and a :class:`~pytest.Collector` (e.g. :class:`~pytest.File`) now issues a warning.
|
||||||
It was never sanely supported and triggers hard to debug errors.
|
It was never sanely supported and triggers hard to debug errors.
|
||||||
|
|
||||||
See :ref:`the deprecation note <diamond-inheritance-deprecated>` for full details.
|
See :ref:`the deprecation note <diamond-inheritance-deprecated>` for full details.
|
||||||
|
|
||||||
|
|
||||||
- `#8592 <https://github.com/pytest-dev/pytest/issues/8592>`_: :hook:`pytest_cmdline_preparse` has been officially deprecated. It will be removed in a future release. Use :hook:`pytest_load_initial_conftests` instead.
|
- `#8592 <https://github.com/pytest-dev/pytest/issues/8592>`_: ``pytest_cmdline_preparse`` has been officially deprecated. It will be removed in a future release. Use :hook:`pytest_load_initial_conftests` instead.
|
||||||
|
|
||||||
See :ref:`the deprecation note <cmdline-preparse-deprecated>` for full details.
|
See :ref:`the deprecation note <cmdline-preparse-deprecated>` for full details.
|
||||||
|
|
||||||
|
@ -897,7 +1324,7 @@ Features
|
||||||
- `#7132 <https://github.com/pytest-dev/pytest/issues/7132>`_: Added two environment variables :envvar:`PYTEST_THEME` and :envvar:`PYTEST_THEME_MODE` to let the users customize the pygments theme used.
|
- `#7132 <https://github.com/pytest-dev/pytest/issues/7132>`_: Added two environment variables :envvar:`PYTEST_THEME` and :envvar:`PYTEST_THEME_MODE` to let the users customize the pygments theme used.
|
||||||
|
|
||||||
|
|
||||||
- `#7259 <https://github.com/pytest-dev/pytest/issues/7259>`_: Added :meth:`cache.mkdir() <pytest.Cache.mkdir>`, which is similar to the existing :meth:`cache.makedir() <pytest.Cache.makedir>`,
|
- `#7259 <https://github.com/pytest-dev/pytest/issues/7259>`_: Added :meth:`cache.mkdir() <pytest.Cache.mkdir>`, which is similar to the existing ``cache.makedir()``,
|
||||||
but returns a :class:`pathlib.Path` instead of a legacy ``py.path.local``.
|
but returns a :class:`pathlib.Path` instead of a legacy ``py.path.local``.
|
||||||
|
|
||||||
Added a ``paths`` type to :meth:`parser.addini() <pytest.Parser.addini>`,
|
Added a ``paths`` type to :meth:`parser.addini() <pytest.Parser.addini>`,
|
||||||
|
@ -923,7 +1350,7 @@ Features
|
||||||
- ``pytest.HookRecorder`` for the :class:`HookRecorder <pytest.HookRecorder>` type returned from :class:`~pytest.Pytester`.
|
- ``pytest.HookRecorder`` for the :class:`HookRecorder <pytest.HookRecorder>` type returned from :class:`~pytest.Pytester`.
|
||||||
- ``pytest.RecordedHookCall`` for the :class:`RecordedHookCall <pytest.HookRecorder>` type returned from :class:`~pytest.HookRecorder`.
|
- ``pytest.RecordedHookCall`` for the :class:`RecordedHookCall <pytest.HookRecorder>` type returned from :class:`~pytest.HookRecorder`.
|
||||||
- ``pytest.RunResult`` for the :class:`RunResult <pytest.RunResult>` type returned from :class:`~pytest.Pytester`.
|
- ``pytest.RunResult`` for the :class:`RunResult <pytest.RunResult>` type returned from :class:`~pytest.Pytester`.
|
||||||
- ``pytest.LineMatcher`` for the :class:`LineMatcher <pytest.RunResult>` type used in :class:`~pytest.RunResult` and others.
|
- ``pytest.LineMatcher`` for the :class:`LineMatcher <pytest.LineMatcher>` type used in :class:`~pytest.RunResult` and others.
|
||||||
- ``pytest.TestReport`` for the :class:`TestReport <pytest.TestReport>` type used in various hooks.
|
- ``pytest.TestReport`` for the :class:`TestReport <pytest.TestReport>` type used in various hooks.
|
||||||
- ``pytest.CollectReport`` for the :class:`CollectReport <pytest.CollectReport>` type used in various hooks.
|
- ``pytest.CollectReport`` for the :class:`CollectReport <pytest.CollectReport>` type used in various hooks.
|
||||||
|
|
||||||
|
@ -956,7 +1383,7 @@ Features
|
||||||
|
|
||||||
|
|
||||||
- `#8251 <https://github.com/pytest-dev/pytest/issues/8251>`_: Implement ``Node.path`` as a ``pathlib.Path``. Both the old ``fspath`` and this new attribute gets set no matter whether ``path`` or ``fspath`` (deprecated) is passed to the constructor. It is a replacement for the ``fspath`` attribute (which represents the same path as ``py.path.local``). While ``fspath`` is not deprecated yet
|
- `#8251 <https://github.com/pytest-dev/pytest/issues/8251>`_: Implement ``Node.path`` as a ``pathlib.Path``. Both the old ``fspath`` and this new attribute gets set no matter whether ``path`` or ``fspath`` (deprecated) is passed to the constructor. It is a replacement for the ``fspath`` attribute (which represents the same path as ``py.path.local``). While ``fspath`` is not deprecated yet
|
||||||
due to the ongoing migration of methods like :meth:`~_pytest.Item.reportinfo`, we expect to deprecate it in a future release.
|
due to the ongoing migration of methods like :meth:`~pytest.Item.reportinfo`, we expect to deprecate it in a future release.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
The name of the :class:`~_pytest.nodes.Node` arguments and attributes (the
|
The name of the :class:`~_pytest.nodes.Node` arguments and attributes (the
|
||||||
|
@ -988,7 +1415,7 @@ Features
|
||||||
See :ref:`plugin-stash` for details.
|
See :ref:`plugin-stash` for details.
|
||||||
|
|
||||||
|
|
||||||
- `#8953 <https://github.com/pytest-dev/pytest/issues/8953>`_: :class:`RunResult <_pytest.pytester.RunResult>` method :meth:`assert_outcomes <_pytest.pytester.RunResult.assert_outcomes>` now accepts a
|
- `#8953 <https://github.com/pytest-dev/pytest/issues/8953>`_: :class:`~pytest.RunResult` method :meth:`~pytest.RunResult.assert_outcomes` now accepts a
|
||||||
``warnings`` argument to assert the total number of warnings captured.
|
``warnings`` argument to assert the total number of warnings captured.
|
||||||
|
|
||||||
|
|
||||||
|
@ -1000,7 +1427,7 @@ Features
|
||||||
used.
|
used.
|
||||||
|
|
||||||
|
|
||||||
- `#9113 <https://github.com/pytest-dev/pytest/issues/9113>`_: :class:`RunResult <_pytest.pytester.RunResult>` method :meth:`assert_outcomes <_pytest.pytester.RunResult.assert_outcomes>` now accepts a
|
- `#9113 <https://github.com/pytest-dev/pytest/issues/9113>`_: :class:`~pytest.RunResult` method :meth:`~pytest.RunResult.assert_outcomes` now accepts a
|
||||||
``deselected`` argument to assert the total number of deselected tests.
|
``deselected`` argument to assert the total number of deselected tests.
|
||||||
|
|
||||||
|
|
||||||
|
@ -1013,7 +1440,7 @@ Improvements
|
||||||
|
|
||||||
- `#7480 <https://github.com/pytest-dev/pytest/issues/7480>`_: A deprecation scheduled to be removed in a major version X (e.g. pytest 7, 8, 9, ...) now uses warning category `PytestRemovedInXWarning`,
|
- `#7480 <https://github.com/pytest-dev/pytest/issues/7480>`_: A deprecation scheduled to be removed in a major version X (e.g. pytest 7, 8, 9, ...) now uses warning category `PytestRemovedInXWarning`,
|
||||||
a subclass of :class:`~pytest.PytestDeprecationWarning`,
|
a subclass of :class:`~pytest.PytestDeprecationWarning`,
|
||||||
instead of :class:`PytestDeprecationWarning` directly.
|
instead of :class:`~pytest.PytestDeprecationWarning` directly.
|
||||||
|
|
||||||
See :ref:`backwards-compatibility` for more details.
|
See :ref:`backwards-compatibility` for more details.
|
||||||
|
|
||||||
|
@ -1052,7 +1479,7 @@ Improvements
|
||||||
|
|
||||||
- `#8803 <https://github.com/pytest-dev/pytest/issues/8803>`_: It is now possible to add colors to custom log levels on cli log.
|
- `#8803 <https://github.com/pytest-dev/pytest/issues/8803>`_: It is now possible to add colors to custom log levels on cli log.
|
||||||
|
|
||||||
By using :func:`add_color_level <_pytest.logging.add_color_level>` from a ``pytest_configure`` hook, colors can be added::
|
By using ``add_color_level`` from a :hook:`pytest_configure` hook, colors can be added::
|
||||||
|
|
||||||
logging_plugin = config.pluginmanager.get_plugin('logging-plugin')
|
logging_plugin = config.pluginmanager.get_plugin('logging-plugin')
|
||||||
logging_plugin.log_cli_handler.formatter.add_color_level(logging.INFO, 'cyan')
|
logging_plugin.log_cli_handler.formatter.add_color_level(logging.INFO, 'cyan')
|
||||||
|
@ -1117,7 +1544,7 @@ Bug Fixes
|
||||||
|
|
||||||
- `#8503 <https://github.com/pytest-dev/pytest/issues/8503>`_: :meth:`pytest.MonkeyPatch.syspath_prepend` no longer fails when
|
- `#8503 <https://github.com/pytest-dev/pytest/issues/8503>`_: :meth:`pytest.MonkeyPatch.syspath_prepend` no longer fails when
|
||||||
``setuptools`` is not installed.
|
``setuptools`` is not installed.
|
||||||
It now only calls :func:`pkg_resources.fixup_namespace_packages` if
|
It now only calls ``pkg_resources.fixup_namespace_packages`` if
|
||||||
``pkg_resources`` was previously imported, because it is not needed otherwise.
|
``pkg_resources`` was previously imported, because it is not needed otherwise.
|
||||||
|
|
||||||
|
|
||||||
|
@ -1344,7 +1771,7 @@ Features
|
||||||
|
|
||||||
This is part of the movement to use :class:`pathlib.Path` objects internally, in order to remove the dependency to ``py`` in the future.
|
This is part of the movement to use :class:`pathlib.Path` objects internally, in order to remove the dependency to ``py`` in the future.
|
||||||
|
|
||||||
Internally, the old :class:`Testdir <_pytest.pytester.Testdir>` is now a thin wrapper around :class:`Pytester <_pytest.pytester.Pytester>`, preserving the old interface.
|
Internally, the old ``pytest.Testdir`` is now a thin wrapper around :class:`~pytest.Pytester`, preserving the old interface.
|
||||||
|
|
||||||
|
|
||||||
- :issue:`7695`: A new hook was added, `pytest_markeval_namespace` which should return a dictionary.
|
- :issue:`7695`: A new hook was added, `pytest_markeval_namespace` which should return a dictionary.
|
||||||
|
@ -1382,7 +1809,7 @@ Features
|
||||||
Improvements
|
Improvements
|
||||||
------------
|
------------
|
||||||
|
|
||||||
- :issue:`1265`: Added an ``__str__`` implementation to the :class:`~pytest.pytester.LineMatcher` class which is returned from ``pytester.run_pytest().stdout`` and similar. It returns the entire output, like the existing ``str()`` method.
|
- :issue:`1265`: Added an ``__str__`` implementation to the :class:`~pytest.LineMatcher` class which is returned from ``pytester.run_pytest().stdout`` and similar. It returns the entire output, like the existing ``str()`` method.
|
||||||
|
|
||||||
|
|
||||||
- :issue:`2044`: Verbose mode now shows the reason that a test was skipped in the test's terminal line after the "SKIPPED", "XFAIL" or "XPASS".
|
- :issue:`2044`: Verbose mode now shows the reason that a test was skipped in the test's terminal line after the "SKIPPED", "XFAIL" or "XPASS".
|
||||||
|
@ -1446,7 +1873,7 @@ Bug Fixes
|
||||||
- :issue:`7911`: Directories created by by :fixture:`tmp_path` and :fixture:`tmpdir` are now considered stale after 3 days without modification (previous value was 3 hours) to avoid deleting directories still in use in long running test suites.
|
- :issue:`7911`: Directories created by by :fixture:`tmp_path` and :fixture:`tmpdir` are now considered stale after 3 days without modification (previous value was 3 hours) to avoid deleting directories still in use in long running test suites.
|
||||||
|
|
||||||
|
|
||||||
- :issue:`7913`: Fixed a crash or hang in :meth:`pytester.spawn <_pytest.pytester.Pytester.spawn>` when the :mod:`readline` module is involved.
|
- :issue:`7913`: Fixed a crash or hang in :meth:`pytester.spawn <pytest.Pytester.spawn>` when the :mod:`readline` module is involved.
|
||||||
|
|
||||||
|
|
||||||
- :issue:`7951`: Fixed handling of recursive symlinks when collecting tests.
|
- :issue:`7951`: Fixed handling of recursive symlinks when collecting tests.
|
||||||
|
@ -1563,7 +1990,7 @@ Deprecations
|
||||||
if you use this and want a replacement.
|
if you use this and want a replacement.
|
||||||
|
|
||||||
|
|
||||||
- :issue:`7255`: The :hook:`pytest_warning_captured` hook is deprecated in favor
|
- :issue:`7255`: The ``pytest_warning_captured`` hook is deprecated in favor
|
||||||
of :hook:`pytest_warning_recorded`, and will be removed in a future version.
|
of :hook:`pytest_warning_recorded`, and will be removed in a future version.
|
||||||
|
|
||||||
|
|
||||||
|
@ -1591,8 +2018,8 @@ Improvements
|
||||||
- :issue:`7572`: When a plugin listed in ``required_plugins`` is missing or an unknown config key is used with ``--strict-config``, a simple error message is now shown instead of a stacktrace.
|
- :issue:`7572`: When a plugin listed in ``required_plugins`` is missing or an unknown config key is used with ``--strict-config``, a simple error message is now shown instead of a stacktrace.
|
||||||
|
|
||||||
|
|
||||||
- :issue:`7685`: Added two new attributes :attr:`rootpath <_pytest.config.Config.rootpath>` and :attr:`inipath <_pytest.config.Config.inipath>` to :class:`Config <_pytest.config.Config>`.
|
- :issue:`7685`: Added two new attributes :attr:`rootpath <pytest.Config.rootpath>` and :attr:`inipath <pytest.Config.inipath>` to :class:`~pytest.Config`.
|
||||||
These attributes are :class:`pathlib.Path` versions of the existing :attr:`rootdir <_pytest.config.Config.rootdir>` and :attr:`inifile <_pytest.config.Config.inifile>` attributes,
|
These attributes are :class:`pathlib.Path` versions of the existing ``rootdir`` and ``inifile`` attributes,
|
||||||
and should be preferred over them when possible.
|
and should be preferred over them when possible.
|
||||||
|
|
||||||
|
|
||||||
|
@ -1663,7 +2090,7 @@ Trivial/Internal Changes
|
||||||
- :issue:`7587`: The dependency on the ``more-itertools`` package has been removed.
|
- :issue:`7587`: The dependency on the ``more-itertools`` package has been removed.
|
||||||
|
|
||||||
|
|
||||||
- :issue:`7631`: The result type of :meth:`capfd.readouterr() <_pytest.capture.CaptureFixture.readouterr>` (and similar) is no longer a namedtuple,
|
- :issue:`7631`: The result type of :meth:`capfd.readouterr() <pytest.CaptureFixture.readouterr>` (and similar) is no longer a namedtuple,
|
||||||
but should behave like one in all respects. This was done for technical reasons.
|
but should behave like one in all respects. This was done for technical reasons.
|
||||||
|
|
||||||
|
|
||||||
|
@ -2041,10 +2468,10 @@ Improvements
|
||||||
- :issue:`7128`: `pytest --version` now displays just the pytest version, while `pytest --version --version` displays more verbose information including plugins. This is more consistent with how other tools show `--version`.
|
- :issue:`7128`: `pytest --version` now displays just the pytest version, while `pytest --version --version` displays more verbose information including plugins. This is more consistent with how other tools show `--version`.
|
||||||
|
|
||||||
|
|
||||||
- :issue:`7133`: :meth:`caplog.set_level() <_pytest.logging.LogCaptureFixture.set_level>` will now override any :confval:`log_level` set via the CLI or configuration file.
|
- :issue:`7133`: :meth:`caplog.set_level() <pytest.LogCaptureFixture.set_level>` will now override any :confval:`log_level` set via the CLI or configuration file.
|
||||||
|
|
||||||
|
|
||||||
- :issue:`7159`: :meth:`caplog.set_level() <_pytest.logging.LogCaptureFixture.set_level>` and :meth:`caplog.at_level() <_pytest.logging.LogCaptureFixture.at_level>` no longer affect
|
- :issue:`7159`: :meth:`caplog.set_level() <pytest.LogCaptureFixture.set_level>` and :meth:`caplog.at_level() <pytest.LogCaptureFixture.at_level>` no longer affect
|
||||||
the level of logs that are shown in the *Captured log report* report section.
|
the level of logs that are shown in the *Captured log report* report section.
|
||||||
|
|
||||||
|
|
||||||
|
@ -2139,7 +2566,7 @@ Bug Fixes
|
||||||
parameter when Python is called with the ``-bb`` flag.
|
parameter when Python is called with the ``-bb`` flag.
|
||||||
|
|
||||||
|
|
||||||
- :issue:`7143`: Fix :meth:`pytest.File.from_parent` so it forwards extra keyword arguments to the constructor.
|
- :issue:`7143`: Fix :meth:`pytest.File.from_parent <_pytest.nodes.Node.from_parent>` so it forwards extra keyword arguments to the constructor.
|
||||||
|
|
||||||
|
|
||||||
- :issue:`7145`: Classes with broken ``__getattribute__`` methods are displayed correctly during failures.
|
- :issue:`7145`: Classes with broken ``__getattribute__`` methods are displayed correctly during failures.
|
||||||
|
@ -2390,7 +2817,7 @@ Improvements
|
||||||
- :issue:`6384`: Make `--showlocals` work also with `--tb=short`.
|
- :issue:`6384`: Make `--showlocals` work also with `--tb=short`.
|
||||||
|
|
||||||
|
|
||||||
- :issue:`6653`: Add support for matching lines consecutively with :attr:`LineMatcher <_pytest.pytester.LineMatcher>`'s :func:`~_pytest.pytester.LineMatcher.fnmatch_lines` and :func:`~_pytest.pytester.LineMatcher.re_match_lines`.
|
- :issue:`6653`: Add support for matching lines consecutively with :class:`~pytest.LineMatcher`'s :func:`~pytest.LineMatcher.fnmatch_lines` and :func:`~pytest.LineMatcher.re_match_lines`.
|
||||||
|
|
||||||
|
|
||||||
- :issue:`6658`: Code is now highlighted in tracebacks when ``pygments`` is installed.
|
- :issue:`6658`: Code is now highlighted in tracebacks when ``pygments`` is installed.
|
||||||
|
@ -2458,7 +2885,7 @@ Bug Fixes
|
||||||
- :issue:`6597`: Fix node ids which contain a parametrized empty-string variable.
|
- :issue:`6597`: Fix node ids which contain a parametrized empty-string variable.
|
||||||
|
|
||||||
|
|
||||||
- :issue:`6646`: Assertion rewriting hooks are (re)stored for the current item, which fixes them being still used after e.g. pytester's :func:`testdir.runpytest <_pytest.pytester.Testdir.runpytest>` etc.
|
- :issue:`6646`: Assertion rewriting hooks are (re)stored for the current item, which fixes them being still used after e.g. pytester's ``testdir.runpytest`` etc.
|
||||||
|
|
||||||
|
|
||||||
- :issue:`6660`: :py:func:`pytest.exit` is handled when emitted from the :hook:`pytest_sessionfinish` hook. This includes quitting from a debugger.
|
- :issue:`6660`: :py:func:`pytest.exit` is handled when emitted from the :hook:`pytest_sessionfinish` hook. This includes quitting from a debugger.
|
||||||
|
@ -2524,7 +2951,7 @@ Bug Fixes
|
||||||
``multiprocessing`` module.
|
``multiprocessing`` module.
|
||||||
|
|
||||||
|
|
||||||
- :issue:`6436`: :class:`FixtureDef <_pytest.fixtures.FixtureDef>` objects now properly register their finalizers with autouse and
|
- :issue:`6436`: :class:`~pytest.FixtureDef` objects now properly register their finalizers with autouse and
|
||||||
parameterized fixtures that execute before them in the fixture stack so they are torn
|
parameterized fixtures that execute before them in the fixture stack so they are torn
|
||||||
down at the right times, and in the right order.
|
down at the right times, and in the right order.
|
||||||
|
|
||||||
|
@ -2580,7 +3007,7 @@ Improvements
|
||||||
Bug Fixes
|
Bug Fixes
|
||||||
---------
|
---------
|
||||||
|
|
||||||
- :issue:`5914`: pytester: fix :py:func:`~_pytest.pytester.LineMatcher.no_fnmatch_line` when used after positive matching.
|
- :issue:`5914`: pytester: fix :py:func:`~pytest.LineMatcher.no_fnmatch_line` when used after positive matching.
|
||||||
|
|
||||||
|
|
||||||
- :issue:`6082`: Fix line detection for doctest samples inside :py:class:`python:property` docstrings, as a workaround to :bpo:`17446`.
|
- :issue:`6082`: Fix line detection for doctest samples inside :py:class:`python:property` docstrings, as a workaround to :bpo:`17446`.
|
||||||
|
@ -2644,8 +3071,8 @@ Features
|
||||||
rather than implicitly.
|
rather than implicitly.
|
||||||
|
|
||||||
|
|
||||||
- :issue:`5914`: :fixture:`testdir` learned two new functions, :py:func:`~_pytest.pytester.LineMatcher.no_fnmatch_line` and
|
- :issue:`5914`: :fixture:`testdir` learned two new functions, :py:func:`~pytest.LineMatcher.no_fnmatch_line` and
|
||||||
:py:func:`~_pytest.pytester.LineMatcher.no_re_match_line`.
|
:py:func:`~pytest.LineMatcher.no_re_match_line`.
|
||||||
|
|
||||||
The functions are used to ensure the captured text *does not* match the given
|
The functions are used to ensure the captured text *does not* match the given
|
||||||
pattern.
|
pattern.
|
||||||
|
@ -6497,7 +6924,7 @@ Changes
|
||||||
* fix :issue:`2013`: turn RecordedWarning into ``namedtuple``,
|
* fix :issue:`2013`: turn RecordedWarning into ``namedtuple``,
|
||||||
to give it a comprehensible repr while preventing unwarranted modification.
|
to give it a comprehensible repr while preventing unwarranted modification.
|
||||||
|
|
||||||
* fix :issue:`2208`: ensure an iteration limit for _pytest.compat.get_real_func.
|
* fix :issue:`2208`: ensure an iteration limit for ``_pytest.compat.get_real_func``.
|
||||||
Thanks :user:`RonnyPfannschmidt` for the report and PR.
|
Thanks :user:`RonnyPfannschmidt` for the report and PR.
|
||||||
|
|
||||||
* Hooks are now verified after collection is complete, rather than right after loading installed plugins. This
|
* Hooks are now verified after collection is complete, rather than right after loading installed plugins. This
|
||||||
|
|
|
@ -169,6 +169,49 @@ extlinks = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
nitpicky = True
|
||||||
|
nitpick_ignore = [
|
||||||
|
# TODO (fix in pluggy?)
|
||||||
|
("py:class", "HookCaller"),
|
||||||
|
("py:class", "HookspecMarker"),
|
||||||
|
("py:exc", "PluginValidationError"),
|
||||||
|
# Might want to expose/TODO (https://github.com/pytest-dev/pytest/issues/7469)
|
||||||
|
("py:class", "ExceptionRepr"),
|
||||||
|
("py:class", "Exit"),
|
||||||
|
("py:class", "SubRequest"),
|
||||||
|
("py:class", "SubRequest"),
|
||||||
|
("py:class", "TerminalReporter"),
|
||||||
|
("py:class", "_pytest._code.code.TerminalRepr"),
|
||||||
|
("py:class", "_pytest.fixtures.FixtureFunctionMarker"),
|
||||||
|
("py:class", "_pytest.logging.LogCaptureHandler"),
|
||||||
|
("py:class", "_pytest.mark.structures.ParameterSet"),
|
||||||
|
# Intentionally undocumented/private
|
||||||
|
("py:class", "_pytest._code.code.Traceback"),
|
||||||
|
("py:class", "_pytest._py.path.LocalPath"),
|
||||||
|
("py:class", "_pytest.capture.CaptureResult"),
|
||||||
|
("py:class", "_pytest.compat.NotSetType"),
|
||||||
|
("py:class", "_pytest.python.PyCollector"),
|
||||||
|
("py:class", "_pytest.python.PyobjMixin"),
|
||||||
|
("py:class", "_pytest.python_api.RaisesContext"),
|
||||||
|
("py:class", "_pytest.recwarn.WarningsChecker"),
|
||||||
|
("py:class", "_pytest.reports.BaseReport"),
|
||||||
|
# Undocumented third parties
|
||||||
|
("py:class", "_tracing.TagTracerSub"),
|
||||||
|
("py:class", "warnings.WarningMessage"),
|
||||||
|
# Undocumented type aliases
|
||||||
|
("py:class", "_PluggyPlugin"),
|
||||||
|
# TypeVars
|
||||||
|
("py:class", "_pytest._code.code.E"),
|
||||||
|
("py:class", "_pytest.fixtures.FixtureFunction"),
|
||||||
|
("py:class", "_pytest.nodes._NodeType"),
|
||||||
|
("py:class", "_pytest.python_api.E"),
|
||||||
|
("py:class", "_pytest.recwarn.T"),
|
||||||
|
("py:class", "_pytest.runner.TResult"),
|
||||||
|
("py:obj", "_pytest.fixtures.FixtureValue"),
|
||||||
|
("py:obj", "_pytest.stash.T"),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTML output ---------------------------------------------------
|
# -- Options for HTML output ---------------------------------------------------
|
||||||
|
|
||||||
sys.path.append(os.path.abspath("_themes"))
|
sys.path.append(os.path.abspath("_themes"))
|
||||||
|
|
|
@ -44,7 +44,6 @@ How-to guides
|
||||||
|
|
||||||
how-to/existingtestsuite
|
how-to/existingtestsuite
|
||||||
how-to/unittest
|
how-to/unittest
|
||||||
how-to/nose
|
|
||||||
how-to/xunit_setup
|
how-to/xunit_setup
|
||||||
|
|
||||||
how-to/bash-completion
|
how-to/bash-completion
|
||||||
|
|
|
@ -19,12 +19,273 @@ Below is a complete list of all pytest features which are considered deprecated.
|
||||||
:class:`~pytest.PytestWarning` or subclasses, which can be filtered using :ref:`standard warning filters <warnings>`.
|
:class:`~pytest.PytestWarning` or subclasses, which can be filtered using :ref:`standard warning filters <warnings>`.
|
||||||
|
|
||||||
|
|
||||||
|
.. _legacy-path-hooks-deprecated:
|
||||||
|
|
||||||
|
Configuring hook specs/impls using markers
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Before pluggy, pytest's plugin library, was its own package and had a clear API,
|
||||||
|
pytest just used ``pytest.mark`` to configure hooks.
|
||||||
|
|
||||||
|
The :py:func:`pytest.hookimpl` and :py:func:`pytest.hookspec` decorators
|
||||||
|
have been available since years and should be used instead.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
@pytest.mark.tryfirst
|
||||||
|
def pytest_runtest_call():
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
# or
|
||||||
|
def pytest_runtest_call():
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
pytest_runtest_call.tryfirst = True
|
||||||
|
|
||||||
|
should be changed to:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
@pytest.hookimpl(tryfirst=True)
|
||||||
|
def pytest_runtest_call():
|
||||||
|
...
|
||||||
|
|
||||||
|
Changed ``hookimpl`` attributes:
|
||||||
|
|
||||||
|
* ``tryfirst``
|
||||||
|
* ``trylast``
|
||||||
|
* ``optionalhook``
|
||||||
|
* ``hookwrapper``
|
||||||
|
|
||||||
|
Changed ``hookwrapper`` attributes:
|
||||||
|
|
||||||
|
* ``firstresult``
|
||||||
|
* ``historic``
|
||||||
|
|
||||||
|
|
||||||
|
Directly constructing internal classes
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 7.0
|
||||||
|
|
||||||
|
Directly constructing the following classes is now deprecated:
|
||||||
|
|
||||||
|
- ``_pytest.mark.structures.Mark``
|
||||||
|
- ``_pytest.mark.structures.MarkDecorator``
|
||||||
|
- ``_pytest.mark.structures.MarkGenerator``
|
||||||
|
- ``_pytest.python.Metafunc``
|
||||||
|
- ``_pytest.runner.CallInfo``
|
||||||
|
- ``_pytest._code.ExceptionInfo``
|
||||||
|
- ``_pytest.config.argparsing.Parser``
|
||||||
|
- ``_pytest.config.argparsing.OptionGroup``
|
||||||
|
- ``_pytest.pytester.HookRecorder``
|
||||||
|
|
||||||
|
These constructors have always been considered private, but now issue a deprecation warning, which may become a hard error in pytest 8.
|
||||||
|
|
||||||
|
.. _diamond-inheritance-deprecated:
|
||||||
|
|
||||||
|
Diamond inheritance between :class:`pytest.Collector` and :class:`pytest.Item`
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 7.0
|
||||||
|
|
||||||
|
Defining a custom pytest node type which is both an :class:`~pytest.Item` and a :class:`~pytest.Collector` (e.g. :class:`~pytest.File`) now issues a warning.
|
||||||
|
It was never sanely supported and triggers hard to debug errors.
|
||||||
|
|
||||||
|
Some plugins providing linting/code analysis have been using this as a hack.
|
||||||
|
Instead, a separate collector node should be used, which collects the item. See
|
||||||
|
:ref:`non-python tests` for an example, as well as an `example pr fixing inheritance`_.
|
||||||
|
|
||||||
|
.. _example pr fixing inheritance: https://github.com/asmeurer/pytest-flakes/pull/40/files
|
||||||
|
|
||||||
|
|
||||||
|
.. _uncooperative-constructors-deprecated:
|
||||||
|
|
||||||
|
Constructors of custom :class:`~_pytest.nodes.Node` subclasses should take ``**kwargs``
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 7.0
|
||||||
|
|
||||||
|
If custom subclasses of nodes like :class:`pytest.Item` override the
|
||||||
|
``__init__`` method, they should take ``**kwargs``. Thus,
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
class CustomItem(pytest.Item):
|
||||||
|
def __init__(self, name, parent, additional_arg):
|
||||||
|
super().__init__(name, parent)
|
||||||
|
self.additional_arg = additional_arg
|
||||||
|
|
||||||
|
should be turned into:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
class CustomItem(pytest.Item):
|
||||||
|
def __init__(self, *, additional_arg, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self.additional_arg = additional_arg
|
||||||
|
|
||||||
|
to avoid hard-coding the arguments pytest can pass to the superclass.
|
||||||
|
See :ref:`non-python tests` for a full example.
|
||||||
|
|
||||||
|
For cases without conflicts, no deprecation warning is emitted. For cases with
|
||||||
|
conflicts (such as :class:`pytest.File` now taking ``path`` instead of
|
||||||
|
``fspath``, as :ref:`outlined above <node-ctor-fspath-deprecation>`), a
|
||||||
|
deprecation warning is now raised.
|
||||||
|
|
||||||
|
Applying a mark to a fixture function
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 7.4
|
||||||
|
|
||||||
|
Applying a mark to a fixture function never had any effect, but it is a common user error.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("clean_database")
|
||||||
|
@pytest.fixture
|
||||||
|
def user() -> User:
|
||||||
|
...
|
||||||
|
|
||||||
|
Users expected in this case that the ``usefixtures`` mark would have its intended effect of using the ``clean_database`` fixture when ``user`` was invoked, when in fact it has no effect at all.
|
||||||
|
|
||||||
|
Now pytest will issue a warning when it encounters this problem, and will raise an error in the future versions.
|
||||||
|
|
||||||
|
|
||||||
|
Returning non-None value in test functions
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 7.2
|
||||||
|
|
||||||
|
A :class:`pytest.PytestReturnNotNoneWarning` is now emitted if a test function returns something other than `None`.
|
||||||
|
|
||||||
|
This prevents a common mistake among beginners that expect that returning a `bool` would cause a test to pass or fail, for example:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
["a", "b", "result"],
|
||||||
|
[
|
||||||
|
[1, 2, 5],
|
||||||
|
[2, 3, 8],
|
||||||
|
[5, 3, 18],
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_foo(a, b, result):
|
||||||
|
return foo(a, b) == result
|
||||||
|
|
||||||
|
Given that pytest ignores the return value, this might be surprising that it will never fail.
|
||||||
|
|
||||||
|
The proper fix is to change the `return` to an `assert`:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
["a", "b", "result"],
|
||||||
|
[
|
||||||
|
[1, 2, 5],
|
||||||
|
[2, 3, 8],
|
||||||
|
[5, 3, 18],
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_foo(a, b, result):
|
||||||
|
assert foo(a, b) == result
|
||||||
|
|
||||||
|
|
||||||
|
The ``yield_fixture`` function/decorator
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 6.2
|
||||||
|
|
||||||
|
``pytest.yield_fixture`` is a deprecated alias for :func:`pytest.fixture`.
|
||||||
|
|
||||||
|
It has been so for a very long time, so can be search/replaced safely.
|
||||||
|
|
||||||
|
|
||||||
|
Removed Features and Breaking Changes
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
As stated in our :ref:`backwards-compatibility` policy, deprecated features are removed only in major releases after
|
||||||
|
an appropriate period of deprecation has passed.
|
||||||
|
|
||||||
|
Some breaking changes which could not be deprecated are also listed.
|
||||||
|
|
||||||
|
.. _node-ctor-fspath-deprecation:
|
||||||
|
|
||||||
|
``fspath`` argument for Node constructors replaced with ``pathlib.Path``
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 7.0
|
||||||
|
|
||||||
|
In order to support the transition from ``py.path.local`` to :mod:`pathlib`,
|
||||||
|
the ``fspath`` argument to :class:`~_pytest.nodes.Node` constructors like
|
||||||
|
:func:`pytest.Function.from_parent()` and :func:`pytest.Class.from_parent()`
|
||||||
|
is now deprecated.
|
||||||
|
|
||||||
|
Plugins which construct nodes should pass the ``path`` argument, of type
|
||||||
|
:class:`pathlib.Path`, instead of the ``fspath`` argument.
|
||||||
|
|
||||||
|
Plugins which implement custom items and collectors are encouraged to replace
|
||||||
|
``fspath`` parameters (``py.path.local``) with ``path`` parameters
|
||||||
|
(``pathlib.Path``), and drop any other usage of the ``py`` library if possible.
|
||||||
|
|
||||||
|
If possible, plugins with custom items should use :ref:`cooperative
|
||||||
|
constructors <uncooperative-constructors-deprecated>` to avoid hardcoding
|
||||||
|
arguments they only pass on to the superclass.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
The name of the :class:`~_pytest.nodes.Node` arguments and attributes (the
|
||||||
|
new attribute being ``path``) is **the opposite** of the situation for
|
||||||
|
hooks, :ref:`outlined below <legacy-path-hooks-deprecated>` (the old
|
||||||
|
argument being ``path``).
|
||||||
|
|
||||||
|
This is an unfortunate artifact due to historical reasons, which should be
|
||||||
|
resolved in future versions as we slowly get rid of the :pypi:`py`
|
||||||
|
dependency (see :issue:`9283` for a longer discussion).
|
||||||
|
|
||||||
|
Due to the ongoing migration of methods like :meth:`~pytest.Item.reportinfo`
|
||||||
|
which still is expected to return a ``py.path.local`` object, nodes still have
|
||||||
|
both ``fspath`` (``py.path.local``) and ``path`` (``pathlib.Path``) attributes,
|
||||||
|
no matter what argument was used in the constructor. We expect to deprecate the
|
||||||
|
``fspath`` attribute in a future release.
|
||||||
|
|
||||||
|
|
||||||
|
``py.path.local`` arguments for hooks replaced with ``pathlib.Path``
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 7.0
|
||||||
|
.. versionremoved:: 8.0
|
||||||
|
|
||||||
|
In order to support the transition from ``py.path.local`` to :mod:`pathlib`, the following hooks now receive additional arguments:
|
||||||
|
|
||||||
|
* :hook:`pytest_ignore_collect(collection_path: pathlib.Path) <pytest_ignore_collect>` as equivalent to ``path``
|
||||||
|
* :hook:`pytest_collect_file(file_path: pathlib.Path) <pytest_collect_file>` as equivalent to ``path``
|
||||||
|
* :hook:`pytest_pycollect_makemodule(module_path: pathlib.Path) <pytest_pycollect_makemodule>` as equivalent to ``path``
|
||||||
|
* :hook:`pytest_report_header(start_path: pathlib.Path) <pytest_report_header>` as equivalent to ``startdir``
|
||||||
|
* :hook:`pytest_report_collectionfinish(start_path: pathlib.Path) <pytest_report_collectionfinish>` as equivalent to ``startdir``
|
||||||
|
|
||||||
|
The accompanying ``py.path.local`` based paths have been deprecated: plugins which manually invoke those hooks should only pass the new ``pathlib.Path`` arguments, and users should change their hook implementations to use the new ``pathlib.Path`` arguments.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
The name of the :class:`~_pytest.nodes.Node` arguments and attributes,
|
||||||
|
:ref:`outlined above <node-ctor-fspath-deprecation>` (the new attribute
|
||||||
|
being ``path``) is **the opposite** of the situation for hooks (the old
|
||||||
|
argument being ``path``).
|
||||||
|
|
||||||
|
This is an unfortunate artifact due to historical reasons, which should be
|
||||||
|
resolved in future versions as we slowly get rid of the :pypi:`py`
|
||||||
|
dependency (see :issue:`9283` for a longer discussion).
|
||||||
|
|
||||||
|
|
||||||
.. _nose-deprecation:
|
.. _nose-deprecation:
|
||||||
|
|
||||||
Support for tests written for nose
|
Support for tests written for nose
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. deprecated:: 7.2
|
.. deprecated:: 7.2
|
||||||
|
.. versionremoved:: 8.0
|
||||||
|
|
||||||
Support for running tests written for `nose <https://nose.readthedocs.io/en/latest/>`__ is now deprecated.
|
Support for running tests written for `nose <https://nose.readthedocs.io/en/latest/>`__ is now deprecated.
|
||||||
|
|
||||||
|
@ -125,160 +386,20 @@ Will also need to be ported to a supported pytest style. One way to do it is usi
|
||||||
|
|
||||||
.. _`with-setup-nose`: https://nose.readthedocs.io/en/latest/testing_tools.html?highlight=with_setup#nose.tools.with_setup
|
.. _`with-setup-nose`: https://nose.readthedocs.io/en/latest/testing_tools.html?highlight=with_setup#nose.tools.with_setup
|
||||||
|
|
||||||
.. _instance-collector-deprecation:
|
|
||||||
|
|
||||||
The ``pytest.Instance`` collector
|
The ``compat_co_firstlineno`` attribute
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
.. versionremoved:: 7.0
|
Nose inspects this attribute on function objects to allow overriding the function's inferred line number.
|
||||||
|
Pytest no longer respects this attribute.
|
||||||
The ``pytest.Instance`` collector type has been removed.
|
|
||||||
|
|
||||||
Previously, Python test methods were collected as :class:`~pytest.Class` -> ``Instance`` -> :class:`~pytest.Function`.
|
|
||||||
Now :class:`~pytest.Class` collects the test methods directly.
|
|
||||||
|
|
||||||
Most plugins which reference ``Instance`` do so in order to ignore or skip it,
|
|
||||||
using a check such as ``if isinstance(node, Instance): return``.
|
|
||||||
Such plugins should simply remove consideration of ``Instance`` on pytest>=7.
|
|
||||||
However, to keep such uses working, a dummy type has been instanted in ``pytest.Instance`` and ``_pytest.python.Instance``,
|
|
||||||
and importing it emits a deprecation warning. This will be removed in pytest 8.
|
|
||||||
|
|
||||||
|
|
||||||
.. _node-ctor-fspath-deprecation:
|
|
||||||
|
|
||||||
``fspath`` argument for Node constructors replaced with ``pathlib.Path``
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. deprecated:: 7.0
|
|
||||||
|
|
||||||
In order to support the transition from ``py.path.local`` to :mod:`pathlib`,
|
|
||||||
the ``fspath`` argument to :class:`~_pytest.nodes.Node` constructors like
|
|
||||||
:func:`pytest.Function.from_parent()` and :func:`pytest.Class.from_parent()`
|
|
||||||
is now deprecated.
|
|
||||||
|
|
||||||
Plugins which construct nodes should pass the ``path`` argument, of type
|
|
||||||
:class:`pathlib.Path`, instead of the ``fspath`` argument.
|
|
||||||
|
|
||||||
Plugins which implement custom items and collectors are encouraged to replace
|
|
||||||
``fspath`` parameters (``py.path.local``) with ``path`` parameters
|
|
||||||
(``pathlib.Path``), and drop any other usage of the ``py`` library if possible.
|
|
||||||
|
|
||||||
If possible, plugins with custom items should use :ref:`cooperative
|
|
||||||
constructors <uncooperative-constructors-deprecated>` to avoid hardcoding
|
|
||||||
arguments they only pass on to the superclass.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
The name of the :class:`~_pytest.nodes.Node` arguments and attributes (the
|
|
||||||
new attribute being ``path``) is **the opposite** of the situation for
|
|
||||||
hooks, :ref:`outlined below <legacy-path-hooks-deprecated>` (the old
|
|
||||||
argument being ``path``).
|
|
||||||
|
|
||||||
This is an unfortunate artifact due to historical reasons, which should be
|
|
||||||
resolved in future versions as we slowly get rid of the :pypi:`py`
|
|
||||||
dependency (see :issue:`9283` for a longer discussion).
|
|
||||||
|
|
||||||
Due to the ongoing migration of methods like :meth:`~_pytest.Item.reportinfo`
|
|
||||||
which still is expected to return a ``py.path.local`` object, nodes still have
|
|
||||||
both ``fspath`` (``py.path.local``) and ``path`` (``pathlib.Path``) attributes,
|
|
||||||
no matter what argument was used in the constructor. We expect to deprecate the
|
|
||||||
``fspath`` attribute in a future release.
|
|
||||||
|
|
||||||
.. _legacy-path-hooks-deprecated:
|
|
||||||
|
|
||||||
Configuring hook specs/impls using markers
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Before pluggy, pytest's plugin library, was its own package and had a clear API,
|
|
||||||
pytest just used ``pytest.mark`` to configure hooks.
|
|
||||||
|
|
||||||
The :py:func:`pytest.hookimpl` and :py:func:`pytest.hookspec` decorators
|
|
||||||
have been available since years and should be used instead.
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
@pytest.mark.tryfirst
|
|
||||||
def pytest_runtest_call():
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
# or
|
|
||||||
def pytest_runtest_call():
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
pytest_runtest_call.tryfirst = True
|
|
||||||
|
|
||||||
should be changed to:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
@pytest.hookimpl(tryfirst=True)
|
|
||||||
def pytest_runtest_call():
|
|
||||||
...
|
|
||||||
|
|
||||||
Changed ``hookimpl`` attributes:
|
|
||||||
|
|
||||||
* ``tryfirst``
|
|
||||||
* ``trylast``
|
|
||||||
* ``optionalhook``
|
|
||||||
* ``hookwrapper``
|
|
||||||
|
|
||||||
Changed ``hookwrapper`` attributes:
|
|
||||||
|
|
||||||
* ``firstresult``
|
|
||||||
* ``historic``
|
|
||||||
|
|
||||||
|
|
||||||
``py.path.local`` arguments for hooks replaced with ``pathlib.Path``
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. deprecated:: 7.0
|
|
||||||
|
|
||||||
In order to support the transition from ``py.path.local`` to :mod:`pathlib`, the following hooks now receive additional arguments:
|
|
||||||
|
|
||||||
* :hook:`pytest_ignore_collect(collection_path: pathlib.Path) <pytest_ignore_collect>` as equivalent to ``path``
|
|
||||||
* :hook:`pytest_collect_file(file_path: pathlib.Path) <pytest_collect_file>` as equivalent to ``path``
|
|
||||||
* :hook:`pytest_pycollect_makemodule(module_path: pathlib.Path) <pytest_pycollect_makemodule>` as equivalent to ``path``
|
|
||||||
* :hook:`pytest_report_header(start_path: pathlib.Path) <pytest_report_header>` as equivalent to ``startdir``
|
|
||||||
* :hook:`pytest_report_collectionfinish(start_path: pathlib.Path) <pytest_report_collectionfinish>` as equivalent to ``startdir``
|
|
||||||
|
|
||||||
The accompanying ``py.path.local`` based paths have been deprecated: plugins which manually invoke those hooks should only pass the new ``pathlib.Path`` arguments, and users should change their hook implementations to use the new ``pathlib.Path`` arguments.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
The name of the :class:`~_pytest.nodes.Node` arguments and attributes,
|
|
||||||
:ref:`outlined above <node-ctor-fspath-deprecation>` (the new attribute
|
|
||||||
being ``path``) is **the opposite** of the situation for hooks (the old
|
|
||||||
argument being ``path``).
|
|
||||||
|
|
||||||
This is an unfortunate artifact due to historical reasons, which should be
|
|
||||||
resolved in future versions as we slowly get rid of the :pypi:`py`
|
|
||||||
dependency (see :issue:`9283` for a longer discussion).
|
|
||||||
|
|
||||||
Directly constructing internal classes
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. deprecated:: 7.0
|
|
||||||
|
|
||||||
Directly constructing the following classes is now deprecated:
|
|
||||||
|
|
||||||
- ``_pytest.mark.structures.Mark``
|
|
||||||
- ``_pytest.mark.structures.MarkDecorator``
|
|
||||||
- ``_pytest.mark.structures.MarkGenerator``
|
|
||||||
- ``_pytest.python.Metafunc``
|
|
||||||
- ``_pytest.runner.CallInfo``
|
|
||||||
- ``_pytest._code.ExceptionInfo``
|
|
||||||
- ``_pytest.config.argparsing.Parser``
|
|
||||||
- ``_pytest.config.argparsing.OptionGroup``
|
|
||||||
- ``_pytest.pytester.HookRecorder``
|
|
||||||
|
|
||||||
These constructors have always been considered private, but now issue a deprecation warning, which may become a hard error in pytest 8.
|
|
||||||
|
|
||||||
.. _cmdline-preparse-deprecated:
|
|
||||||
|
|
||||||
Passing ``msg=`` to ``pytest.skip``, ``pytest.fail`` or ``pytest.exit``
|
Passing ``msg=`` to ``pytest.skip``, ``pytest.fail`` or ``pytest.exit``
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. deprecated:: 7.0
|
.. deprecated:: 7.0
|
||||||
|
.. versionremoved:: 8.0
|
||||||
|
|
||||||
Passing the keyword argument ``msg`` to :func:`pytest.skip`, :func:`pytest.fail` or :func:`pytest.exit`
|
Passing the keyword argument ``msg`` to :func:`pytest.skip`, :func:`pytest.fail` or :func:`pytest.exit`
|
||||||
is now deprecated and ``reason`` should be used instead. This change is to bring consistency between these
|
is now deprecated and ``reason`` should be used instead. This change is to bring consistency between these
|
||||||
|
@ -307,12 +428,74 @@ functions and the ``@pytest.mark.skip`` and ``@pytest.mark.xfail`` markers which
|
||||||
pytest.exit(reason="bar")
|
pytest.exit(reason="bar")
|
||||||
|
|
||||||
|
|
||||||
|
.. _instance-collector-deprecation:
|
||||||
|
|
||||||
|
The ``pytest.Instance`` collector
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. versionremoved:: 7.0
|
||||||
|
|
||||||
|
The ``pytest.Instance`` collector type has been removed.
|
||||||
|
|
||||||
|
Previously, Python test methods were collected as :class:`~pytest.Class` -> ``Instance`` -> :class:`~pytest.Function`.
|
||||||
|
Now :class:`~pytest.Class` collects the test methods directly.
|
||||||
|
|
||||||
|
Most plugins which reference ``Instance`` do so in order to ignore or skip it,
|
||||||
|
using a check such as ``if isinstance(node, Instance): return``.
|
||||||
|
Such plugins should simply remove consideration of ``Instance`` on pytest>=7.
|
||||||
|
However, to keep such uses working, a dummy type has been instanted in ``pytest.Instance`` and ``_pytest.python.Instance``,
|
||||||
|
and importing it emits a deprecation warning. This was removed in pytest 8.
|
||||||
|
|
||||||
|
|
||||||
|
Using ``pytest.warns(None)``
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 7.0
|
||||||
|
.. versionremoved:: 8.0
|
||||||
|
|
||||||
|
:func:`pytest.warns(None) <pytest.warns>` is now deprecated because it was frequently misused.
|
||||||
|
Its correct usage was checking that the code emits at least one warning of any type - like ``pytest.warns()``
|
||||||
|
or ``pytest.warns(Warning)``.
|
||||||
|
|
||||||
|
See :ref:`warns use cases` for examples.
|
||||||
|
|
||||||
|
|
||||||
|
Backward compatibilities in ``Parser.addoption``
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 2.4
|
||||||
|
.. versionremoved:: 8.0
|
||||||
|
|
||||||
|
Several behaviors of :meth:`Parser.addoption <pytest.Parser.addoption>` are now
|
||||||
|
removed in pytest 8 (deprecated since pytest 2.4.0):
|
||||||
|
|
||||||
|
- ``parser.addoption(..., help=".. %default ..")`` - use ``%(default)s`` instead.
|
||||||
|
- ``parser.addoption(..., type="int/string/float/complex")`` - use ``type=int`` etc. instead.
|
||||||
|
|
||||||
|
|
||||||
|
The ``--strict`` command-line option
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 6.2
|
||||||
|
.. versionremoved:: 8.0
|
||||||
|
|
||||||
|
The ``--strict`` command-line option has been deprecated in favor of ``--strict-markers``, which
|
||||||
|
better conveys what the option does.
|
||||||
|
|
||||||
|
We have plans to maybe in the future to reintroduce ``--strict`` and make it an encompassing
|
||||||
|
flag for all strictness related options (``--strict-markers`` and ``--strict-config``
|
||||||
|
at the moment, more might be introduced in the future).
|
||||||
|
|
||||||
|
|
||||||
|
.. _cmdline-preparse-deprecated:
|
||||||
|
|
||||||
Implementing the ``pytest_cmdline_preparse`` hook
|
Implementing the ``pytest_cmdline_preparse`` hook
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. deprecated:: 7.0
|
.. deprecated:: 7.0
|
||||||
|
.. versionremoved:: 8.0
|
||||||
|
|
||||||
Implementing the :hook:`pytest_cmdline_preparse` hook has been officially deprecated.
|
Implementing the ``pytest_cmdline_preparse`` hook has been officially deprecated.
|
||||||
Implement the :hook:`pytest_load_initial_conftests` hook instead.
|
Implement the :hook:`pytest_load_initial_conftests` hook instead.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
@ -329,170 +512,90 @@ Implement the :hook:`pytest_load_initial_conftests` hook instead.
|
||||||
) -> None:
|
) -> None:
|
||||||
...
|
...
|
||||||
|
|
||||||
.. _diamond-inheritance-deprecated:
|
|
||||||
|
|
||||||
Diamond inheritance between :class:`pytest.Collector` and :class:`pytest.Item`
|
Collection changes in pytest 8
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. deprecated:: 7.0
|
Added a new :class:`pytest.Directory` base collection node, which all collector nodes for filesystem directories are expected to subclass.
|
||||||
|
This is analogous to the existing :class:`pytest.File` for file nodes.
|
||||||
|
|
||||||
Defining a custom pytest node type which is both an :class:`pytest.Item <Item>` and a :class:`pytest.Collector <Collector>` (e.g. :class:`pytest.File <File>`) now issues a warning.
|
Changed :class:`pytest.Package` to be a subclass of :class:`pytest.Directory`.
|
||||||
It was never sanely supported and triggers hard to debug errors.
|
A ``Package`` represents a filesystem directory which is a Python package,
|
||||||
|
i.e. contains an ``__init__.py`` file.
|
||||||
|
|
||||||
Some plugins providing linting/code analysis have been using this as a hack.
|
:class:`pytest.Package` now only collects files in its own directory; previously it collected recursively.
|
||||||
Instead, a separate collector node should be used, which collects the item. See
|
Sub-directories are collected as sub-collector nodes, thus creating a collection tree which mirrors the filesystem hierarchy.
|
||||||
:ref:`non-python tests` for an example, as well as an `example pr fixing inheritance`_.
|
|
||||||
|
|
||||||
.. _example pr fixing inheritance: https://github.com/asmeurer/pytest-flakes/pull/40/files
|
:attr:`session.name <pytest.Session.name>` is now ``""``; previously it was the rootdir directory name.
|
||||||
|
This matches :attr:`session.nodeid <_pytest.nodes.Node.nodeid>` which has always been `""`.
|
||||||
|
|
||||||
|
Added a new :class:`pytest.Dir` concrete collection node, a subclass of :class:`pytest.Directory`.
|
||||||
|
This node represents a filesystem directory, which is not a :class:`pytest.Package`,
|
||||||
|
i.e. does not contain an ``__init__.py`` file.
|
||||||
|
Similarly to ``Package``, it only collects the files in its own directory,
|
||||||
|
while collecting sub-directories as sub-collector nodes.
|
||||||
|
|
||||||
.. _uncooperative-constructors-deprecated:
|
Files and directories are now collected in alphabetical order jointly, unless changed by a plugin.
|
||||||
|
Previously, files were collected before directories.
|
||||||
|
|
||||||
Constructors of custom :class:`pytest.Node` subclasses should take ``**kwargs``
|
The collection tree now contains directories/packages up to the :ref:`rootdir <rootdir>`,
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
for initial arguments that are found within the rootdir.
|
||||||
|
For files outside the rootdir, only the immediate directory/package is collected --
|
||||||
|
note however that collecting from outside the rootdir is discouraged.
|
||||||
|
|
||||||
.. deprecated:: 7.0
|
As an example, given the following filesystem tree::
|
||||||
|
|
||||||
If custom subclasses of nodes like :class:`pytest.Item` override the
|
myroot/
|
||||||
``__init__`` method, they should take ``**kwargs``. Thus,
|
pytest.ini
|
||||||
|
top/
|
||||||
|
├── aaa
|
||||||
|
│ └── test_aaa.py
|
||||||
|
├── test_a.py
|
||||||
|
├── test_b
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ └── test_b.py
|
||||||
|
├── test_c.py
|
||||||
|
└── zzz
|
||||||
|
├── __init__.py
|
||||||
|
└── test_zzz.py
|
||||||
|
|
||||||
.. code-block:: python
|
the collection tree, as shown by `pytest --collect-only top/` but with the otherwise-hidden :class:`~pytest.Session` node added for clarity,
|
||||||
|
is now the following::
|
||||||
|
|
||||||
class CustomItem(pytest.Item):
|
<Session>
|
||||||
def __init__(self, name, parent, additional_arg):
|
<Dir myroot>
|
||||||
super().__init__(name, parent)
|
<Dir top>
|
||||||
self.additional_arg = additional_arg
|
<Dir aaa>
|
||||||
|
<Module test_aaa.py>
|
||||||
|
<Function test_it>
|
||||||
|
<Module test_a.py>
|
||||||
|
<Function test_it>
|
||||||
|
<Package test_b>
|
||||||
|
<Module test_b.py>
|
||||||
|
<Function test_it>
|
||||||
|
<Module test_c.py>
|
||||||
|
<Function test_it>
|
||||||
|
<Package zzz>
|
||||||
|
<Module test_zzz.py>
|
||||||
|
<Function test_it>
|
||||||
|
|
||||||
should be turned into:
|
Previously, it was::
|
||||||
|
|
||||||
.. code-block:: python
|
<Session>
|
||||||
|
<Module top/test_a.py>
|
||||||
|
<Function test_it>
|
||||||
|
<Module top/test_c.py>
|
||||||
|
<Function test_it>
|
||||||
|
<Module top/aaa/test_aaa.py>
|
||||||
|
<Function test_it>
|
||||||
|
<Package test_b>
|
||||||
|
<Module test_b.py>
|
||||||
|
<Function test_it>
|
||||||
|
<Package zzz>
|
||||||
|
<Module test_zzz.py>
|
||||||
|
<Function test_it>
|
||||||
|
|
||||||
class CustomItem(pytest.Item):
|
Code/plugins which rely on a specific shape of the collection tree might need to update.
|
||||||
def __init__(self, *, additional_arg, **kwargs):
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
self.additional_arg = additional_arg
|
|
||||||
|
|
||||||
to avoid hard-coding the arguments pytest can pass to the superclass.
|
|
||||||
See :ref:`non-python tests` for a full example.
|
|
||||||
|
|
||||||
For cases without conflicts, no deprecation warning is emitted. For cases with
|
|
||||||
conflicts (such as :class:`pytest.File` now taking ``path`` instead of
|
|
||||||
``fspath``, as :ref:`outlined above <node-ctor-fspath-deprecation>`), a
|
|
||||||
deprecation warning is now raised.
|
|
||||||
|
|
||||||
Applying a mark to a fixture function
|
|
||||||
-------------------------------------
|
|
||||||
|
|
||||||
.. deprecated:: 7.4
|
|
||||||
|
|
||||||
Applying a mark to a fixture function never had any effect, but it is a common user error.
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("clean_database")
|
|
||||||
@pytest.fixture
|
|
||||||
def user() -> User:
|
|
||||||
...
|
|
||||||
|
|
||||||
Users expected in this case that the ``usefixtures`` mark would have its intended effect of using the ``clean_database`` fixture when ``user`` was invoked, when in fact it has no effect at all.
|
|
||||||
|
|
||||||
Now pytest will issue a warning when it encounters this problem, and will raise an error in the future versions.
|
|
||||||
|
|
||||||
|
|
||||||
Backward compatibilities in ``Parser.addoption``
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. deprecated:: 2.4
|
|
||||||
|
|
||||||
Several behaviors of :meth:`Parser.addoption <pytest.Parser.addoption>` are now
|
|
||||||
scheduled for removal in pytest 8 (deprecated since pytest 2.4.0):
|
|
||||||
|
|
||||||
- ``parser.addoption(..., help=".. %default ..")`` - use ``%(default)s`` instead.
|
|
||||||
- ``parser.addoption(..., type="int/string/float/complex")`` - use ``type=int`` etc. instead.
|
|
||||||
|
|
||||||
|
|
||||||
Using ``pytest.warns(None)``
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. deprecated:: 7.0
|
|
||||||
|
|
||||||
:func:`pytest.warns(None) <pytest.warns>` is now deprecated because it was frequently misused.
|
|
||||||
Its correct usage was checking that the code emits at least one warning of any type - like ``pytest.warns()``
|
|
||||||
or ``pytest.warns(Warning)``.
|
|
||||||
|
|
||||||
See :ref:`warns use cases` for examples.
|
|
||||||
|
|
||||||
|
|
||||||
Returning non-None value in test functions
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. deprecated:: 7.2
|
|
||||||
|
|
||||||
A :class:`pytest.PytestReturnNotNoneWarning` is now emitted if a test function returns something other than `None`.
|
|
||||||
|
|
||||||
This prevents a common mistake among beginners that expect that returning a `bool` would cause a test to pass or fail, for example:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
["a", "b", "result"],
|
|
||||||
[
|
|
||||||
[1, 2, 5],
|
|
||||||
[2, 3, 8],
|
|
||||||
[5, 3, 18],
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_foo(a, b, result):
|
|
||||||
return foo(a, b) == result
|
|
||||||
|
|
||||||
Given that pytest ignores the return value, this might be surprising that it will never fail.
|
|
||||||
|
|
||||||
The proper fix is to change the `return` to an `assert`:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
["a", "b", "result"],
|
|
||||||
[
|
|
||||||
[1, 2, 5],
|
|
||||||
[2, 3, 8],
|
|
||||||
[5, 3, 18],
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_foo(a, b, result):
|
|
||||||
assert foo(a, b) == result
|
|
||||||
|
|
||||||
|
|
||||||
The ``--strict`` command-line option
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. deprecated:: 6.2
|
|
||||||
|
|
||||||
The ``--strict`` command-line option has been deprecated in favor of ``--strict-markers``, which
|
|
||||||
better conveys what the option does.
|
|
||||||
|
|
||||||
We have plans to maybe in the future to reintroduce ``--strict`` and make it an encompassing
|
|
||||||
flag for all strictness related options (``--strict-markers`` and ``--strict-config``
|
|
||||||
at the moment, more might be introduced in the future).
|
|
||||||
|
|
||||||
|
|
||||||
The ``yield_fixture`` function/decorator
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. deprecated:: 6.2
|
|
||||||
|
|
||||||
``pytest.yield_fixture`` is a deprecated alias for :func:`pytest.fixture`.
|
|
||||||
|
|
||||||
It has been so for a very long time, so can be search/replaced safely.
|
|
||||||
|
|
||||||
|
|
||||||
Removed Features and Breaking Changes
|
|
||||||
-------------------------------------
|
|
||||||
|
|
||||||
As stated in our :ref:`backwards-compatibility` policy, deprecated features are removed only in major releases after
|
|
||||||
an appropriate period of deprecation has passed.
|
|
||||||
|
|
||||||
Some breaking changes which could not be deprecated are also listed.
|
|
||||||
|
|
||||||
|
|
||||||
:class:`pytest.Package` is no longer a :class:`pytest.Module` or :class:`pytest.File`
|
:class:`pytest.Package` is no longer a :class:`pytest.Module` or :class:`pytest.File`
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
collect_ignore = ["nonpython"]
|
collect_ignore = ["nonpython", "customdirectory"]
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
.. _`custom directory collectors`:
|
||||||
|
|
||||||
|
Using a custom directory collector
|
||||||
|
====================================================
|
||||||
|
|
||||||
|
By default, pytest collects directories using :class:`pytest.Package`, for directories with ``__init__.py`` files,
|
||||||
|
and :class:`pytest.Dir` for other directories.
|
||||||
|
If you want to customize how a directory is collected, you can write your own :class:`pytest.Directory` collector,
|
||||||
|
and use :hook:`pytest_collect_directory` to hook it up.
|
||||||
|
|
||||||
|
.. _`directory manifest plugin`:
|
||||||
|
|
||||||
|
A basic example for a directory manifest file
|
||||||
|
--------------------------------------------------------------
|
||||||
|
|
||||||
|
Suppose you want to customize how collection is done on a per-directory basis.
|
||||||
|
Here is an example ``conftest.py`` plugin that allows directories to contain a ``manifest.json`` file,
|
||||||
|
which defines how the collection should be done for the directory.
|
||||||
|
In this example, only a simple list of files is supported,
|
||||||
|
however you can imagine adding other keys, such as exclusions and globs.
|
||||||
|
|
||||||
|
.. include:: customdirectory/conftest.py
|
||||||
|
:literal:
|
||||||
|
|
||||||
|
You can create a ``manifest.json`` file and some test files:
|
||||||
|
|
||||||
|
.. include:: customdirectory/tests/manifest.json
|
||||||
|
:literal:
|
||||||
|
|
||||||
|
.. include:: customdirectory/tests/test_first.py
|
||||||
|
:literal:
|
||||||
|
|
||||||
|
.. include:: customdirectory/tests/test_second.py
|
||||||
|
:literal:
|
||||||
|
|
||||||
|
.. include:: customdirectory/tests/test_third.py
|
||||||
|
:literal:
|
||||||
|
|
||||||
|
An you can now execute the test specification:
|
||||||
|
|
||||||
|
.. code-block:: pytest
|
||||||
|
|
||||||
|
customdirectory $ pytest
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
|
rootdir: /home/sweet/project/customdirectory
|
||||||
|
configfile: pytest.ini
|
||||||
|
collected 2 items
|
||||||
|
|
||||||
|
tests/test_first.py . [ 50%]
|
||||||
|
tests/test_second.py . [100%]
|
||||||
|
|
||||||
|
============================ 2 passed in 0.12s =============================
|
||||||
|
|
||||||
|
.. regendoc:wipe
|
||||||
|
|
||||||
|
Notice how ``test_three.py`` was not executed, because it is not listed in the manifest.
|
||||||
|
|
||||||
|
You can verify that your custom collector appears in the collection tree:
|
||||||
|
|
||||||
|
.. code-block:: pytest
|
||||||
|
|
||||||
|
customdirectory $ pytest --collect-only
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
|
rootdir: /home/sweet/project/customdirectory
|
||||||
|
configfile: pytest.ini
|
||||||
|
collected 2 items
|
||||||
|
|
||||||
|
<Dir customdirectory>
|
||||||
|
<ManifestDirectory tests>
|
||||||
|
<Module test_first.py>
|
||||||
|
<Function test_1>
|
||||||
|
<Module test_second.py>
|
||||||
|
<Function test_2>
|
||||||
|
|
||||||
|
======================== 2 tests collected in 0.12s ========================
|
|
@ -0,0 +1,28 @@
|
||||||
|
# content of conftest.py
|
||||||
|
import json
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
class ManifestDirectory(pytest.Directory):
|
||||||
|
def collect(self):
|
||||||
|
# The standard pytest behavior is to loop over all `test_*.py` files and
|
||||||
|
# call `pytest_collect_file` on each file. This collector instead reads
|
||||||
|
# the `manifest.json` file and only calls `pytest_collect_file` for the
|
||||||
|
# files defined there.
|
||||||
|
manifest_path = self.path / "manifest.json"
|
||||||
|
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
|
||||||
|
ihook = self.ihook
|
||||||
|
for file in manifest["files"]:
|
||||||
|
yield from ihook.pytest_collect_file(
|
||||||
|
file_path=self.path / file, parent=self
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.hookimpl
|
||||||
|
def pytest_collect_directory(path, parent):
|
||||||
|
# Use our custom collector for directories containing a `mainfest.json` file.
|
||||||
|
if path.joinpath("manifest.json").is_file():
|
||||||
|
return ManifestDirectory.from_parent(parent=parent, path=path)
|
||||||
|
# Otherwise fallback to the standard behavior.
|
||||||
|
return None
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"test_first.py",
|
||||||
|
"test_second.py"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
# content of test_first.py
|
||||||
|
def test_1():
|
||||||
|
pass
|
|
@ -0,0 +1,3 @@
|
||||||
|
# content of test_second.py
|
||||||
|
def test_2():
|
||||||
|
pass
|
|
@ -0,0 +1,3 @@
|
||||||
|
# content of test_third.py
|
||||||
|
def test_3():
|
||||||
|
pass
|
|
@ -18,7 +18,6 @@ For basic examples, see
|
||||||
- :ref:`Fixtures <fixtures>` for basic fixture/setup examples
|
- :ref:`Fixtures <fixtures>` for basic fixture/setup examples
|
||||||
- :ref:`parametrize` for basic test function parametrization
|
- :ref:`parametrize` for basic test function parametrization
|
||||||
- :ref:`unittest` for basic unittest integration
|
- :ref:`unittest` for basic unittest integration
|
||||||
- :ref:`noseintegration` for basic nosetests integration
|
|
||||||
|
|
||||||
The following examples aim at various use cases you might encounter.
|
The following examples aim at various use cases you might encounter.
|
||||||
|
|
||||||
|
@ -32,3 +31,4 @@ The following examples aim at various use cases you might encounter.
|
||||||
special
|
special
|
||||||
pythoncollection
|
pythoncollection
|
||||||
nonpython
|
nonpython
|
||||||
|
customdirectory
|
||||||
|
|
|
@ -45,7 +45,7 @@ You can then restrict a test run to only run tests marked with ``webtest``:
|
||||||
|
|
||||||
$ pytest -v -m webtest
|
$ pytest -v -m webtest
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
||||||
cachedir: .pytest_cache
|
cachedir: .pytest_cache
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collecting ... collected 4 items / 3 deselected / 1 selected
|
collecting ... collected 4 items / 3 deselected / 1 selected
|
||||||
|
@ -60,7 +60,7 @@ Or the inverse, running all tests except the webtest ones:
|
||||||
|
|
||||||
$ pytest -v -m "not webtest"
|
$ pytest -v -m "not webtest"
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
||||||
cachedir: .pytest_cache
|
cachedir: .pytest_cache
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collecting ... collected 4 items / 1 deselected / 3 selected
|
collecting ... collected 4 items / 1 deselected / 3 selected
|
||||||
|
@ -82,7 +82,7 @@ tests based on their module, class, method, or function name:
|
||||||
|
|
||||||
$ pytest -v test_server.py::TestClass::test_method
|
$ pytest -v test_server.py::TestClass::test_method
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
||||||
cachedir: .pytest_cache
|
cachedir: .pytest_cache
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collecting ... collected 1 item
|
collecting ... collected 1 item
|
||||||
|
@ -97,7 +97,7 @@ You can also select on the class:
|
||||||
|
|
||||||
$ pytest -v test_server.py::TestClass
|
$ pytest -v test_server.py::TestClass
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
||||||
cachedir: .pytest_cache
|
cachedir: .pytest_cache
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collecting ... collected 1 item
|
collecting ... collected 1 item
|
||||||
|
@ -112,7 +112,7 @@ Or select multiple nodes:
|
||||||
|
|
||||||
$ pytest -v test_server.py::TestClass test_server.py::test_send_http
|
$ pytest -v test_server.py::TestClass test_server.py::test_send_http
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
||||||
cachedir: .pytest_cache
|
cachedir: .pytest_cache
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collecting ... collected 2 items
|
collecting ... collected 2 items
|
||||||
|
@ -156,7 +156,7 @@ The expression matching is now case-insensitive.
|
||||||
|
|
||||||
$ pytest -v -k http # running with the above defined example module
|
$ pytest -v -k http # running with the above defined example module
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
||||||
cachedir: .pytest_cache
|
cachedir: .pytest_cache
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collecting ... collected 4 items / 3 deselected / 1 selected
|
collecting ... collected 4 items / 3 deselected / 1 selected
|
||||||
|
@ -171,7 +171,7 @@ And you can also run all tests except the ones that match the keyword:
|
||||||
|
|
||||||
$ pytest -k "not send_http" -v
|
$ pytest -k "not send_http" -v
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
||||||
cachedir: .pytest_cache
|
cachedir: .pytest_cache
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collecting ... collected 4 items / 1 deselected / 3 selected
|
collecting ... collected 4 items / 1 deselected / 3 selected
|
||||||
|
@ -188,7 +188,7 @@ Or to select "http" and "quick" tests:
|
||||||
|
|
||||||
$ pytest -k "http or quick" -v
|
$ pytest -k "http or quick" -v
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
||||||
cachedir: .pytest_cache
|
cachedir: .pytest_cache
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collecting ... collected 4 items / 2 deselected / 2 selected
|
collecting ... collected 4 items / 2 deselected / 2 selected
|
||||||
|
@ -397,7 +397,7 @@ the test needs:
|
||||||
|
|
||||||
$ pytest -E stage2
|
$ pytest -E stage2
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 1 item
|
collected 1 item
|
||||||
|
|
||||||
|
@ -411,7 +411,7 @@ and here is one that specifies exactly the environment needed:
|
||||||
|
|
||||||
$ pytest -E stage1
|
$ pytest -E stage1
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 1 item
|
collected 1 item
|
||||||
|
|
||||||
|
@ -604,7 +604,7 @@ then you will see two tests skipped and two executed tests as expected:
|
||||||
|
|
||||||
$ pytest -rs # this option reports skip reasons
|
$ pytest -rs # this option reports skip reasons
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 4 items
|
collected 4 items
|
||||||
|
|
||||||
|
@ -620,7 +620,7 @@ Note that if you specify a platform via the marker-command line option like this
|
||||||
|
|
||||||
$ pytest -m linux
|
$ pytest -m linux
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 4 items / 3 deselected / 1 selected
|
collected 4 items / 3 deselected / 1 selected
|
||||||
|
|
||||||
|
@ -683,7 +683,7 @@ We can now use the ``-m option`` to select one set:
|
||||||
|
|
||||||
$ pytest -m interface --tb=short
|
$ pytest -m interface --tb=short
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 4 items / 2 deselected / 2 selected
|
collected 4 items / 2 deselected / 2 selected
|
||||||
|
|
||||||
|
@ -709,7 +709,7 @@ or to select both "event" and "interface" tests:
|
||||||
|
|
||||||
$ pytest -m "interface or event" --tb=short
|
$ pytest -m "interface or event" --tb=short
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 4 items / 1 deselected / 3 selected
|
collected 4 items / 1 deselected / 3 selected
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ now execute the test specification:
|
||||||
|
|
||||||
nonpython $ pytest test_simple.yaml
|
nonpython $ pytest test_simple.yaml
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project/nonpython
|
rootdir: /home/sweet/project/nonpython
|
||||||
collected 2 items
|
collected 2 items
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ consulted when reporting in ``verbose`` mode:
|
||||||
|
|
||||||
nonpython $ pytest -v
|
nonpython $ pytest -v
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
||||||
cachedir: .pytest_cache
|
cachedir: .pytest_cache
|
||||||
rootdir: /home/sweet/project/nonpython
|
rootdir: /home/sweet/project/nonpython
|
||||||
collecting ... collected 2 items
|
collecting ... collected 2 items
|
||||||
|
@ -90,7 +90,7 @@ interesting to just look at the collection tree:
|
||||||
|
|
||||||
nonpython $ pytest --collect-only
|
nonpython $ pytest --collect-only
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project/nonpython
|
rootdir: /home/sweet/project/nonpython
|
||||||
collected 2 items
|
collected 2 items
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
Parametrizing tests
|
Parametrizing tests
|
||||||
=================================================
|
=================================================
|
||||||
|
|
||||||
.. currentmodule:: _pytest.python
|
|
||||||
|
|
||||||
``pytest`` allows to easily parametrize test functions.
|
``pytest`` allows to easily parametrize test functions.
|
||||||
For basic docs, see :ref:`parametrize-basics`.
|
For basic docs, see :ref:`parametrize-basics`.
|
||||||
|
|
||||||
|
@ -160,10 +158,11 @@ objects, they are still using the default pytest representation:
|
||||||
|
|
||||||
$ pytest test_time.py --collect-only
|
$ pytest test_time.py --collect-only
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 8 items
|
collected 8 items
|
||||||
|
|
||||||
|
<Dir parametrize.rst-192>
|
||||||
<Module test_time.py>
|
<Module test_time.py>
|
||||||
<Function test_timedistance_v0[a0-b0-expected0]>
|
<Function test_timedistance_v0[a0-b0-expected0]>
|
||||||
<Function test_timedistance_v0[a1-b1-expected1]>
|
<Function test_timedistance_v0[a1-b1-expected1]>
|
||||||
|
@ -185,7 +184,7 @@ A quick port of "testscenarios"
|
||||||
Here is a quick port to run tests configured with :pypi:`testscenarios`,
|
Here is a quick port to run tests configured with :pypi:`testscenarios`,
|
||||||
an add-on from Robert Collins for the standard unittest framework. We
|
an add-on from Robert Collins for the standard unittest framework. We
|
||||||
only have to work a bit to construct the correct arguments for pytest's
|
only have to work a bit to construct the correct arguments for pytest's
|
||||||
:py:func:`Metafunc.parametrize`:
|
:py:func:`Metafunc.parametrize <pytest.Metafunc.parametrize>`:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
@ -222,7 +221,7 @@ this is a fully self-contained example which you can run with:
|
||||||
|
|
||||||
$ pytest test_scenarios.py
|
$ pytest test_scenarios.py
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 4 items
|
collected 4 items
|
||||||
|
|
||||||
|
@ -236,10 +235,11 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia
|
||||||
|
|
||||||
$ pytest --collect-only test_scenarios.py
|
$ pytest --collect-only test_scenarios.py
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 4 items
|
collected 4 items
|
||||||
|
|
||||||
|
<Dir parametrize.rst-192>
|
||||||
<Module test_scenarios.py>
|
<Module test_scenarios.py>
|
||||||
<Class TestSampleWithScenarios>
|
<Class TestSampleWithScenarios>
|
||||||
<Function test_demo1[basic]>
|
<Function test_demo1[basic]>
|
||||||
|
@ -314,10 +314,11 @@ Let's first see how it looks like at collection time:
|
||||||
|
|
||||||
$ pytest test_backends.py --collect-only
|
$ pytest test_backends.py --collect-only
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 2 items
|
collected 2 items
|
||||||
|
|
||||||
|
<Dir parametrize.rst-192>
|
||||||
<Module test_backends.py>
|
<Module test_backends.py>
|
||||||
<Function test_db_initialized[d1]>
|
<Function test_db_initialized[d1]>
|
||||||
<Function test_db_initialized[d2]>
|
<Function test_db_initialized[d2]>
|
||||||
|
@ -412,7 +413,7 @@ The result of this test will be successful:
|
||||||
|
|
||||||
$ pytest -v test_indirect_list.py
|
$ pytest -v test_indirect_list.py
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
||||||
cachedir: .pytest_cache
|
cachedir: .pytest_cache
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collecting ... collected 1 item
|
collecting ... collected 1 item
|
||||||
|
@ -502,12 +503,11 @@ Running it results in some skips if we don't have all the python interpreters in
|
||||||
.. code-block:: pytest
|
.. code-block:: pytest
|
||||||
|
|
||||||
. $ pytest -rs -q multipython.py
|
. $ pytest -rs -q multipython.py
|
||||||
sssssssssssssssssssssssssss [100%]
|
ssssssssssssssssssssssss... [100%]
|
||||||
========================= short test summary info ==========================
|
========================= short test summary info ==========================
|
||||||
SKIPPED [9] multipython.py:69: 'python3.5' not found
|
SKIPPED [12] multipython.py:68: 'python3.9' not found
|
||||||
SKIPPED [9] multipython.py:69: 'python3.6' not found
|
SKIPPED [12] multipython.py:68: 'python3.10' not found
|
||||||
SKIPPED [9] multipython.py:69: 'python3.7' not found
|
3 passed, 24 skipped in 0.12s
|
||||||
27 skipped in 0.12s
|
|
||||||
|
|
||||||
Parametrization of optional implementations/imports
|
Parametrization of optional implementations/imports
|
||||||
---------------------------------------------------
|
---------------------------------------------------
|
||||||
|
@ -567,7 +567,7 @@ If you run this with reporting for skips enabled:
|
||||||
|
|
||||||
$ pytest -rs test_module.py
|
$ pytest -rs test_module.py
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 2 items
|
collected 2 items
|
||||||
|
|
||||||
|
@ -628,7 +628,7 @@ Then run ``pytest`` with verbose mode and with only the ``basic`` marker:
|
||||||
|
|
||||||
$ pytest -v -m basic
|
$ pytest -v -m basic
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
||||||
cachedir: .pytest_cache
|
cachedir: .pytest_cache
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collecting ... collected 24 items / 21 deselected / 3 selected
|
collecting ... collected 24 items / 21 deselected / 3 selected
|
||||||
|
|
|
@ -147,11 +147,12 @@ The test collection would look like this:
|
||||||
|
|
||||||
$ pytest --collect-only
|
$ pytest --collect-only
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
configfile: pytest.ini
|
configfile: pytest.ini
|
||||||
collected 2 items
|
collected 2 items
|
||||||
|
|
||||||
|
<Dir pythoncollection.rst-193>
|
||||||
<Module check_myapp.py>
|
<Module check_myapp.py>
|
||||||
<Class CheckMyApp>
|
<Class CheckMyApp>
|
||||||
<Function simple_check>
|
<Function simple_check>
|
||||||
|
@ -209,12 +210,14 @@ You can always peek at the collection tree without running tests like this:
|
||||||
|
|
||||||
. $ pytest --collect-only pythoncollection.py
|
. $ pytest --collect-only pythoncollection.py
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
configfile: pytest.ini
|
configfile: pytest.ini
|
||||||
collected 3 items
|
collected 3 items
|
||||||
|
|
||||||
<Module CWD/pythoncollection.py>
|
<Dir pythoncollection.rst-193>
|
||||||
|
<Dir CWD>
|
||||||
|
<Module pythoncollection.py>
|
||||||
<Function test_function>
|
<Function test_function>
|
||||||
<Class TestClass>
|
<Class TestClass>
|
||||||
<Function test_method>
|
<Function test_method>
|
||||||
|
@ -291,7 +294,7 @@ file will be left out:
|
||||||
|
|
||||||
$ pytest --collect-only
|
$ pytest --collect-only
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
configfile: pytest.ini
|
configfile: pytest.ini
|
||||||
collected 0 items
|
collected 0 items
|
||||||
|
|
|
@ -9,7 +9,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
|
||||||
|
|
||||||
assertion $ pytest failure_demo.py
|
assertion $ pytest failure_demo.py
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project/assertion
|
rootdir: /home/sweet/project/assertion
|
||||||
collected 44 items
|
collected 44 items
|
||||||
|
|
||||||
|
@ -80,6 +80,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
|
||||||
def test_eq_text(self):
|
def test_eq_text(self):
|
||||||
> assert "spam" == "eggs"
|
> assert "spam" == "eggs"
|
||||||
E AssertionError: assert 'spam' == 'eggs'
|
E AssertionError: assert 'spam' == 'eggs'
|
||||||
|
E
|
||||||
E - eggs
|
E - eggs
|
||||||
E + spam
|
E + spam
|
||||||
|
|
||||||
|
@ -91,6 +92,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
|
||||||
def test_eq_similar_text(self):
|
def test_eq_similar_text(self):
|
||||||
> assert "foo 1 bar" == "foo 2 bar"
|
> assert "foo 1 bar" == "foo 2 bar"
|
||||||
E AssertionError: assert 'foo 1 bar' == 'foo 2 bar'
|
E AssertionError: assert 'foo 1 bar' == 'foo 2 bar'
|
||||||
|
E
|
||||||
E - foo 2 bar
|
E - foo 2 bar
|
||||||
E ? ^
|
E ? ^
|
||||||
E + foo 1 bar
|
E + foo 1 bar
|
||||||
|
@ -104,6 +106,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
|
||||||
def test_eq_multiline_text(self):
|
def test_eq_multiline_text(self):
|
||||||
> assert "foo\nspam\nbar" == "foo\neggs\nbar"
|
> assert "foo\nspam\nbar" == "foo\neggs\nbar"
|
||||||
E AssertionError: assert 'foo\nspam\nbar' == 'foo\neggs\nbar'
|
E AssertionError: assert 'foo\nspam\nbar' == 'foo\neggs\nbar'
|
||||||
|
E
|
||||||
E foo
|
E foo
|
||||||
E - eggs
|
E - eggs
|
||||||
E + spam
|
E + spam
|
||||||
|
@ -119,6 +122,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
|
||||||
b = "1" * 100 + "b" + "2" * 100
|
b = "1" * 100 + "b" + "2" * 100
|
||||||
> assert a == b
|
> assert a == b
|
||||||
E AssertionError: assert '111111111111...2222222222222' == '111111111111...2222222222222'
|
E AssertionError: assert '111111111111...2222222222222' == '111111111111...2222222222222'
|
||||||
|
E
|
||||||
E Skipping 90 identical leading characters in diff, use -v to show
|
E Skipping 90 identical leading characters in diff, use -v to show
|
||||||
E Skipping 91 identical trailing characters in diff, use -v to show
|
E Skipping 91 identical trailing characters in diff, use -v to show
|
||||||
E - 1111111111b222222222
|
E - 1111111111b222222222
|
||||||
|
@ -136,15 +140,15 @@ Here is a nice run of several failures and how ``pytest`` presents things:
|
||||||
b = "1\n" * 100 + "b" + "2\n" * 100
|
b = "1\n" * 100 + "b" + "2\n" * 100
|
||||||
> assert a == b
|
> assert a == b
|
||||||
E AssertionError: assert '1\n1\n1\n1\n...n2\n2\n2\n2\n' == '1\n1\n1\n1\n...n2\n2\n2\n2\n'
|
E AssertionError: assert '1\n1\n1\n1\n...n2\n2\n2\n2\n' == '1\n1\n1\n1\n...n2\n2\n2\n2\n'
|
||||||
|
E
|
||||||
E Skipping 190 identical leading characters in diff, use -v to show
|
E Skipping 190 identical leading characters in diff, use -v to show
|
||||||
E Skipping 191 identical trailing characters in diff, use -v to show
|
E Skipping 191 identical trailing characters in diff, use -v to show
|
||||||
E 1
|
E 1
|
||||||
E 1
|
E 1
|
||||||
E 1
|
E 1
|
||||||
E 1
|
|
||||||
E 1...
|
E 1...
|
||||||
E
|
E
|
||||||
E ...Full output truncated (6 lines hidden), use '-vv' to show
|
E ...Full output truncated (7 lines hidden), use '-vv' to show
|
||||||
|
|
||||||
failure_demo.py:60: AssertionError
|
failure_demo.py:60: AssertionError
|
||||||
_________________ TestSpecialisedExplanations.test_eq_list _________________
|
_________________ TestSpecialisedExplanations.test_eq_list _________________
|
||||||
|
@ -154,6 +158,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
|
||||||
def test_eq_list(self):
|
def test_eq_list(self):
|
||||||
> assert [0, 1, 2] == [0, 1, 3]
|
> assert [0, 1, 2] == [0, 1, 3]
|
||||||
E assert [0, 1, 2] == [0, 1, 3]
|
E assert [0, 1, 2] == [0, 1, 3]
|
||||||
|
E
|
||||||
E At index 2 diff: 2 != 3
|
E At index 2 diff: 2 != 3
|
||||||
E Use -v to get more diff
|
E Use -v to get more diff
|
||||||
|
|
||||||
|
@ -167,6 +172,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
|
||||||
b = [0] * 100 + [2] + [3] * 100
|
b = [0] * 100 + [2] + [3] * 100
|
||||||
> assert a == b
|
> assert a == b
|
||||||
E assert [0, 0, 0, 0, 0, 0, ...] == [0, 0, 0, 0, 0, 0, ...]
|
E assert [0, 0, 0, 0, 0, 0, ...] == [0, 0, 0, 0, 0, 0, ...]
|
||||||
|
E
|
||||||
E At index 100 diff: 1 != 2
|
E At index 100 diff: 1 != 2
|
||||||
E Use -v to get more diff
|
E Use -v to get more diff
|
||||||
|
|
||||||
|
@ -178,6 +184,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
|
||||||
def test_eq_dict(self):
|
def test_eq_dict(self):
|
||||||
> assert {"a": 0, "b": 1, "c": 0} == {"a": 0, "b": 2, "d": 0}
|
> assert {"a": 0, "b": 1, "c": 0} == {"a": 0, "b": 2, "d": 0}
|
||||||
E AssertionError: assert {'a': 0, 'b': 1, 'c': 0} == {'a': 0, 'b': 2, 'd': 0}
|
E AssertionError: assert {'a': 0, 'b': 1, 'c': 0} == {'a': 0, 'b': 2, 'd': 0}
|
||||||
|
E
|
||||||
E Omitting 1 identical items, use -vv to show
|
E Omitting 1 identical items, use -vv to show
|
||||||
E Differing items:
|
E Differing items:
|
||||||
E {'b': 1} != {'b': 2}
|
E {'b': 1} != {'b': 2}
|
||||||
|
@ -195,6 +202,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
|
||||||
def test_eq_set(self):
|
def test_eq_set(self):
|
||||||
> assert {0, 10, 11, 12} == {0, 20, 21}
|
> assert {0, 10, 11, 12} == {0, 20, 21}
|
||||||
E assert {0, 10, 11, 12} == {0, 20, 21}
|
E assert {0, 10, 11, 12} == {0, 20, 21}
|
||||||
|
E
|
||||||
E Extra items in the left set:
|
E Extra items in the left set:
|
||||||
E 10
|
E 10
|
||||||
E 11
|
E 11
|
||||||
|
@ -212,6 +220,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
|
||||||
def test_eq_longer_list(self):
|
def test_eq_longer_list(self):
|
||||||
> assert [1, 2] == [1, 2, 3]
|
> assert [1, 2] == [1, 2, 3]
|
||||||
E assert [1, 2] == [1, 2, 3]
|
E assert [1, 2] == [1, 2, 3]
|
||||||
|
E
|
||||||
E Right contains one more item: 3
|
E Right contains one more item: 3
|
||||||
E Use -v to get more diff
|
E Use -v to get more diff
|
||||||
|
|
||||||
|
@ -233,6 +242,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
|
||||||
text = "some multiline\ntext\nwhich\nincludes foo\nand a\ntail"
|
text = "some multiline\ntext\nwhich\nincludes foo\nand a\ntail"
|
||||||
> assert "foo" not in text
|
> assert "foo" not in text
|
||||||
E AssertionError: assert 'foo' not in 'some multil...nand a\ntail'
|
E AssertionError: assert 'foo' not in 'some multil...nand a\ntail'
|
||||||
|
E
|
||||||
E 'foo' is contained here:
|
E 'foo' is contained here:
|
||||||
E some multiline
|
E some multiline
|
||||||
E text
|
E text
|
||||||
|
@ -251,6 +261,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
|
||||||
text = "single foo line"
|
text = "single foo line"
|
||||||
> assert "foo" not in text
|
> assert "foo" not in text
|
||||||
E AssertionError: assert 'foo' not in 'single foo line'
|
E AssertionError: assert 'foo' not in 'single foo line'
|
||||||
|
E
|
||||||
E 'foo' is contained here:
|
E 'foo' is contained here:
|
||||||
E single foo line
|
E single foo line
|
||||||
E ? +++
|
E ? +++
|
||||||
|
@ -264,6 +275,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
|
||||||
text = "head " * 50 + "foo " + "tail " * 20
|
text = "head " * 50 + "foo " + "tail " * 20
|
||||||
> assert "foo" not in text
|
> assert "foo" not in text
|
||||||
E AssertionError: assert 'foo' not in 'head head h...l tail tail '
|
E AssertionError: assert 'foo' not in 'head head h...l tail tail '
|
||||||
|
E
|
||||||
E 'foo' is contained here:
|
E 'foo' is contained here:
|
||||||
E head head foo tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail
|
E head head foo tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail
|
||||||
E ? +++
|
E ? +++
|
||||||
|
@ -277,6 +289,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
|
||||||
text = "head " * 50 + "f" * 70 + "tail " * 20
|
text = "head " * 50 + "f" * 70 + "tail " * 20
|
||||||
> assert "f" * 70 not in text
|
> assert "f" * 70 not in text
|
||||||
E AssertionError: assert 'fffffffffff...ffffffffffff' not in 'head head h...l tail tail '
|
E AssertionError: assert 'fffffffffff...ffffffffffff' not in 'head head h...l tail tail '
|
||||||
|
E
|
||||||
E 'ffffffffffffffffff...fffffffffffffffffff' is contained here:
|
E 'ffffffffffffffffff...fffffffffffffffffff' is contained here:
|
||||||
E head head fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffftail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail
|
E head head fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffftail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail
|
||||||
E ? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
E ? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
|
@ -168,7 +168,7 @@ Now we'll get feedback on a bad argument:
|
||||||
|
|
||||||
|
|
||||||
If you need to provide more detailed error messages, you can use the
|
If you need to provide more detailed error messages, you can use the
|
||||||
``type`` parameter and raise ``pytest.UsageError``:
|
``type`` parameter and raise :exc:`pytest.UsageError`:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
@ -232,7 +232,7 @@ directory with the above conftest.py:
|
||||||
|
|
||||||
$ pytest
|
$ pytest
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 0 items
|
collected 0 items
|
||||||
|
|
||||||
|
@ -296,7 +296,7 @@ and when running it will see a skipped "slow" test:
|
||||||
|
|
||||||
$ pytest -rs # "-rs" means report details on the little 's'
|
$ pytest -rs # "-rs" means report details on the little 's'
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 2 items
|
collected 2 items
|
||||||
|
|
||||||
|
@ -312,7 +312,7 @@ Or run it including the ``slow`` marked test:
|
||||||
|
|
||||||
$ pytest --runslow
|
$ pytest --runslow
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 2 items
|
collected 2 items
|
||||||
|
|
||||||
|
@ -456,7 +456,7 @@ which will add the string to the test header accordingly:
|
||||||
|
|
||||||
$ pytest
|
$ pytest
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
project deps: mylib-1.1
|
project deps: mylib-1.1
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 0 items
|
collected 0 items
|
||||||
|
@ -484,7 +484,7 @@ which will add info only when run with "--v":
|
||||||
|
|
||||||
$ pytest -v
|
$ pytest -v
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
||||||
cachedir: .pytest_cache
|
cachedir: .pytest_cache
|
||||||
info1: did you know that ...
|
info1: did you know that ...
|
||||||
did you?
|
did you?
|
||||||
|
@ -499,7 +499,7 @@ and nothing when run plainly:
|
||||||
|
|
||||||
$ pytest
|
$ pytest
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 0 items
|
collected 0 items
|
||||||
|
|
||||||
|
@ -538,7 +538,7 @@ Now we can profile which test functions execute the slowest:
|
||||||
|
|
||||||
$ pytest --durations=3
|
$ pytest --durations=3
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 3 items
|
collected 3 items
|
||||||
|
|
||||||
|
@ -644,7 +644,7 @@ If we run this:
|
||||||
|
|
||||||
$ pytest -rx
|
$ pytest -rx
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 4 items
|
collected 4 items
|
||||||
|
|
||||||
|
@ -660,6 +660,31 @@ If we run this:
|
||||||
E assert 0
|
E assert 0
|
||||||
|
|
||||||
test_step.py:11: AssertionError
|
test_step.py:11: AssertionError
|
||||||
|
================================ XFAILURES =================================
|
||||||
|
______________________ TestUserHandling.test_deletion ______________________
|
||||||
|
|
||||||
|
item = <Function test_deletion>
|
||||||
|
|
||||||
|
def pytest_runtest_setup(item):
|
||||||
|
if "incremental" in item.keywords:
|
||||||
|
# retrieve the class name of the test
|
||||||
|
cls_name = str(item.cls)
|
||||||
|
# check if a previous test has failed for this class
|
||||||
|
if cls_name in _test_failed_incremental:
|
||||||
|
# retrieve the index of the test (if parametrize is used in combination with incremental)
|
||||||
|
parametrize_index = (
|
||||||
|
tuple(item.callspec.indices.values())
|
||||||
|
if hasattr(item, "callspec")
|
||||||
|
else ()
|
||||||
|
)
|
||||||
|
# retrieve the name of the first test function to fail for this class name and index
|
||||||
|
test_name = _test_failed_incremental[cls_name].get(parametrize_index, None)
|
||||||
|
# if name found, test has failed for the combination of class name & test name
|
||||||
|
if test_name is not None:
|
||||||
|
> pytest.xfail(f"previous test failed ({test_name})")
|
||||||
|
E _pytest.outcomes.XFailed: previous test failed (test_modification)
|
||||||
|
|
||||||
|
conftest.py:47: XFailed
|
||||||
========================= short test summary info ==========================
|
========================= short test summary info ==========================
|
||||||
XFAIL test_step.py::TestUserHandling::test_deletion - reason: previous test failed (test_modification)
|
XFAIL test_step.py::TestUserHandling::test_deletion - reason: previous test failed (test_modification)
|
||||||
================== 1 failed, 2 passed, 1 xfailed in 0.12s ==================
|
================== 1 failed, 2 passed, 1 xfailed in 0.12s ==================
|
||||||
|
@ -726,14 +751,14 @@ We can run this:
|
||||||
|
|
||||||
$ pytest
|
$ pytest
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 7 items
|
collected 7 items
|
||||||
|
|
||||||
test_step.py .Fx. [ 57%]
|
a/test_db.py F [ 14%]
|
||||||
a/test_db.py F [ 71%]
|
a/test_db2.py F [ 28%]
|
||||||
a/test_db2.py F [ 85%]
|
b/test_error.py E [ 42%]
|
||||||
b/test_error.py E [100%]
|
test_step.py .Fx. [100%]
|
||||||
|
|
||||||
================================== ERRORS ==================================
|
================================== ERRORS ==================================
|
||||||
_______________________ ERROR at setup of test_root ________________________
|
_______________________ ERROR at setup of test_root ________________________
|
||||||
|
@ -745,39 +770,39 @@ We can run this:
|
||||||
|
|
||||||
/home/sweet/project/b/test_error.py:1
|
/home/sweet/project/b/test_error.py:1
|
||||||
================================= FAILURES =================================
|
================================= FAILURES =================================
|
||||||
|
_________________________________ test_a1 __________________________________
|
||||||
|
|
||||||
|
db = <conftest.DB object at 0xdeadbeef0002>
|
||||||
|
|
||||||
|
def test_a1(db):
|
||||||
|
> assert 0, db # to show value
|
||||||
|
E AssertionError: <conftest.DB object at 0xdeadbeef0002>
|
||||||
|
E assert 0
|
||||||
|
|
||||||
|
a/test_db.py:2: AssertionError
|
||||||
|
_________________________________ test_a2 __________________________________
|
||||||
|
|
||||||
|
db = <conftest.DB object at 0xdeadbeef0002>
|
||||||
|
|
||||||
|
def test_a2(db):
|
||||||
|
> assert 0, db # to show value
|
||||||
|
E AssertionError: <conftest.DB object at 0xdeadbeef0002>
|
||||||
|
E assert 0
|
||||||
|
|
||||||
|
a/test_db2.py:2: AssertionError
|
||||||
____________________ TestUserHandling.test_modification ____________________
|
____________________ TestUserHandling.test_modification ____________________
|
||||||
|
|
||||||
self = <test_step.TestUserHandling object at 0xdeadbeef0002>
|
self = <test_step.TestUserHandling object at 0xdeadbeef0003>
|
||||||
|
|
||||||
def test_modification(self):
|
def test_modification(self):
|
||||||
> assert 0
|
> assert 0
|
||||||
E assert 0
|
E assert 0
|
||||||
|
|
||||||
test_step.py:11: AssertionError
|
test_step.py:11: AssertionError
|
||||||
_________________________________ test_a1 __________________________________
|
|
||||||
|
|
||||||
db = <conftest.DB object at 0xdeadbeef0003>
|
|
||||||
|
|
||||||
def test_a1(db):
|
|
||||||
> assert 0, db # to show value
|
|
||||||
E AssertionError: <conftest.DB object at 0xdeadbeef0003>
|
|
||||||
E assert 0
|
|
||||||
|
|
||||||
a/test_db.py:2: AssertionError
|
|
||||||
_________________________________ test_a2 __________________________________
|
|
||||||
|
|
||||||
db = <conftest.DB object at 0xdeadbeef0003>
|
|
||||||
|
|
||||||
def test_a2(db):
|
|
||||||
> assert 0, db # to show value
|
|
||||||
E AssertionError: <conftest.DB object at 0xdeadbeef0003>
|
|
||||||
E assert 0
|
|
||||||
|
|
||||||
a/test_db2.py:2: AssertionError
|
|
||||||
========================= short test summary info ==========================
|
========================= short test summary info ==========================
|
||||||
FAILED test_step.py::TestUserHandling::test_modification - assert 0
|
|
||||||
FAILED a/test_db.py::test_a1 - AssertionError: <conftest.DB object at 0x7...
|
FAILED a/test_db.py::test_a1 - AssertionError: <conftest.DB object at 0x7...
|
||||||
FAILED a/test_db2.py::test_a2 - AssertionError: <conftest.DB object at 0x...
|
FAILED a/test_db2.py::test_a2 - AssertionError: <conftest.DB object at 0x...
|
||||||
|
FAILED test_step.py::TestUserHandling::test_modification - assert 0
|
||||||
ERROR b/test_error.py::test_root
|
ERROR b/test_error.py::test_root
|
||||||
============= 3 failed, 2 passed, 1 xfailed, 1 error in 0.12s ==============
|
============= 3 failed, 2 passed, 1 xfailed, 1 error in 0.12s ==============
|
||||||
|
|
||||||
|
@ -846,7 +871,7 @@ and run them:
|
||||||
|
|
||||||
$ pytest test_module.py
|
$ pytest test_module.py
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 2 items
|
collected 2 items
|
||||||
|
|
||||||
|
@ -955,7 +980,7 @@ and run it:
|
||||||
|
|
||||||
$ pytest -s test_module.py
|
$ pytest -s test_module.py
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 3 items
|
collected 3 items
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ style of setup/teardown functions:
|
||||||
In addition, pytest continues to support :ref:`xunitsetup`. You can mix
|
In addition, pytest continues to support :ref:`xunitsetup`. You can mix
|
||||||
both styles, moving incrementally from classic to new style, as you
|
both styles, moving incrementally from classic to new style, as you
|
||||||
prefer. You can also start out from existing :ref:`unittest.TestCase
|
prefer. You can also start out from existing :ref:`unittest.TestCase
|
||||||
style <unittest.TestCase>` or :ref:`nose based <nosestyle>` projects.
|
style <unittest.TestCase>`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ A note about fixture cleanup
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
pytest does not do any special processing for :data:`SIGTERM <signal.SIGTERM>` and
|
pytest does not do any special processing for :data:`SIGTERM <signal.SIGTERM>` and
|
||||||
:data:`SIGQUIT <signal.SIGQUIT>` signals (:data:`SIGINT <signal.SIGINT>` is handled naturally
|
``SIGQUIT`` signals (:data:`SIGINT <signal.SIGINT>` is handled naturally
|
||||||
by the Python runtime via :class:`KeyboardInterrupt`), so fixtures that manage external resources which are important
|
by the Python runtime via :class:`KeyboardInterrupt`), so fixtures that manage external resources which are important
|
||||||
to be cleared when the Python process is terminated (by those signals) might leak resources.
|
to be cleared when the Python process is terminated (by those signals) might leak resources.
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,6 @@ funcarg mechanism, see :ref:`historical funcargs and pytest.funcargs`.
|
||||||
If you are new to pytest, then you can simply ignore this
|
If you are new to pytest, then you can simply ignore this
|
||||||
section and read the other sections.
|
section and read the other sections.
|
||||||
|
|
||||||
.. currentmodule:: _pytest
|
|
||||||
|
|
||||||
Shortcomings of the previous ``pytest_funcarg__`` mechanism
|
Shortcomings of the previous ``pytest_funcarg__`` mechanism
|
||||||
--------------------------------------------------------------
|
--------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -46,7 +44,7 @@ There are several limitations and difficulties with this approach:
|
||||||
|
|
||||||
2. parametrizing the "db" resource is not straight forward:
|
2. parametrizing the "db" resource is not straight forward:
|
||||||
you need to apply a "parametrize" decorator or implement a
|
you need to apply a "parametrize" decorator or implement a
|
||||||
:py:func:`~hookspec.pytest_generate_tests` hook
|
:hook:`pytest_generate_tests` hook
|
||||||
calling :py:func:`~pytest.Metafunc.parametrize` which
|
calling :py:func:`~pytest.Metafunc.parametrize` which
|
||||||
performs parametrization at the places where the resource
|
performs parametrization at the places where the resource
|
||||||
is used. Moreover, you need to modify the factory to use an
|
is used. Moreover, you need to modify the factory to use an
|
||||||
|
@ -94,7 +92,7 @@ Direct parametrization of funcarg resource factories
|
||||||
|
|
||||||
Previously, funcarg factories could not directly cause parametrization.
|
Previously, funcarg factories could not directly cause parametrization.
|
||||||
You needed to specify a ``@parametrize`` decorator on your test function
|
You needed to specify a ``@parametrize`` decorator on your test function
|
||||||
or implement a ``pytest_generate_tests`` hook to perform
|
or implement a :hook:`pytest_generate_tests` hook to perform
|
||||||
parametrization, i.e. calling a test multiple times with different value
|
parametrization, i.e. calling a test multiple times with different value
|
||||||
sets. pytest-2.3 introduces a decorator for use on the factory itself:
|
sets. pytest-2.3 introduces a decorator for use on the factory itself:
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ Install ``pytest``
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ pytest --version
|
$ pytest --version
|
||||||
pytest 7.4.3
|
pytest 8.0.0rc2
|
||||||
|
|
||||||
.. _`simpletest`:
|
.. _`simpletest`:
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ The test
|
||||||
|
|
||||||
$ pytest
|
$ pytest
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 1 item
|
collected 1 item
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ Use the :ref:`raises <assertraises>` helper to assert that some code raises an e
|
||||||
f()
|
f()
|
||||||
|
|
||||||
You can also use the context provided by :ref:`raises <assertraises>` to
|
You can also use the context provided by :ref:`raises <assertraises>` to
|
||||||
assert that an expected exception is part of a raised ``ExceptionGroup``:
|
assert that an expected exception is part of a raised :class:`ExceptionGroup`:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,7 @@ More details can be found in the :pull:`original PR <3317>`.
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
in a future major release of pytest we will introduce class based markers,
|
in a future major release of pytest we will introduce class based markers,
|
||||||
at which point markers will no longer be limited to instances of :py:class:`~_pytest.mark.Mark`.
|
at which point markers will no longer be limited to instances of :py:class:`~pytest.Mark`.
|
||||||
|
|
||||||
|
|
||||||
cache plugin integrated into the core
|
cache plugin integrated into the core
|
||||||
|
|
|
@ -29,7 +29,7 @@ you will see the return value of the function call:
|
||||||
|
|
||||||
$ pytest test_assert1.py
|
$ pytest test_assert1.py
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 1 item
|
collected 1 item
|
||||||
|
|
||||||
|
@ -143,11 +143,13 @@ Notes:
|
||||||
* The ``match`` parameter also matches against `PEP-678 <https://peps.python.org/pep-0678/>`__ ``__notes__``.
|
* The ``match`` parameter also matches against `PEP-678 <https://peps.python.org/pep-0678/>`__ ``__notes__``.
|
||||||
|
|
||||||
|
|
||||||
|
.. _`assert-matching-exception-groups`:
|
||||||
|
|
||||||
Matching exception groups
|
Matching exception groups
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
You can also use the :func:`excinfo.group_contains() <pytest.ExceptionInfo.group_contains>`
|
You can also use the :func:`excinfo.group_contains() <pytest.ExceptionInfo.group_contains>`
|
||||||
method to test for exceptions returned as part of an ``ExceptionGroup``:
|
method to test for exceptions returned as part of an :class:`ExceptionGroup`:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
@ -278,7 +280,7 @@ if you run this module:
|
||||||
|
|
||||||
$ pytest test_assert2.py
|
$ pytest test_assert2.py
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 1 item
|
collected 1 item
|
||||||
|
|
||||||
|
@ -292,6 +294,7 @@ if you run this module:
|
||||||
set2 = set("8035")
|
set2 = set("8035")
|
||||||
> assert set1 == set2
|
> assert set1 == set2
|
||||||
E AssertionError: assert {'0', '1', '3', '8'} == {'0', '3', '5', '8'}
|
E AssertionError: assert {'0', '1', '3', '8'} == {'0', '3', '5', '8'}
|
||||||
|
E
|
||||||
E Extra items in the left set:
|
E Extra items in the left set:
|
||||||
E '1'
|
E '1'
|
||||||
E Extra items in the right set:
|
E Extra items in the right set:
|
||||||
|
|
|
@ -86,7 +86,7 @@ If you then run it with ``--lf``:
|
||||||
|
|
||||||
$ pytest --lf
|
$ pytest --lf
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 2 items
|
collected 2 items
|
||||||
run-last-failure: rerun previous 2 failures
|
run-last-failure: rerun previous 2 failures
|
||||||
|
@ -132,7 +132,7 @@ of ``FF`` and dots):
|
||||||
|
|
||||||
$ pytest --ff
|
$ pytest --ff
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 50 items
|
collected 50 items
|
||||||
run-last-failure: rerun previous 2 failures first
|
run-last-failure: rerun previous 2 failures first
|
||||||
|
@ -281,7 +281,7 @@ You can always peek at the content of the cache using the
|
||||||
|
|
||||||
$ pytest --cache-show
|
$ pytest --cache-show
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
cachedir: /home/sweet/project/.pytest_cache
|
cachedir: /home/sweet/project/.pytest_cache
|
||||||
--------------------------- cache values for '*' ---------------------------
|
--------------------------- cache values for '*' ---------------------------
|
||||||
|
@ -303,7 +303,7 @@ filtering:
|
||||||
|
|
||||||
$ pytest --cache-show example/*
|
$ pytest --cache-show example/*
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
cachedir: /home/sweet/project/.pytest_cache
|
cachedir: /home/sweet/project/.pytest_cache
|
||||||
----------------------- cache values for 'example/*' -----------------------
|
----------------------- cache values for 'example/*' -----------------------
|
||||||
|
|
|
@ -83,7 +83,7 @@ of the failing function and hide the other one:
|
||||||
|
|
||||||
$ pytest
|
$ pytest
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 2 items
|
collected 2 items
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ Running pytest now produces this output:
|
||||||
|
|
||||||
$ pytest test_show_warnings.py
|
$ pytest test_show_warnings.py
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 1 item
|
collected 1 item
|
||||||
|
|
||||||
|
@ -382,8 +382,6 @@ warnings: a WarningsRecorder instance. To view the recorded warnings, you can
|
||||||
iterate over this instance, call ``len`` on it to get the number of recorded
|
iterate over this instance, call ``len`` on it to get the number of recorded
|
||||||
warnings, or index into it to get a particular recorded warning.
|
warnings, or index into it to get a particular recorded warning.
|
||||||
|
|
||||||
.. currentmodule:: _pytest.warnings
|
|
||||||
|
|
||||||
Full API: :class:`~_pytest.recwarn.WarningsRecorder`.
|
Full API: :class:`~_pytest.recwarn.WarningsRecorder`.
|
||||||
|
|
||||||
.. _`warns use cases`:
|
.. _`warns use cases`:
|
||||||
|
|
|
@ -30,7 +30,7 @@ then you can just invoke ``pytest`` directly:
|
||||||
|
|
||||||
$ pytest
|
$ pytest
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 1 item
|
collected 1 item
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ and functions, including from test modules:
|
||||||
|
|
||||||
$ pytest --doctest-modules
|
$ pytest --doctest-modules
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 2 items
|
collected 2 items
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,8 @@ How to use pytest with an existing test suite
|
||||||
==============================================
|
==============================================
|
||||||
|
|
||||||
Pytest can be used with most existing test suites, but its
|
Pytest can be used with most existing test suites, but its
|
||||||
behavior differs from other test runners such as :ref:`nose <noseintegration>` or
|
behavior differs from other test runners such as Python's
|
||||||
Python's default unittest framework.
|
default unittest framework.
|
||||||
|
|
||||||
Before using this section you will want to :ref:`install pytest <getstarted>`.
|
Before using this section you will want to :ref:`install pytest <getstarted>`.
|
||||||
|
|
||||||
|
|
|
@ -433,7 +433,7 @@ marked ``smtp_connection`` fixture function. Running the test looks like this:
|
||||||
|
|
||||||
$ pytest test_module.py
|
$ pytest test_module.py
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 2 items
|
collected 2 items
|
||||||
|
|
||||||
|
@ -494,7 +494,7 @@ Fixtures are created when first requested by a test, and are destroyed based on
|
||||||
* ``function``: the default scope, the fixture is destroyed at the end of the test.
|
* ``function``: the default scope, the fixture is destroyed at the end of the test.
|
||||||
* ``class``: the fixture is destroyed during teardown of the last test in the class.
|
* ``class``: the fixture is destroyed during teardown of the last test in the class.
|
||||||
* ``module``: the fixture is destroyed during teardown of the last test in the module.
|
* ``module``: the fixture is destroyed during teardown of the last test in the module.
|
||||||
* ``package``: the fixture is destroyed during teardown of the last test in the package.
|
* ``package``: the fixture is destroyed during teardown of the last test in the package where the fixture is defined, including sub-packages and sub-directories within it.
|
||||||
* ``session``: the fixture is destroyed at the end of the test session.
|
* ``session``: the fixture is destroyed at the end of the test session.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
@ -771,7 +771,7 @@ For yield fixtures, the first teardown code to run is from the right-most fixtur
|
||||||
|
|
||||||
$ pytest -s test_finalizers.py
|
$ pytest -s test_finalizers.py
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 1 item
|
collected 1 item
|
||||||
|
|
||||||
|
@ -805,7 +805,7 @@ For finalizers, the first fixture to run is last call to `request.addfinalizer`.
|
||||||
|
|
||||||
$ pytest -s test_finalizers.py
|
$ pytest -s test_finalizers.py
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 1 item
|
collected 1 item
|
||||||
|
|
||||||
|
@ -1271,7 +1271,7 @@ configured in multiple ways.
|
||||||
Extending the previous example, we can flag the fixture to create two
|
Extending the previous example, we can flag the fixture to create two
|
||||||
``smtp_connection`` fixture instances which will cause all tests using the fixture
|
``smtp_connection`` fixture instances which will cause all tests using the fixture
|
||||||
to run twice. The fixture function gets access to each parameter
|
to run twice. The fixture function gets access to each parameter
|
||||||
through the special :py:class:`request <FixtureRequest>` object:
|
through the special :py:class:`request <pytest.FixtureRequest>` object:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
@ -1414,10 +1414,11 @@ Running the above tests results in the following test IDs being used:
|
||||||
|
|
||||||
$ pytest --collect-only
|
$ pytest --collect-only
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 12 items
|
collected 12 items
|
||||||
|
|
||||||
|
<Dir fixtures.rst-211>
|
||||||
<Module test_anothersmtp.py>
|
<Module test_anothersmtp.py>
|
||||||
<Function test_showhelo[smtp.gmail.com]>
|
<Function test_showhelo[smtp.gmail.com]>
|
||||||
<Function test_showhelo[mail.python.org]>
|
<Function test_showhelo[mail.python.org]>
|
||||||
|
@ -1468,7 +1469,7 @@ Running this test will *skip* the invocation of ``data_set`` with value ``2``:
|
||||||
|
|
||||||
$ pytest test_fixture_marks.py -v
|
$ pytest test_fixture_marks.py -v
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
||||||
cachedir: .pytest_cache
|
cachedir: .pytest_cache
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collecting ... collected 3 items
|
collecting ... collected 3 items
|
||||||
|
@ -1518,7 +1519,7 @@ Here we declare an ``app`` fixture which receives the previously defined
|
||||||
|
|
||||||
$ pytest -v test_appsetup.py
|
$ pytest -v test_appsetup.py
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
||||||
cachedir: .pytest_cache
|
cachedir: .pytest_cache
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collecting ... collected 2 items
|
collecting ... collected 2 items
|
||||||
|
@ -1598,7 +1599,7 @@ Let's run the tests in verbose mode and with looking at the print-output:
|
||||||
|
|
||||||
$ pytest -v -s test_module.py
|
$ pytest -v -s test_module.py
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
|
||||||
cachedir: .pytest_cache
|
cachedir: .pytest_cache
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collecting ... collected 8 items
|
collecting ... collected 8 items
|
||||||
|
|
|
@ -52,7 +52,6 @@ pytest and other test systems
|
||||||
|
|
||||||
existingtestsuite
|
existingtestsuite
|
||||||
unittest
|
unittest
|
||||||
nose
|
|
||||||
xunit_setup
|
xunit_setup
|
||||||
|
|
||||||
pytest development environment
|
pytest development environment
|
||||||
|
|
|
@ -1,99 +0,0 @@
|
||||||
.. _`noseintegration`:
|
|
||||||
|
|
||||||
How to run tests written for nose
|
|
||||||
=======================================
|
|
||||||
|
|
||||||
``pytest`` has basic support for running tests written for nose_.
|
|
||||||
|
|
||||||
.. warning::
|
|
||||||
This functionality has been deprecated and is likely to be removed in ``pytest 8.x``.
|
|
||||||
|
|
||||||
.. _nosestyle:
|
|
||||||
|
|
||||||
Usage
|
|
||||||
-------------
|
|
||||||
|
|
||||||
After :ref:`installation` type:
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
python setup.py develop # make sure tests can import our package
|
|
||||||
pytest # instead of 'nosetests'
|
|
||||||
|
|
||||||
and you should be able to run your nose style tests and
|
|
||||||
make use of pytest's capabilities.
|
|
||||||
|
|
||||||
Supported nose Idioms
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
* ``setup()`` and ``teardown()`` at module/class/method level: any function or method called ``setup`` will be called during the setup phase for each test, same for ``teardown``.
|
|
||||||
* ``SkipTest`` exceptions and markers
|
|
||||||
* setup/teardown decorators
|
|
||||||
* ``__test__`` attribute on modules/classes/functions
|
|
||||||
* general usage of nose utilities
|
|
||||||
|
|
||||||
Unsupported idioms / known issues
|
|
||||||
----------------------------------
|
|
||||||
|
|
||||||
- unittest-style ``setUp, tearDown, setUpClass, tearDownClass``
|
|
||||||
are recognized only on ``unittest.TestCase`` classes but not
|
|
||||||
on plain classes. ``nose`` supports these methods also on plain
|
|
||||||
classes but pytest deliberately does not. As nose and pytest already
|
|
||||||
both support ``setup_class, teardown_class, setup_method, teardown_method``
|
|
||||||
it doesn't seem useful to duplicate the unittest-API like nose does.
|
|
||||||
If you however rather think pytest should support the unittest-spelling on
|
|
||||||
plain classes please post to :issue:`377`.
|
|
||||||
|
|
||||||
- nose imports test modules with the same import path (e.g.
|
|
||||||
``tests.test_mode``) but different file system paths
|
|
||||||
(e.g. ``tests/test_mode.py`` and ``other/tests/test_mode.py``)
|
|
||||||
by extending sys.path/import semantics. pytest does not do that. Note that
|
|
||||||
`nose2 choose to avoid this sys.path/import hackery <https://nose2.readthedocs.io/en/latest/differences.html#test-discovery-and-loading>`_.
|
|
||||||
|
|
||||||
If you place a conftest.py file in the root directory of your project
|
|
||||||
(as determined by pytest) pytest will run tests "nose style" against
|
|
||||||
the code below that directory by adding it to your ``sys.path`` instead of
|
|
||||||
running against your installed code.
|
|
||||||
|
|
||||||
You may find yourself wanting to do this if you ran ``python setup.py install``
|
|
||||||
to set up your project, as opposed to ``python setup.py develop`` or any of
|
|
||||||
the package manager equivalents. Installing with develop in a
|
|
||||||
virtual environment like tox is recommended over this pattern.
|
|
||||||
|
|
||||||
- nose-style doctests are not collected and executed correctly,
|
|
||||||
also doctest fixtures don't work.
|
|
||||||
|
|
||||||
- no nose-configuration is recognized.
|
|
||||||
|
|
||||||
- ``yield``-based methods are
|
|
||||||
fundamentally incompatible with pytest because they don't support fixtures
|
|
||||||
properly since collection and test execution are separated.
|
|
||||||
|
|
||||||
Here is a table comparing the default supported naming conventions for both
|
|
||||||
nose and pytest.
|
|
||||||
|
|
||||||
========= ========================== ======= =====
|
|
||||||
what default naming convention pytest nose
|
|
||||||
========= ========================== ======= =====
|
|
||||||
module ``test*.py`` ✅
|
|
||||||
module ``test_*.py`` ✅ ✅
|
|
||||||
module ``*_test.py`` ✅
|
|
||||||
module ``*_tests.py``
|
|
||||||
class ``*(unittest.TestCase)`` ✅ ✅
|
|
||||||
method ``test_*`` ✅ ✅
|
|
||||||
class ``Test*`` ✅
|
|
||||||
method ``test_*`` ✅
|
|
||||||
function ``test_*`` ✅
|
|
||||||
========= ========================== ======= =====
|
|
||||||
|
|
||||||
|
|
||||||
Migrating from nose to pytest
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
`nose2pytest <https://github.com/pytest-dev/nose2pytest>`_ is a Python script
|
|
||||||
and pytest plugin to help convert Nose-based tests into pytest-based tests.
|
|
||||||
Specifically, the script transforms ``nose.tools.assert_*`` function calls into
|
|
||||||
raw assert statements, while preserving format of original arguments
|
|
||||||
as much as possible.
|
|
||||||
|
|
||||||
.. _nose: https://nose.readthedocs.io/en/latest/
|
|
|
@ -100,6 +100,7 @@ Executing pytest normally gives us this output (we are skipping the header to fo
|
||||||
fruits2 = ["banana", "apple", "orange", "melon", "kiwi"]
|
fruits2 = ["banana", "apple", "orange", "melon", "kiwi"]
|
||||||
> assert fruits1 == fruits2
|
> assert fruits1 == fruits2
|
||||||
E AssertionError: assert ['banana', 'a...elon', 'kiwi'] == ['banana', 'a...elon', 'kiwi']
|
E AssertionError: assert ['banana', 'a...elon', 'kiwi'] == ['banana', 'a...elon', 'kiwi']
|
||||||
|
E
|
||||||
E At index 2 diff: 'grapes' != 'orange'
|
E At index 2 diff: 'grapes' != 'orange'
|
||||||
E Use -v to get more diff
|
E Use -v to get more diff
|
||||||
|
|
||||||
|
@ -111,6 +112,7 @@ Executing pytest normally gives us this output (we are skipping the header to fo
|
||||||
number_to_text2 = {str(x * 10): x * 10 for x in range(5)}
|
number_to_text2 = {str(x * 10): x * 10 for x in range(5)}
|
||||||
> assert number_to_text1 == number_to_text2
|
> assert number_to_text1 == number_to_text2
|
||||||
E AssertionError: assert {'0': 0, '1':..., '3': 3, ...} == {'0': 0, '10'...'30': 30, ...}
|
E AssertionError: assert {'0': 0, '1':..., '3': 3, ...} == {'0': 0, '10'...'30': 30, ...}
|
||||||
|
E
|
||||||
E Omitting 1 identical items, use -vv to show
|
E Omitting 1 identical items, use -vv to show
|
||||||
E Left contains 4 more items:
|
E Left contains 4 more items:
|
||||||
E {'1': 1, '2': 2, '3': 3, '4': 4}
|
E {'1': 1, '2': 2, '3': 3, '4': 4}
|
||||||
|
@ -162,12 +164,15 @@ Now we can increase pytest's verbosity:
|
||||||
fruits2 = ["banana", "apple", "orange", "melon", "kiwi"]
|
fruits2 = ["banana", "apple", "orange", "melon", "kiwi"]
|
||||||
> assert fruits1 == fruits2
|
> assert fruits1 == fruits2
|
||||||
E AssertionError: assert ['banana', 'a...elon', 'kiwi'] == ['banana', 'a...elon', 'kiwi']
|
E AssertionError: assert ['banana', 'a...elon', 'kiwi'] == ['banana', 'a...elon', 'kiwi']
|
||||||
|
E
|
||||||
E At index 2 diff: 'grapes' != 'orange'
|
E At index 2 diff: 'grapes' != 'orange'
|
||||||
|
E
|
||||||
E Full diff:
|
E Full diff:
|
||||||
E - ['banana', 'apple', 'orange', 'melon', 'kiwi']
|
E [
|
||||||
E ? ^ ^^
|
E 'banana',
|
||||||
E + ['banana', 'apple', 'grapes', 'melon', 'kiwi']
|
E 'apple',...
|
||||||
E ? ^ ^ +
|
E
|
||||||
|
E ...Full output truncated (7 lines hidden), use '-vv' to show
|
||||||
|
|
||||||
test_verbosity_example.py:8: AssertionError
|
test_verbosity_example.py:8: AssertionError
|
||||||
____________________________ test_numbers_fail _____________________________
|
____________________________ test_numbers_fail _____________________________
|
||||||
|
@ -177,15 +182,15 @@ Now we can increase pytest's verbosity:
|
||||||
number_to_text2 = {str(x * 10): x * 10 for x in range(5)}
|
number_to_text2 = {str(x * 10): x * 10 for x in range(5)}
|
||||||
> assert number_to_text1 == number_to_text2
|
> assert number_to_text1 == number_to_text2
|
||||||
E AssertionError: assert {'0': 0, '1':..., '3': 3, ...} == {'0': 0, '10'...'30': 30, ...}
|
E AssertionError: assert {'0': 0, '1':..., '3': 3, ...} == {'0': 0, '10'...'30': 30, ...}
|
||||||
|
E
|
||||||
E Omitting 1 identical items, use -vv to show
|
E Omitting 1 identical items, use -vv to show
|
||||||
E Left contains 4 more items:
|
E Left contains 4 more items:
|
||||||
E {'1': 1, '2': 2, '3': 3, '4': 4}
|
E {'1': 1, '2': 2, '3': 3, '4': 4}
|
||||||
E Right contains 4 more items:
|
E Right contains 4 more items:
|
||||||
E {'10': 10, '20': 20, '30': 30, '40': 40}
|
E {'10': 10, '20': 20, '30': 30, '40': 40}
|
||||||
E Full diff:
|
E ...
|
||||||
E - {'0': 0, '10': 10, '20': 20, '30': 30, '40': 40}
|
E
|
||||||
E ? - - - - - - - -
|
E ...Full output truncated (16 lines hidden), use '-vv' to show
|
||||||
E + {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4}
|
|
||||||
|
|
||||||
test_verbosity_example.py:14: AssertionError
|
test_verbosity_example.py:14: AssertionError
|
||||||
___________________________ test_long_text_fail ____________________________
|
___________________________ test_long_text_fail ____________________________
|
||||||
|
@ -231,12 +236,20 @@ Now if we increase verbosity even more:
|
||||||
fruits2 = ["banana", "apple", "orange", "melon", "kiwi"]
|
fruits2 = ["banana", "apple", "orange", "melon", "kiwi"]
|
||||||
> assert fruits1 == fruits2
|
> assert fruits1 == fruits2
|
||||||
E AssertionError: assert ['banana', 'apple', 'grapes', 'melon', 'kiwi'] == ['banana', 'apple', 'orange', 'melon', 'kiwi']
|
E AssertionError: assert ['banana', 'apple', 'grapes', 'melon', 'kiwi'] == ['banana', 'apple', 'orange', 'melon', 'kiwi']
|
||||||
|
E
|
||||||
E At index 2 diff: 'grapes' != 'orange'
|
E At index 2 diff: 'grapes' != 'orange'
|
||||||
|
E
|
||||||
E Full diff:
|
E Full diff:
|
||||||
E - ['banana', 'apple', 'orange', 'melon', 'kiwi']
|
E [
|
||||||
|
E 'banana',
|
||||||
|
E 'apple',
|
||||||
|
E - 'orange',
|
||||||
E ? ^ ^^
|
E ? ^ ^^
|
||||||
E + ['banana', 'apple', 'grapes', 'melon', 'kiwi']
|
E + 'grapes',
|
||||||
E ? ^ ^ +
|
E ? ^ ^ +
|
||||||
|
E 'melon',
|
||||||
|
E 'kiwi',
|
||||||
|
E ]
|
||||||
|
|
||||||
test_verbosity_example.py:8: AssertionError
|
test_verbosity_example.py:8: AssertionError
|
||||||
____________________________ test_numbers_fail _____________________________
|
____________________________ test_numbers_fail _____________________________
|
||||||
|
@ -246,16 +259,30 @@ Now if we increase verbosity even more:
|
||||||
number_to_text2 = {str(x * 10): x * 10 for x in range(5)}
|
number_to_text2 = {str(x * 10): x * 10 for x in range(5)}
|
||||||
> assert number_to_text1 == number_to_text2
|
> assert number_to_text1 == number_to_text2
|
||||||
E AssertionError: assert {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4} == {'0': 0, '10': 10, '20': 20, '30': 30, '40': 40}
|
E AssertionError: assert {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4} == {'0': 0, '10': 10, '20': 20, '30': 30, '40': 40}
|
||||||
|
E
|
||||||
E Common items:
|
E Common items:
|
||||||
E {'0': 0}
|
E {'0': 0}
|
||||||
E Left contains 4 more items:
|
E Left contains 4 more items:
|
||||||
E {'1': 1, '2': 2, '3': 3, '4': 4}
|
E {'1': 1, '2': 2, '3': 3, '4': 4}
|
||||||
E Right contains 4 more items:
|
E Right contains 4 more items:
|
||||||
E {'10': 10, '20': 20, '30': 30, '40': 40}
|
E {'10': 10, '20': 20, '30': 30, '40': 40}
|
||||||
|
E
|
||||||
E Full diff:
|
E Full diff:
|
||||||
E - {'0': 0, '10': 10, '20': 20, '30': 30, '40': 40}
|
E {
|
||||||
E ? - - - - - - - -
|
E '0': 0,
|
||||||
E + {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4}
|
E - '10': 10,
|
||||||
|
E ? - -
|
||||||
|
E + '1': 1,
|
||||||
|
E - '20': 20,
|
||||||
|
E ? - -
|
||||||
|
E + '2': 2,
|
||||||
|
E - '30': 30,
|
||||||
|
E ? - -
|
||||||
|
E + '3': 3,
|
||||||
|
E - '40': 40,
|
||||||
|
E ? - -
|
||||||
|
E + '4': 4,
|
||||||
|
E }
|
||||||
|
|
||||||
test_verbosity_example.py:14: AssertionError
|
test_verbosity_example.py:14: AssertionError
|
||||||
___________________________ test_long_text_fail ____________________________
|
___________________________ test_long_text_fail ____________________________
|
||||||
|
@ -354,7 +381,7 @@ Example:
|
||||||
|
|
||||||
$ pytest -ra
|
$ pytest -ra
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 6 items
|
collected 6 items
|
||||||
|
|
||||||
|
@ -377,10 +404,19 @@ Example:
|
||||||
E assert 0
|
E assert 0
|
||||||
|
|
||||||
test_example.py:14: AssertionError
|
test_example.py:14: AssertionError
|
||||||
|
================================ XFAILURES =================================
|
||||||
|
________________________________ test_xfail ________________________________
|
||||||
|
|
||||||
|
def test_xfail():
|
||||||
|
> pytest.xfail("xfailing this test")
|
||||||
|
E _pytest.outcomes.XFailed: xfailing this test
|
||||||
|
|
||||||
|
test_example.py:26: XFailed
|
||||||
|
================================= XPASSES ==================================
|
||||||
========================= short test summary info ==========================
|
========================= short test summary info ==========================
|
||||||
SKIPPED [1] test_example.py:22: skipping this test
|
SKIPPED [1] test_example.py:22: skipping this test
|
||||||
XFAIL test_example.py::test_xfail - reason: xfailing this test
|
XFAIL test_example.py::test_xfail - reason: xfailing this test
|
||||||
XPASS test_example.py::test_xpass always xfail
|
XPASS test_example.py::test_xpass - always xfail
|
||||||
ERROR test_example.py::test_error - assert 0
|
ERROR test_example.py::test_error - assert 0
|
||||||
FAILED test_example.py::test_fail - assert 0
|
FAILED test_example.py::test_fail - assert 0
|
||||||
== 1 failed, 1 passed, 1 skipped, 1 xfailed, 1 xpassed, 1 error in 0.12s ===
|
== 1 failed, 1 passed, 1 skipped, 1 xfailed, 1 xpassed, 1 error in 0.12s ===
|
||||||
|
@ -410,7 +446,7 @@ More than one character can be used, so for example to only see failed and skipp
|
||||||
|
|
||||||
$ pytest -rfs
|
$ pytest -rfs
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 6 items
|
collected 6 items
|
||||||
|
|
||||||
|
@ -445,7 +481,7 @@ captured output:
|
||||||
|
|
||||||
$ pytest -rpP
|
$ pytest -rpP
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 6 items
|
collected 6 items
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ them in turn:
|
||||||
|
|
||||||
$ pytest
|
$ pytest
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 3 items
|
collected 3 items
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ Let's run this:
|
||||||
|
|
||||||
$ pytest
|
$ pytest
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 3 items
|
collected 3 items
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,8 @@ How to use temporary directories and files in tests
|
||||||
The ``tmp_path`` fixture
|
The ``tmp_path`` fixture
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
You can use the ``tmp_path`` fixture which will
|
You can use the ``tmp_path`` fixture which will provide a temporary directory
|
||||||
provide a temporary directory unique to the test invocation,
|
unique to each test function.
|
||||||
created in the `base temporary directory`_.
|
|
||||||
|
|
||||||
``tmp_path`` is a :class:`pathlib.Path` object. Here is an example test usage:
|
``tmp_path`` is a :class:`pathlib.Path` object. Here is an example test usage:
|
||||||
|
|
||||||
|
@ -36,7 +35,7 @@ Running this would result in a passed test except for the last
|
||||||
|
|
||||||
$ pytest test_tmp_path.py
|
$ pytest test_tmp_path.py
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 1 item
|
collected 1 item
|
||||||
|
|
||||||
|
@ -62,6 +61,11 @@ Running this would result in a passed test except for the last
|
||||||
FAILED test_tmp_path.py::test_create_file - assert 0
|
FAILED test_tmp_path.py::test_create_file - assert 0
|
||||||
============================ 1 failed in 0.12s =============================
|
============================ 1 failed in 0.12s =============================
|
||||||
|
|
||||||
|
By default, ``pytest`` retains the temporary directory for the last 3 ``pytest``
|
||||||
|
invocations. Concurrent invocations of the same test function are supported by
|
||||||
|
configuring the base temporary directory to be unique for each concurrent
|
||||||
|
run. See `temporary directory location and retention`_ for details.
|
||||||
|
|
||||||
.. _`tmp_path_factory example`:
|
.. _`tmp_path_factory example`:
|
||||||
|
|
||||||
The ``tmp_path_factory`` fixture
|
The ``tmp_path_factory`` fixture
|
||||||
|
@ -100,7 +104,7 @@ See :ref:`tmp_path_factory API <tmp_path_factory factory api>` for details.
|
||||||
.. _tmpdir:
|
.. _tmpdir:
|
||||||
|
|
||||||
The ``tmpdir`` and ``tmpdir_factory`` fixtures
|
The ``tmpdir`` and ``tmpdir_factory`` fixtures
|
||||||
---------------------------------------------------
|
----------------------------------------------
|
||||||
|
|
||||||
The ``tmpdir`` and ``tmpdir_factory`` fixtures are similar to ``tmp_path``
|
The ``tmpdir`` and ``tmpdir_factory`` fixtures are similar to ``tmp_path``
|
||||||
and ``tmp_path_factory``, but use/return legacy `py.path.local`_ objects
|
and ``tmp_path_factory``, but use/return legacy `py.path.local`_ objects
|
||||||
|
@ -124,10 +128,10 @@ See :fixture:`tmpdir <tmpdir>` :fixture:`tmpdir_factory <tmpdir_factory>`
|
||||||
API for details.
|
API for details.
|
||||||
|
|
||||||
|
|
||||||
.. _`base temporary directory`:
|
.. _`temporary directory location and retention`:
|
||||||
|
|
||||||
The default base temporary directory
|
Temporary directory location and retention
|
||||||
-----------------------------------------------
|
------------------------------------------
|
||||||
|
|
||||||
Temporary directories are by default created as sub-directories of
|
Temporary directories are by default created as sub-directories of
|
||||||
the system temporary directory. The base name will be ``pytest-NUM`` where
|
the system temporary directory. The base name will be ``pytest-NUM`` where
|
||||||
|
@ -152,7 +156,7 @@ You can override the default temporary directory setting like this:
|
||||||
for that purpose only.
|
for that purpose only.
|
||||||
|
|
||||||
When distributing tests on the local machine using ``pytest-xdist``, care is taken to
|
When distributing tests on the local machine using ``pytest-xdist``, care is taken to
|
||||||
automatically configure a basetemp directory for the sub processes such that all temporary
|
automatically configure a `basetemp` directory for the sub processes such that all temporary
|
||||||
data lands below a single per-test run basetemp directory.
|
data lands below a single per-test run temporary directory.
|
||||||
|
|
||||||
.. _`py.path.local`: https://py.readthedocs.io/en/latest/path.html
|
.. _`py.path.local`: https://py.readthedocs.io/en/latest/path.html
|
||||||
|
|
|
@ -140,7 +140,7 @@ the ``self.db`` values in the traceback:
|
||||||
|
|
||||||
$ pytest test_unittest_db.py
|
$ pytest test_unittest_db.py
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 2 items
|
collected 2 items
|
||||||
|
|
||||||
|
|
|
@ -59,10 +59,6 @@ The remaining hook functions will not be called in this case.
|
||||||
hook wrappers: executing around other hooks
|
hook wrappers: executing around other hooks
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
|
|
||||||
.. currentmodule:: _pytest.core
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pytest plugins can implement hook wrappers which wrap the execution
|
pytest plugins can implement hook wrappers which wrap the execution
|
||||||
of other hook implementations. A hook wrapper is a generator function
|
of other hook implementations. A hook wrapper is a generator function
|
||||||
which yields exactly once. When pytest invokes hooks it first executes
|
which yields exactly once. When pytest invokes hooks it first executes
|
||||||
|
@ -165,6 +161,7 @@ Here is the order of execution:
|
||||||
It's possible to use ``tryfirst`` and ``trylast`` also on hook wrappers
|
It's possible to use ``tryfirst`` and ``trylast`` also on hook wrappers
|
||||||
in which case it will influence the ordering of hook wrappers among each other.
|
in which case it will influence the ordering of hook wrappers among each other.
|
||||||
|
|
||||||
|
.. _`declaringhooks`:
|
||||||
|
|
||||||
Declaring new hooks
|
Declaring new hooks
|
||||||
------------------------
|
------------------------
|
||||||
|
@ -174,13 +171,11 @@ Declaring new hooks
|
||||||
This is a quick overview on how to add new hooks and how they work in general, but a more complete
|
This is a quick overview on how to add new hooks and how they work in general, but a more complete
|
||||||
overview can be found in `the pluggy documentation <https://pluggy.readthedocs.io/en/latest/>`__.
|
overview can be found in `the pluggy documentation <https://pluggy.readthedocs.io/en/latest/>`__.
|
||||||
|
|
||||||
.. currentmodule:: _pytest.hookspec
|
|
||||||
|
|
||||||
Plugins and ``conftest.py`` files may declare new hooks that can then be
|
Plugins and ``conftest.py`` files may declare new hooks that can then be
|
||||||
implemented by other plugins in order to alter behaviour or interact with
|
implemented by other plugins in order to alter behaviour or interact with
|
||||||
the new plugin:
|
the new plugin:
|
||||||
|
|
||||||
.. autofunction:: pytest_addhooks
|
.. autofunction:: _pytest.hookspec.pytest_addhooks
|
||||||
:noindex:
|
:noindex:
|
||||||
|
|
||||||
Hooks are usually declared as do-nothing functions that contain only
|
Hooks are usually declared as do-nothing functions that contain only
|
||||||
|
|
|
@ -46,24 +46,18 @@ Plugin discovery order at tool startup
|
||||||
|
|
||||||
5. by loading all plugins specified through the :envvar:`PYTEST_PLUGINS` environment variable.
|
5. by loading all plugins specified through the :envvar:`PYTEST_PLUGINS` environment variable.
|
||||||
|
|
||||||
6. by loading all :file:`conftest.py` files as inferred by the command line
|
6. by loading all "initial ":file:`conftest.py` files:
|
||||||
invocation:
|
|
||||||
|
|
||||||
- if no test paths are specified, use the current dir as a test path
|
- determine the test paths: specified on the command line, otherwise in
|
||||||
- if exists, load ``conftest.py`` and ``test*/conftest.py`` relative
|
:confval:`testpaths` if defined and running from the rootdir, otherwise the
|
||||||
to the directory part of the first test path. After the ``conftest.py``
|
current dir
|
||||||
file is loaded, load all plugins specified in its
|
- for each test path, load ``conftest.py`` and ``test*/conftest.py`` relative
|
||||||
:globalvar:`pytest_plugins` variable if present.
|
to the directory part of the test path, if exist. Before a ``conftest.py``
|
||||||
|
file is loaded, load ``conftest.py`` files in all of its parent directories.
|
||||||
Note that pytest does not find ``conftest.py`` files in deeper nested
|
After a ``conftest.py`` file is loaded, recursively load all plugins specified
|
||||||
sub directories at tool startup. It is usually a good idea to keep
|
in its :globalvar:`pytest_plugins` variable if present.
|
||||||
your ``conftest.py`` file in the top level test or project root directory.
|
|
||||||
|
|
||||||
7. by recursively loading all plugins specified by the
|
|
||||||
:globalvar:`pytest_plugins` variable in ``conftest.py`` files.
|
|
||||||
|
|
||||||
|
|
||||||
.. _`pytest/plugin`: http://bitbucket.org/pytest-dev/pytest/src/tip/pytest/plugin/
|
|
||||||
.. _`conftest.py plugins`:
|
.. _`conftest.py plugins`:
|
||||||
.. _`localplugin`:
|
.. _`localplugin`:
|
||||||
.. _`local conftest plugins`:
|
.. _`local conftest plugins`:
|
||||||
|
@ -108,9 +102,9 @@ Here is how you might run it::
|
||||||
See also: :ref:`pythonpath`.
|
See also: :ref:`pythonpath`.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
Some hooks should be implemented only in plugins or conftest.py files situated at the
|
Some hooks cannot be implemented in conftest.py files which are not
|
||||||
tests root directory due to how pytest discovers plugins during startup,
|
:ref:`initial <pluginorder>` due to how pytest discovers plugins during
|
||||||
see the documentation of each hook for details.
|
startup. See the documentation of each hook for details.
|
||||||
|
|
||||||
Writing your own plugin
|
Writing your own plugin
|
||||||
-----------------------
|
-----------------------
|
||||||
|
@ -448,7 +442,7 @@ in our ``pytest.ini`` to tell pytest where to look for example files.
|
||||||
|
|
||||||
$ pytest
|
$ pytest
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
configfile: pytest.ini
|
configfile: pytest.ini
|
||||||
collected 2 items
|
collected 2 items
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
:orphan:
|
:orphan:
|
||||||
|
|
||||||
.. sidebar:: Next Open Trainings
|
.. sidebar:: Next Open Trainings and Events
|
||||||
|
|
||||||
- `Professional Testing with Python <https://python-academy.com/courses/python_course_testing.html>`_, via `Python Academy <https://www.python-academy.com/>`_, **March 5th to 7th 2024** (3 day in-depth training), **Leipzig, Germany / Remote**
|
- `Professional Testing with Python <https://python-academy.com/courses/python_course_testing.html>`_, via `Python Academy <https://www.python-academy.com/>`_ (3 day in-depth training):
|
||||||
|
* **June 11th to 13th 2024**, Remote
|
||||||
|
* **March 4th to 6th 2025**, Leipzig, Germany / Remote
|
||||||
|
- `pytest development sprint <https://github.com/pytest-dev/pytest/discussions/11655>`_, June 2024 (`date poll <https://nuudel.digitalcourage.de/2tEsEpRcwMNcAXVO>`_)
|
||||||
|
|
||||||
Also see :doc:`previous talks and blogposts <talks>`.
|
Also see :doc:`previous talks and blogposts <talks>`.
|
||||||
|
|
||||||
|
@ -42,7 +45,7 @@ To execute it:
|
||||||
|
|
||||||
$ pytest
|
$ pytest
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
|
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
|
||||||
rootdir: /home/sweet/project
|
rootdir: /home/sweet/project
|
||||||
collected 1 item
|
collected 1 item
|
||||||
|
|
||||||
|
@ -74,7 +77,7 @@ Features
|
||||||
|
|
||||||
- :ref:`Modular fixtures <fixture>` for managing small or parametrized long-lived test resources
|
- :ref:`Modular fixtures <fixture>` for managing small or parametrized long-lived test resources
|
||||||
|
|
||||||
- Can run :ref:`unittest <unittest>` (including trial) and :ref:`nose <noseintegration>` test suites out of the box
|
- Can run :ref:`unittest <unittest>` (including trial) test suites out of the box
|
||||||
|
|
||||||
- Python 3.8+ or PyPy 3
|
- Python 3.8+ or PyPy 3
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,6 @@ Fixtures reference
|
||||||
.. seealso:: :ref:`about-fixtures`
|
.. seealso:: :ref:`about-fixtures`
|
||||||
.. seealso:: :ref:`how-to-fixtures`
|
.. seealso:: :ref:`how-to-fixtures`
|
||||||
|
|
||||||
|
|
||||||
.. currentmodule:: _pytest.python
|
|
||||||
|
|
||||||
.. _`Dependency injection`: https://en.wikipedia.org/wiki/Dependency_injection
|
.. _`Dependency injection`: https://en.wikipedia.org/wiki/Dependency_injection
|
||||||
|
|
||||||
|
|
||||||
|
@ -76,15 +73,13 @@ Built-in fixtures
|
||||||
:class:`pathlib.Path` objects.
|
:class:`pathlib.Path` objects.
|
||||||
|
|
||||||
:fixture:`tmpdir`
|
:fixture:`tmpdir`
|
||||||
Provide a :class:`py.path.local` object to a temporary
|
Provide a `py.path.local <https://py.readthedocs.io/en/latest/path.html>`_ object to a temporary
|
||||||
directory which is unique to each test function;
|
directory which is unique to each test function;
|
||||||
replaced by :fixture:`tmp_path`.
|
replaced by :fixture:`tmp_path`.
|
||||||
|
|
||||||
.. _`py.path.local`: https://py.readthedocs.io/en/latest/path.html
|
|
||||||
|
|
||||||
:fixture:`tmpdir_factory`
|
:fixture:`tmpdir_factory`
|
||||||
Make session-scoped temporary directories and return
|
Make session-scoped temporary directories and return
|
||||||
:class:`py.path.local` objects;
|
``py.path.local`` objects;
|
||||||
replaced by :fixture:`tmp_path_factory`.
|
replaced by :fixture:`tmp_path_factory`.
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,7 +93,7 @@ Fixture availability is determined from the perspective of the test. A fixture
|
||||||
is only available for tests to request if they are in the scope that fixture is
|
is only available for tests to request if they are in the scope that fixture is
|
||||||
defined in. If a fixture is defined inside a class, it can only be requested by
|
defined in. If a fixture is defined inside a class, it can only be requested by
|
||||||
tests inside that class. But if a fixture is defined inside the global scope of
|
tests inside that class. But if a fixture is defined inside the global scope of
|
||||||
the module, than every test in that module, even if it's defined inside a class,
|
the module, then every test in that module, even if it's defined inside a class,
|
||||||
can request it.
|
can request it.
|
||||||
|
|
||||||
Similarly, a test can also only be affected by an autouse fixture if that test
|
Similarly, a test can also only be affected by an autouse fixture if that test
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -79,7 +79,7 @@ pytest.xfail
|
||||||
pytest.exit
|
pytest.exit
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
.. autofunction:: pytest.exit(reason, [returncode=False, msg=None])
|
.. autofunction:: pytest.exit(reason, [returncode=None, msg=None])
|
||||||
|
|
||||||
pytest.main
|
pytest.main
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
@ -612,10 +612,30 @@ Hooks
|
||||||
|
|
||||||
**Tutorial**: :ref:`writing-plugins`
|
**Tutorial**: :ref:`writing-plugins`
|
||||||
|
|
||||||
.. currentmodule:: _pytest.hookspec
|
|
||||||
|
|
||||||
Reference to all hooks which can be implemented by :ref:`conftest.py files <localplugin>` and :ref:`plugins <plugins>`.
|
Reference to all hooks which can be implemented by :ref:`conftest.py files <localplugin>` and :ref:`plugins <plugins>`.
|
||||||
|
|
||||||
|
@pytest.hookimpl
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. function:: pytest.hookimpl
|
||||||
|
:decorator:
|
||||||
|
|
||||||
|
pytest's decorator for marking functions as hook implementations.
|
||||||
|
|
||||||
|
See :ref:`writinghooks` and :func:`pluggy.HookimplMarker`.
|
||||||
|
|
||||||
|
@pytest.hookspec
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. function:: pytest.hookspec
|
||||||
|
:decorator:
|
||||||
|
|
||||||
|
pytest's decorator for marking functions as hook specifications.
|
||||||
|
|
||||||
|
See :ref:`declaringhooks` and :func:`pluggy.HookspecMarker`.
|
||||||
|
|
||||||
|
.. currentmodule:: _pytest.hookspec
|
||||||
|
|
||||||
Bootstrapping hooks
|
Bootstrapping hooks
|
||||||
~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -623,8 +643,6 @@ Bootstrapping hooks called for plugins registered early enough (internal and set
|
||||||
|
|
||||||
.. hook:: pytest_load_initial_conftests
|
.. hook:: pytest_load_initial_conftests
|
||||||
.. autofunction:: pytest_load_initial_conftests
|
.. autofunction:: pytest_load_initial_conftests
|
||||||
.. hook:: pytest_cmdline_preparse
|
|
||||||
.. autofunction:: pytest_cmdline_preparse
|
|
||||||
.. hook:: pytest_cmdline_parse
|
.. hook:: pytest_cmdline_parse
|
||||||
.. autofunction:: pytest_cmdline_parse
|
.. autofunction:: pytest_cmdline_parse
|
||||||
.. hook:: pytest_cmdline_main
|
.. hook:: pytest_cmdline_main
|
||||||
|
@ -662,6 +680,8 @@ Collection hooks
|
||||||
.. autofunction:: pytest_collection
|
.. autofunction:: pytest_collection
|
||||||
.. hook:: pytest_ignore_collect
|
.. hook:: pytest_ignore_collect
|
||||||
.. autofunction:: pytest_ignore_collect
|
.. autofunction:: pytest_ignore_collect
|
||||||
|
.. hook:: pytest_collect_directory
|
||||||
|
.. autofunction:: pytest_collect_directory
|
||||||
.. hook:: pytest_collect_file
|
.. hook:: pytest_collect_file
|
||||||
.. autofunction:: pytest_collect_file
|
.. autofunction:: pytest_collect_file
|
||||||
.. hook:: pytest_pycollect_makemodule
|
.. hook:: pytest_pycollect_makemodule
|
||||||
|
@ -801,6 +821,7 @@ Node
|
||||||
|
|
||||||
.. autoclass:: _pytest.nodes.Node()
|
.. autoclass:: _pytest.nodes.Node()
|
||||||
:members:
|
:members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
Collector
|
Collector
|
||||||
~~~~~~~~~
|
~~~~~~~~~
|
||||||
|
@ -900,6 +921,18 @@ Config
|
||||||
.. autoclass:: pytest.Config()
|
.. autoclass:: pytest.Config()
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
Dir
|
||||||
|
~~~
|
||||||
|
|
||||||
|
.. autoclass:: pytest.Dir()
|
||||||
|
:members:
|
||||||
|
|
||||||
|
Directory
|
||||||
|
~~~~~~~~~
|
||||||
|
|
||||||
|
.. autoclass:: pytest.Directory()
|
||||||
|
:members:
|
||||||
|
|
||||||
ExceptionInfo
|
ExceptionInfo
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -1125,19 +1158,22 @@ When set to ``0``, pytest will not use color.
|
||||||
|
|
||||||
.. envvar:: NO_COLOR
|
.. envvar:: NO_COLOR
|
||||||
|
|
||||||
When set (regardless of value), pytest will not use color in terminal output.
|
When set to a non-empty string (regardless of value), pytest will not use color in terminal output.
|
||||||
``PY_COLORS`` takes precedence over ``NO_COLOR``, which takes precedence over ``FORCE_COLOR``.
|
``PY_COLORS`` takes precedence over ``NO_COLOR``, which takes precedence over ``FORCE_COLOR``.
|
||||||
See `no-color.org <https://no-color.org/>`__ for other libraries supporting this community standard.
|
See `no-color.org <https://no-color.org/>`__ for other libraries supporting this community standard.
|
||||||
|
|
||||||
.. envvar:: FORCE_COLOR
|
.. envvar:: FORCE_COLOR
|
||||||
|
|
||||||
When set (regardless of value), pytest will use color in terminal output.
|
When set to a non-empty string (regardless of value), pytest will use color in terminal output.
|
||||||
``PY_COLORS`` and ``NO_COLOR`` take precedence over ``FORCE_COLOR``.
|
``PY_COLORS`` and ``NO_COLOR`` take precedence over ``FORCE_COLOR``.
|
||||||
|
|
||||||
Exceptions
|
Exceptions
|
||||||
----------
|
----------
|
||||||
|
|
||||||
.. autoclass:: pytest.UsageError()
|
.. autoexception:: pytest.UsageError()
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
.. autoexception:: pytest.FixtureLookupError()
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
.. _`warnings ref`:
|
.. _`warnings ref`:
|
||||||
|
@ -1171,9 +1207,6 @@ Custom warnings generated in some situations such as improper usage or deprecate
|
||||||
.. autoclass:: pytest.PytestReturnNotNoneWarning
|
.. autoclass:: pytest.PytestReturnNotNoneWarning
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
.. autoclass:: pytest.PytestRemovedIn8Warning
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
.. autoclass:: pytest.PytestRemovedIn9Warning
|
.. autoclass:: pytest.PytestRemovedIn9Warning
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
@ -2062,7 +2095,7 @@ All the command-line flags can be obtained by running ``pytest --help``::
|
||||||
|
|
||||||
[pytest] ini-options in the first pytest.ini|tox.ini|setup.cfg|pyproject.toml file found:
|
[pytest] ini-options in the first pytest.ini|tox.ini|setup.cfg|pyproject.toml file found:
|
||||||
|
|
||||||
markers (linelist): Markers for test functions
|
markers (linelist): Register new markers for test functions
|
||||||
empty_parameter_set_mark (string):
|
empty_parameter_set_mark (string):
|
||||||
Default marker for empty parametersets
|
Default marker for empty parametersets
|
||||||
norecursedirs (args): Directory patterns to avoid for recursion
|
norecursedirs (args): Directory patterns to avoid for recursion
|
||||||
|
@ -2103,6 +2136,10 @@ All the command-line flags can be obtained by running ``pytest --help``::
|
||||||
enable_assertion_pass_hook (bool):
|
enable_assertion_pass_hook (bool):
|
||||||
Enables the pytest_assertion_pass hook. Make sure to
|
Enables the pytest_assertion_pass hook. Make sure to
|
||||||
delete any previously generated pyc cache files.
|
delete any previously generated pyc cache files.
|
||||||
|
verbosity_assertions (string):
|
||||||
|
Specify a verbosity level for assertions, overriding
|
||||||
|
the main level. Higher levels will provide more
|
||||||
|
detailed explanation when an assertion fails.
|
||||||
junit_suite_name (string):
|
junit_suite_name (string):
|
||||||
Test suite name for JUnit report
|
Test suite name for JUnit report
|
||||||
junit_logging (string):
|
junit_logging (string):
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue