From f4b0fd2294a0b2f89bf308d513d574e1e2e01ad5 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Wed, 5 Nov 2025 07:54:08 +0000 Subject: [PATCH 01/74] Prepare release version 9.0.0 --- changelog/12083.breaking.rst | 9 - changelog/12244.contrib.rst | 1 - changelog/12474.contrib.rst | 1 - changelog/13072.feature.rst | 8 - changelog/13330.improvement.rst | 3 - changelog/13445.bugfix.rst | 1 - changelog/13522.bugfix.rst | 5 - changelog/13537.bugfix.rst | 1 - changelog/13574.improvement.rst | 7 - changelog/13598.bugfix.rst | 1 - changelog/13621.contrib.rst | 1 - changelog/13625.doc.rst | 1 - changelog/13638.contrib.rst | 2 - changelog/1367.feature.rst | 28 --- changelog/13678.feature.rst | 3 - changelog/13695.contrib.rst | 1 - changelog/13700.improvement.rst | 1 - changelog/13716.bugfix.rst | 1 - changelog/13719.breaking.rst | 1 - changelog/13722.bugfix.rst | 1 - changelog/13732.improvement.rst | 1 - changelog/13737.feature.rst | 4 - changelog/13743.feature.rst | 37 ---- changelog/13766.breaking.rst | 2 - changelog/13771.contrib.rst | 1 - changelog/13773.bugfix.rst | 1 - changelog/13779.breaking.rst | 22 -- changelog/13791.packaging.rst | 2 - changelog/13807.deprecation.rst | 3 - changelog/13816.bugfix.rst | 1 - changelog/13823.feature.rst | 18 -- changelog/13823.improvement.rst | 4 - changelog/13829.feature.rst | 5 - changelog/13830.misc.rst | 1 - changelog/13841.contrib.rst | 1 - changelog/13849.bugfix.rst | 2 - changelog/13859.improvement.rst | 1 - changelog/13861.improvement.rst | 1 - changelog/13865.bugfix.rst | 1 - changelog/478.feature.rst | 3 - doc/en/announce/index.rst | 1 + doc/en/announce/release-9.0.0.rst | 69 +++++++ doc/en/builtin.rst | 11 +- doc/en/changelog.rst | 301 ++++++++++++++++++++++++++++ doc/en/example/markers.rst | 4 +- doc/en/example/nonpython.rst | 4 +- doc/en/example/parametrize.rst | 14 +- doc/en/example/pythoncollection.rst | 10 +- doc/en/example/simple.rst | 4 +- doc/en/getting-started.rst | 2 +- doc/en/how-to/fixtures.rst | 2 +- doc/en/how-to/subtests.rst | 32 ++- doc/en/how-to/writing_plugins.rst | 2 +- doc/en/reference/reference.rst | 38 +++- doc/en/requirements.txt | 2 +- 55 files changed, 459 insertions(+), 225 deletions(-) delete mode 100644 changelog/12083.breaking.rst delete mode 100644 changelog/12244.contrib.rst delete mode 100644 changelog/12474.contrib.rst delete mode 100644 changelog/13072.feature.rst delete mode 100644 changelog/13330.improvement.rst delete mode 100644 changelog/13445.bugfix.rst delete mode 100644 changelog/13522.bugfix.rst delete mode 100644 changelog/13537.bugfix.rst delete mode 100644 changelog/13574.improvement.rst delete mode 100644 changelog/13598.bugfix.rst delete mode 100644 changelog/13621.contrib.rst delete mode 100644 changelog/13625.doc.rst delete mode 100644 changelog/13638.contrib.rst delete mode 100644 changelog/1367.feature.rst delete mode 100644 changelog/13678.feature.rst delete mode 100644 changelog/13695.contrib.rst delete mode 100644 changelog/13700.improvement.rst delete mode 100644 changelog/13716.bugfix.rst delete mode 100644 changelog/13719.breaking.rst delete mode 100644 changelog/13722.bugfix.rst delete mode 100644 changelog/13732.improvement.rst delete mode 100644 changelog/13737.feature.rst delete mode 100644 changelog/13743.feature.rst delete mode 100644 changelog/13766.breaking.rst delete mode 100644 changelog/13771.contrib.rst delete mode 100644 changelog/13773.bugfix.rst delete mode 100644 changelog/13779.breaking.rst delete mode 100644 changelog/13791.packaging.rst delete mode 100644 changelog/13807.deprecation.rst delete mode 100644 changelog/13816.bugfix.rst delete mode 100644 changelog/13823.feature.rst delete mode 100644 changelog/13823.improvement.rst delete mode 100644 changelog/13829.feature.rst delete mode 100644 changelog/13830.misc.rst delete mode 100644 changelog/13841.contrib.rst delete mode 100644 changelog/13849.bugfix.rst delete mode 100644 changelog/13859.improvement.rst delete mode 100644 changelog/13861.improvement.rst delete mode 100644 changelog/13865.bugfix.rst delete mode 100644 changelog/478.feature.rst create mode 100644 doc/en/announce/release-9.0.0.rst diff --git a/changelog/12083.breaking.rst b/changelog/12083.breaking.rst deleted file mode 100644 index 53a8393dfb4..00000000000 --- a/changelog/12083.breaking.rst +++ /dev/null @@ -1,9 +0,0 @@ -Fixed a bug where an invocation such as `pytest a/ a/b` would cause only tests from `a/b` to run, and not other tests under `a/`. - -The fix entails a few breaking changes to how such overlapping arguments and duplicates are handled: - -1. `pytest a/b a/` or `pytest a/ a/b` are equivalent to `pytest a`; if an argument overlaps another arguments, only the prefix remains. - -2. `pytest x.py x.py` is equivalent to `pytest x.py`; previously such an invocation was taken as an explicit request to run the tests from the file twice. - -If you rely on these behaviors, consider using :ref:`--keep-duplicates `, which retains its existing behavior (including the bug). diff --git a/changelog/12244.contrib.rst b/changelog/12244.contrib.rst deleted file mode 100644 index e39dad1cfbf..00000000000 --- a/changelog/12244.contrib.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed self-test failures when `TERM=dumb`. diff --git a/changelog/12474.contrib.rst b/changelog/12474.contrib.rst deleted file mode 100644 index bb668fd66c5..00000000000 --- a/changelog/12474.contrib.rst +++ /dev/null @@ -1 +0,0 @@ -Added scheduled GitHub Action Workflow to run Sphinx linkchecks in repo documentation. diff --git a/changelog/13072.feature.rst b/changelog/13072.feature.rst deleted file mode 100644 index 6f9fd11e540..00000000000 --- a/changelog/13072.feature.rst +++ /dev/null @@ -1,8 +0,0 @@ -Added support for displaying test session progress in the terminal tab using the `OSC 9;4; `_ ANSI sequence. -When pytest runs in a supported terminal emulator like ConEmu, Gnome Terminal, Ptyxis, Windows Terminal, Kitty or Ghostty, -you'll see the progress in the terminal tab or window, -allowing you to monitor pytest's progress at a glance. - -This feature is automatically enabled when running in a TTY. It is implemented as an internal plugin. If needed, it can be disabled as follows: -- On a user level, using ``-p no:terminalprogress`` on the command line or via an environment variable ``PYTEST_ADDOPTS='-p no:terminalprogress'``. -- On a project configuration level, using ``addopts = "-p no:terminalprogress"``. diff --git a/changelog/13330.improvement.rst b/changelog/13330.improvement.rst deleted file mode 100644 index 58350ea30ef..00000000000 --- a/changelog/13330.improvement.rst +++ /dev/null @@ -1,3 +0,0 @@ -Having pytest configuration spread over more than one file (for example having both a ``pytest.ini`` file and ``pyproject.toml`` with a ``[tool.pytest.ini_options]`` table) will now print a warning to make it clearer to the user that only one of them is actually used. - --- by :user:`sgaist` diff --git a/changelog/13445.bugfix.rst b/changelog/13445.bugfix.rst deleted file mode 100644 index 1c601a1045e..00000000000 --- a/changelog/13445.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Made the type annotations of :func:`pytest.skip` and friends more spec-complaint to have them work across more type checkers. diff --git a/changelog/13522.bugfix.rst b/changelog/13522.bugfix.rst deleted file mode 100644 index 683304251aa..00000000000 --- a/changelog/13522.bugfix.rst +++ /dev/null @@ -1,5 +0,0 @@ -Fixed :fixture:`pytester` in subprocess mode ignored all :attr`pytester.plugins ` except the first. - -Fixed :fixture:`pytester` in subprocess mode silently ignored non-str :attr:`pytester.plugins `. -Now it errors instead. -If you are affected by this, specify the plugin by name, or switch the affected tests to use :func:`pytester.runpytest_inprocess ` explicitly instead. diff --git a/changelog/13537.bugfix.rst b/changelog/13537.bugfix.rst deleted file mode 100644 index 47743b24f05..00000000000 --- a/changelog/13537.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix bug in which ExceptionGroup with only Skipped exceptions in teardown was not handled correctly and showed as error. diff --git a/changelog/13574.improvement.rst b/changelog/13574.improvement.rst deleted file mode 100644 index 7820cd03fac..00000000000 --- a/changelog/13574.improvement.rst +++ /dev/null @@ -1,7 +0,0 @@ -The single argument ``--version`` no longer loads the entire plugin infrastructure, making it faster and more reliable when displaying only the pytest version. - -Passing ``--version`` twice (e.g., ``pytest --version --version``) retains the original behavior, showing both the pytest version and plugin information. - -.. note:: - - Since ``--version`` is now processed early, it only takes effect when passed directly via the command line. It will not work if set through other mechanisms, such as :envvar:`PYTEST_ADDOPTS` or :confval:`addopts`. diff --git a/changelog/13598.bugfix.rst b/changelog/13598.bugfix.rst deleted file mode 100644 index dd195112eb8..00000000000 --- a/changelog/13598.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed possible collection confusion on Windows when short paths and symlinks are involved. diff --git a/changelog/13621.contrib.rst b/changelog/13621.contrib.rst deleted file mode 100644 index c5e622b7619..00000000000 --- a/changelog/13621.contrib.rst +++ /dev/null @@ -1 +0,0 @@ -pytest's own testsuite now handles the ``lsof`` command hanging (e.g. due to unreachable network filesystems), with the affected selftests being skipped after 10 seconds. diff --git a/changelog/13625.doc.rst b/changelog/13625.doc.rst deleted file mode 100644 index 850c81583b6..00000000000 --- a/changelog/13625.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Added missing docstrings to ``pytest_addoption()``, ``pytest_configure()``, and ``cacheshow()`` functions in ``cacheprovider.py``. diff --git a/changelog/13638.contrib.rst b/changelog/13638.contrib.rst deleted file mode 100644 index 8eb06298c77..00000000000 --- a/changelog/13638.contrib.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed deprecated :command:`gh pr new` command in :file:`scripts/prepare-release-pr.py`. -The script now uses :command:`gh pr create` which is compatible with GitHub CLI v2.0+. diff --git a/changelog/1367.feature.rst b/changelog/1367.feature.rst deleted file mode 100644 index b88480338b5..00000000000 --- a/changelog/1367.feature.rst +++ /dev/null @@ -1,28 +0,0 @@ -**Support for subtests** has been added. - -:ref:`subtests ` are an alternative to parametrization, useful in situations where the parametrization values are not all known at collection time. - -**Example** - -.. code-block:: python - - def contains_docstring(p: Path) -> bool: - """Return True if the given Python file contains a top-level docstring.""" - ... - - - def test_py_files_contain_docstring(subtests: pytest.Subtests) -> None: - for path in Path.cwd().glob("*.py"): - with subtests.test(path=str(path)): - assert contains_docstring(path) - - -Each assert failure or error is caught by the context manager and reported individually, giving a clear picture of all files that are missing a docstring. - -In addition, :meth:`unittest.TestCase.subTest` is now also supported. - -This feature was originally implemented as a separate plugin in `pytest-subtests `__, but since then has been merged into the core. - -.. note:: - - This feature is experimental and will likely evolve in future releases. By that we mean that we might change how subtests are reported on failure, but the functionality and how to use it are stable. diff --git a/changelog/13678.feature.rst b/changelog/13678.feature.rst deleted file mode 100644 index 63c7dfa399f..00000000000 --- a/changelog/13678.feature.rst +++ /dev/null @@ -1,3 +0,0 @@ -Added a new `faulthandler_exit_on_timeout` ini option set to "false" by default to let `faulthandler` interrupt the `pytest` process after a timeout in case of deadlock -- by :user:`ogrisel`. - -Previously, a `faulthandler` timeout would only dump the traceback of all threads to stderr, but would not interrupt the `pytest` process. diff --git a/changelog/13695.contrib.rst b/changelog/13695.contrib.rst deleted file mode 100644 index 675e1fc96a0..00000000000 --- a/changelog/13695.contrib.rst +++ /dev/null @@ -1 +0,0 @@ -Flush `stdout` and `stderr` in `Pytester.run` to avoid truncated outputs in `test_faulthandler.py::test_timeout` on CI -- by :user:`ogrisel`. diff --git a/changelog/13700.improvement.rst b/changelog/13700.improvement.rst deleted file mode 100644 index 40753ae5d5f..00000000000 --- a/changelog/13700.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -`--junitxml` no longer prints the `generated xml file` summary at the end of the pytest session when `--quiet` is given. diff --git a/changelog/13716.bugfix.rst b/changelog/13716.bugfix.rst deleted file mode 100644 index 5eeef4b7624..00000000000 --- a/changelog/13716.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a bug where a nonsensical invocation like ``pytest x.py[a]`` (a file cannot be parametrized) was silently treated as ``pytest x.py``. This is now a usage error. diff --git a/changelog/13719.breaking.rst b/changelog/13719.breaking.rst deleted file mode 100644 index 328c7dfcf2b..00000000000 --- a/changelog/13719.breaking.rst +++ /dev/null @@ -1 +0,0 @@ -Support for Python 3.9 is dropped following its end of life. diff --git a/changelog/13722.bugfix.rst b/changelog/13722.bugfix.rst deleted file mode 100644 index ec36f466815..00000000000 --- a/changelog/13722.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a misleading assertion failure message when using :func:`pytest.approx` on mappings with differing lengths. diff --git a/changelog/13732.improvement.rst b/changelog/13732.improvement.rst deleted file mode 100644 index 07b3d620cf6..00000000000 --- a/changelog/13732.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Previously, when filtering warnings, pytest would fail if the filter referenced a class that could not be imported. Now, this only outputs a message indicating the problem. diff --git a/changelog/13737.feature.rst b/changelog/13737.feature.rst deleted file mode 100644 index e7fe7fd3ab7..00000000000 --- a/changelog/13737.feature.rst +++ /dev/null @@ -1,4 +0,0 @@ -Added the :confval:`strict_parametrization_ids` configuration option. - -When set, pytest emits an error if it detects non-unique parameter set IDs, -rather than automatically making the IDs unique by adding `0`, `1`, ... to them. diff --git a/changelog/13743.feature.rst b/changelog/13743.feature.rst deleted file mode 100644 index b36782487f5..00000000000 --- a/changelog/13743.feature.rst +++ /dev/null @@ -1,37 +0,0 @@ -Added support for native TOML configuration files. - -While pytest, since version 6, supports configuration in ``pyproject.toml`` files under ``[tool.pytest.ini_options]``, -it does so in an "INI compatibility mode", where all configuration values are treated as strings or list of strings. -Now, pytest supports the native TOML data model. - -In ``pyproject.toml``, the native TOML configuration is under the ``[tool.pytest]`` table. - -.. code-block:: toml - - # pyproject.toml - [tool.pytest] - minversion = "9.0" - addopts = ["-ra", "-q"] - testpaths = [ - "tests", - "integration", - ] - -The ``[tool.pytest.ini_options]`` table remains supported, but both tables cannot be used at the same time. - -If you prefer to use a separate configuration file, or don't use ``pyproject.toml``, you can use ``pytest.toml`` or ``.pytest.toml``: - -.. code-block:: toml - - # pytest.toml or .pytest.toml - [pytest] - minversion = "9.0" - addopts = ["-ra", "-q"] - testpaths = [ - "tests", - "integration", - ] - -The documentation now shows configuration snippets in both TOML and INI formats, in a tabbed interface. - -See :ref:`config file formats` for full details. diff --git a/changelog/13766.breaking.rst b/changelog/13766.breaking.rst deleted file mode 100644 index d7bd5a9a0ee..00000000000 --- a/changelog/13766.breaking.rst +++ /dev/null @@ -1,2 +0,0 @@ -Previously, pytest would assume it was running in a CI/CD environment if either of the environment variables `$CI` or `$BUILD_NUMBER` was defined; -now, CI mode is only activated if at least one of those variables is defined and set to a *non-empty* value. diff --git a/changelog/13771.contrib.rst b/changelog/13771.contrib.rst deleted file mode 100644 index fa5cc8afee5..00000000000 --- a/changelog/13771.contrib.rst +++ /dev/null @@ -1 +0,0 @@ -Skip `test_do_not_collect_symlink_siblings` on Windows environments without symlink support to avoid false negatives. diff --git a/changelog/13773.bugfix.rst b/changelog/13773.bugfix.rst deleted file mode 100644 index e3a9ff4b7a1..00000000000 --- a/changelog/13773.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed the static fixture closure calculation to properly consider transitive dependencies requested by overridden fixtures. diff --git a/changelog/13779.breaking.rst b/changelog/13779.breaking.rst deleted file mode 100644 index f7e44c27dfa..00000000000 --- a/changelog/13779.breaking.rst +++ /dev/null @@ -1,22 +0,0 @@ -**PytestRemovedIn9Warning deprecation warnings are now errors by default.** - -Following our plan to remove deprecated features with as little disruption as -possible, all warnings of type ``PytestRemovedIn9Warning`` now generate errors -instead of warning messages by default. - -**The affected features will be effectively removed in pytest 9.1**, so please consult the -:ref:`deprecations` section in the docs for directions on how to update existing code. - -In the pytest ``9.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.PytestRemovedIn9Warning - -But this will stop working when pytest ``9.1`` is released. - -**If you have concerns** about the removal of a specific feature, please add a -comment to :issue:`13779`. diff --git a/changelog/13791.packaging.rst b/changelog/13791.packaging.rst deleted file mode 100644 index d16065e85a5..00000000000 --- a/changelog/13791.packaging.rst +++ /dev/null @@ -1,2 +0,0 @@ -Minimum requirements on ``iniconfig`` and ``packaging`` were bumped -to ``1.0.1`` and ``22.0.0``, respectively. diff --git a/changelog/13807.deprecation.rst b/changelog/13807.deprecation.rst deleted file mode 100644 index 59bd62214e1..00000000000 --- a/changelog/13807.deprecation.rst +++ /dev/null @@ -1,3 +0,0 @@ -:meth:`monkeypatch.syspath_prepend() ` now issues a deprecation warning when the prepended path contains legacy namespace packages (those using ``pkg_resources.declare_namespace()``). -Users should migrate to native namespace packages (:pep:`420`). -See :ref:`monkeypatch-fixup-namespace-packages` for details. diff --git a/changelog/13816.bugfix.rst b/changelog/13816.bugfix.rst deleted file mode 100644 index 432fc519ed5..00000000000 --- a/changelog/13816.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed :func:`pytest.approx` which now returns a clearer error message when comparing mappings with different keys. diff --git a/changelog/13823.feature.rst b/changelog/13823.feature.rst deleted file mode 100644 index b6152ff50ea..00000000000 --- a/changelog/13823.feature.rst +++ /dev/null @@ -1,18 +0,0 @@ -Added a :confval:`strict` configuration option to enable all strictness-related options. - -When set to ``true``, the :confval:`strict` option currently enables - -* :confval:`strict_config` -* :confval:`strict_markers` -* :confval:`strict_parametrization_ids` -* :confval:`strict_xfail` - -The individual strictness options can be explicitly set to override the global :confval:`strict` setting. - -The previously-deprecated ``--strict`` command-line flag now enables strict mode. - -If pytest adds new strictness options in the future, they will also be enabled in strict mode. -Therefore, you should only enable strict mode if you use a pinned/locked version of pytest, -or if you want to proactively adopt new strictness options as they are added. - -See :ref:`strict mode` for more details. diff --git a/changelog/13823.improvement.rst b/changelog/13823.improvement.rst deleted file mode 100644 index 4346d702c8c..00000000000 --- a/changelog/13823.improvement.rst +++ /dev/null @@ -1,4 +0,0 @@ -Added :confval:`strict_xfail` as an alias to the ``xfail_strict`` option, -:confval:`strict_config` as an alias to the ``--strict-config`` flag, -and :confval:`strict_markers` as an alias to the ``--strict-markers`` flag. -This makes all strictness options consistently have configuration options with the prefix ``strict_``. diff --git a/changelog/13829.feature.rst b/changelog/13829.feature.rst deleted file mode 100644 index 5f80ca5ac2f..00000000000 --- a/changelog/13829.feature.rst +++ /dev/null @@ -1,5 +0,0 @@ -Added support for ini option aliases via the ``aliases`` parameter in :meth:`Parser.addini() `. - -Plugins can now register alternative names for ini options, -allowing for more flexibility in configuration naming and supporting backward compatibility when renaming options. -The canonical name always takes precedence if both the canonical name and an alias are specified in the configuration file. diff --git a/changelog/13830.misc.rst b/changelog/13830.misc.rst deleted file mode 100644 index 0d81ce2f14f..00000000000 --- a/changelog/13830.misc.rst +++ /dev/null @@ -1 +0,0 @@ -Configuration overrides (``-o``/``--override-ini``) are now processed during startup rather than during :func:`config.getini() `. diff --git a/changelog/13841.contrib.rst b/changelog/13841.contrib.rst deleted file mode 100644 index e5672634700..00000000000 --- a/changelog/13841.contrib.rst +++ /dev/null @@ -1 +0,0 @@ -``tox>=4`` is now required when contributing to pytest. diff --git a/changelog/13849.bugfix.rst b/changelog/13849.bugfix.rst deleted file mode 100644 index cdcc7b83591..00000000000 --- a/changelog/13849.bugfix.rst +++ /dev/null @@ -1,2 +0,0 @@ -Hidden ``.pytest.ini`` files are now picked up as the config file even if empty. -This was an inconsistency with non-hidden ``pytest.ini``. diff --git a/changelog/13859.improvement.rst b/changelog/13859.improvement.rst deleted file mode 100644 index b785381fd68..00000000000 --- a/changelog/13859.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Clarify the error message for `pytest.raises()` when a regex `match` fails. diff --git a/changelog/13861.improvement.rst b/changelog/13861.improvement.rst deleted file mode 100644 index 2f062404e1c..00000000000 --- a/changelog/13861.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Better sentence structure in a test's expected error message. Previously, the error message would be "expected exception must be , but got ". Now, it is "Expected , but got ". diff --git a/changelog/13865.bugfix.rst b/changelog/13865.bugfix.rst deleted file mode 100644 index f7cd94c2a30..00000000000 --- a/changelog/13865.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed `--show-capture` with `--tb=line`. diff --git a/changelog/478.feature.rst b/changelog/478.feature.rst deleted file mode 100644 index cd13ddd9733..00000000000 --- a/changelog/478.feature.rst +++ /dev/null @@ -1,3 +0,0 @@ -Support PEP420 (implicit namespace packages) as `--pyargs` target when :confval:`consider_namespace_packages` is `true` in the config. - -Previously, this option only impacted package names, now it also impacts tests discovery. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 1cc8fbaf7c0..f5e00d34cdb 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-9.0.0 release-8.4.2 release-8.4.1 release-8.4.0 diff --git a/doc/en/announce/release-9.0.0.rst b/doc/en/announce/release-9.0.0.rst new file mode 100644 index 00000000000..86dd828f045 --- /dev/null +++ b/doc/en/announce/release-9.0.0.rst @@ -0,0 +1,69 @@ +pytest-9.0.0 +======================================= + +The pytest team is proud to announce the 9.0.0 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: + +* AD +* Aditi De +* Ali Nazzal +* Bruno Oliveira +* Charles-Meldhine Madi Mnemoi +* Clément Robert +* CoretexShadow +* Cornelius Roemer +* Eero Vaher +* Florian Bruhin +* Harsha Sai +* Hossein +* Israël Hallé +* Iwithyou2025 +* James Addison +* John Litborn +* Jordan Macdonald +* Kieran Ryan +* Liam DeVoe +* Marc Mueller +* Marcos Boger +* Michał Górny +* Mulat Mekonen +* NayeemJohn +* Olivier Grisel +* Omri Golan +* Pierre Sassoulas +* Praise Tompane +* Ran Benita +* Reilly Brogan +* Samuel Gaist +* SarahPythonista +* Sorin Sbarnea +* Stu-ops +* Tanuj Rai +* bengartner +* dariomesic +* jakkdl +* karlicoss +* popododo0720 +* sazsu +* slackline +* vyuroshchin +* zapl +* 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index ca350c5f3dd..a7b0ff2e5c8 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -22,7 +22,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a cachedir: .pytest_cache rootdir: /home/sweet/project collected 0 items - cache -- .../_pytest/cacheprovider.py:555 + cache -- .../_pytest/cacheprovider.py:566 Return a cache object that can persist state between testing sessions. cache.get(key, default) @@ -128,7 +128,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capfdbinary.readouterr() assert captured.out == b"hello\n" - doctest_namespace [session scope] -- .../_pytest/doctest.py:740 + doctest_namespace [session scope] -- .../_pytest/doctest.py:722 Fixture that returns a :py:class:`dict` that will be injected into the namespace of doctests. @@ -142,7 +142,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a For more details: :ref:`doctest_namespace`. - pytestconfig [session scope] -- .../_pytest/fixtures.py:1425 + pytestconfig [session scope] -- .../_pytest/fixtures.py:1431 Session-scoped fixture that returns the session's :class:`pytest.Config` object. @@ -225,7 +225,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a * caplog.record_tuples -> list of (logger_name, level, message) tuples * caplog.clear() -> clear captured records and formatted log output string - monkeypatch -- .../_pytest/monkeypatch.py:31 + monkeypatch -- .../_pytest/monkeypatch.py:33 A convenient fixture for monkey-patching. The fixture provides these methods to modify objects, dictionaries, or @@ -254,6 +254,9 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a See :ref:`warnings` for information on warning categories. + subtests -- .../_pytest/subtests.py:129 + Provides subtests functionality. + tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:240 Return a :class:`pytest.TempPathFactory` instance for the test session. diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 89f1c4e61b3..5220afc46e3 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -31,6 +31,307 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 9.0.0 (2025-11-05) +========================= + +New features +------------ + + +- `#1367 `_: **Support for subtests** has been added. + + :ref:`subtests ` are an alternative to parametrization, useful in situations where the parametrization values are not all known at collection time. + + Example: + + .. code-block:: python + + def contains_docstring(p: Path) -> bool: + """Return True if the given Python file contains a top-level docstring.""" + ... + + + def test_py_files_contain_docstring(subtests: pytest.Subtests) -> None: + for path in Path.cwd().glob("*.py"): + with subtests.test(path=str(path)): + assert contains_docstring(path) + + + Each assert failure or error is caught by the context manager and reported individually, giving a clear picture of all files that are missing a docstring. + + In addition, :meth:`unittest.TestCase.subTest` is now also supported. + + This feature was originally implemented as a separate plugin in `pytest-subtests `__, but since then has been merged into the core. + + .. note:: + + This feature is experimental and will likely evolve in future releases. By that we mean that we might change how subtests are reported on failure, but the functionality and how to use it are stable. + + +- `#13743 `_: Added support for **native TOML configuration files**. + + While pytest, since version 6, supports configuration in ``pyproject.toml`` files under ``[tool.pytest.ini_options]``, + it does so in an "INI compatibility mode", where all configuration values are treated as strings or list of strings. + Now, pytest supports the native TOML data model. + + In ``pyproject.toml``, the native TOML configuration is under the ``[tool.pytest]`` table. + + .. code-block:: toml + + # pyproject.toml + [tool.pytest] + minversion = "9.0" + addopts = ["-ra", "-q"] + testpaths = [ + "tests", + "integration", + ] + + The ``[tool.pytest.ini_options]`` table remains supported, but both tables cannot be used at the same time. + + If you prefer to use a separate configuration file, or don't use ``pyproject.toml``, you can use ``pytest.toml`` or ``.pytest.toml``: + + .. code-block:: toml + + # pytest.toml or .pytest.toml + [pytest] + minversion = "9.0" + addopts = ["-ra", "-q"] + testpaths = [ + "tests", + "integration", + ] + + The documentation now (sometimes) shows configuration snippets in both TOML and INI formats, in a tabbed interface. + + See :ref:`config file formats` for full details. + + +- `#13823 `_: Added a **"strict mode"** enabled by the :confval:`strict` configuration option. + + When set to ``true``, the :confval:`strict` option currently enables + + * :confval:`strict_config` + * :confval:`strict_markers` + * :confval:`strict_parametrization_ids` + * :confval:`strict_xfail` + + The individual strictness options can be explicitly set to override the global :confval:`strict` setting. + + The previously-deprecated ``--strict`` command-line flag now enables strict mode. + + If pytest adds new strictness options in the future, they will also be enabled in strict mode. + Therefore, you should only enable strict mode if you use a pinned/locked version of pytest, + or if you want to proactively adopt new strictness options as they are added. + + See :ref:`strict mode` for more details. + + +- `#13737 `_: Added the :confval:`strict_parametrization_ids` configuration option. + + When set, pytest emits an error if it detects non-unique parameter set IDs, + rather than automatically making the IDs unique by adding `0`, `1`, ... to them. + This can be particularly useful for catching unintended duplicates. + + +- `#13072 `_: Added support for displaying test session **progress in the terminal tab** using the `OSC 9;4; `_ ANSI sequence. + When pytest runs in a supported terminal emulator like ConEmu, Gnome Terminal, Ptyxis, Windows Terminal, Kitty or Ghostty, + you'll see the progress in the terminal tab or window, + allowing you to monitor pytest's progress at a glance. + + This feature is automatically enabled when running in a TTY. It is implemented as an internal plugin. If needed, it can be disabled as follows: + - On a user level, using ``-p no:terminalprogress`` on the command line or via an environment variable ``PYTEST_ADDOPTS='-p no:terminalprogress'``. + - On a project configuration level, using ``addopts = "-p no:terminalprogress"``. + + +- `#478 `_: Support PEP420 (implicit namespace packages) as `--pyargs` target when :confval:`consider_namespace_packages` is `true` in the config. + + Previously, this option only impacted package imports, now it also impacts tests discovery. + + +- `#13678 `_: Added a new :confval:`faulthandler_exit_on_timeout` configuration option set to "false" by default to let `faulthandler` interrupt the `pytest` process after a timeout in case of deadlock. + + Previously, a `faulthandler` timeout would only dump the traceback of all threads to stderr, but would not interrupt the `pytest` process. + + -- by :user:`ogrisel`. + + +- `#13829 `_: Added support for configuration option aliases via the ``aliases`` parameter in :meth:`Parser.addini() `. + + Plugins can now register alternative names for configuration options, + allowing for more flexibility in configuration naming and supporting backward compatibility when renaming options. + The canonical name always takes precedence if both the canonical name and an alias are specified in the configuration file. + + + +Improvements in existing functionality +-------------------------------------- + +- `#13330 `_: Having pytest configuration spread over more than one file (for example having both a ``pytest.ini`` file and ``pyproject.toml`` with a ``[tool.pytest.ini_options]`` table) will now print a warning to make it clearer to the user that only one of them is actually used. + + -- by :user:`sgaist` + + +- `#13574 `_: The single argument ``--version`` no longer loads the entire plugin infrastructure, making it faster and more reliable when displaying only the pytest version. + + Passing ``--version`` twice (e.g., ``pytest --version --version``) retains the original behavior, showing both the pytest version and plugin information. + + .. note:: + + Since ``--version`` is now processed early, it only takes effect when passed directly via the command line. It will not work if set through other mechanisms, such as :envvar:`PYTEST_ADDOPTS` or :confval:`addopts`. + + +- `#13823 `_: Added :confval:`strict_xfail` as an alias to the ``xfail_strict`` option, + :confval:`strict_config` as an alias to the ``--strict-config`` flag, + and :confval:`strict_markers` as an alias to the ``--strict-markers`` flag. + This makes all strictness options consistently have configuration options with the prefix ``strict_``. + +- `#13700 `_: `--junitxml` no longer prints the `generated xml file` summary at the end of the pytest session when `--quiet` is given. + + +- `#13732 `_: Previously, when filtering warnings, pytest would fail if the filter referenced a class that could not be imported. Now, this only outputs a message indicating the problem. + + +- `#13859 `_: Clarify the error message for `pytest.raises()` when a regex `match` fails. + + +- `#13861 `_: Better sentence structure in a test's expected error message. Previously, the error message would be "expected exception must be , but got ". Now, it is "Expected , but got ". + + +Removals and backward incompatible breaking changes +--------------------------------------------------- + +- `#12083 `_: Fixed a bug where an invocation such as `pytest a/ a/b` would cause only tests from `a/b` to run, and not other tests under `a/`. + + The fix entails a few breaking changes to how such overlapping arguments and duplicates are handled: + + 1. `pytest a/b a/` or `pytest a/ a/b` are equivalent to `pytest a`; if an argument overlaps another arguments, only the prefix remains. + + 2. `pytest x.py x.py` is equivalent to `pytest x.py`; previously such an invocation was taken as an explicit request to run the tests from the file twice. + + If you rely on these behaviors, consider using :ref:`--keep-duplicates `, which retains its existing behavior (including the bug). + + +- `#13719 `_: Support for Python 3.9 is dropped following its end of life. + + +- `#13766 `_: Previously, pytest would assume it was running in a CI/CD environment if either of the environment variables `$CI` or `$BUILD_NUMBER` was defined; + now, CI mode is only activated if at least one of those variables is defined and set to a *non-empty* value. + + +- `#13779 `_: **PytestRemovedIn9Warning deprecation warnings are now errors by default.** + + Following our plan to remove deprecated features with as little disruption as + possible, all warnings of type ``PytestRemovedIn9Warning`` now generate errors + instead of warning messages by default. + + **The affected features will be effectively removed in pytest 9.1**, so please consult the + :ref:`deprecations` section in the docs for directions on how to update existing code. + + In the pytest ``9.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.PytestRemovedIn9Warning + + But this will stop working when pytest ``9.1`` is released. + + **If you have concerns** about the removal of a specific feature, please add a + comment to :issue:`13779`. + + + +Deprecations (removal in next major release) +-------------------------------------------- + +- `#13807 `_: :meth:`monkeypatch.syspath_prepend() ` now issues a deprecation warning when the prepended path contains legacy namespace packages (those using ``pkg_resources.declare_namespace()``). + Users should migrate to native namespace packages (:pep:`420`). + See :ref:`monkeypatch-fixup-namespace-packages` for details. + + +Bug fixes +--------- + +- `#13445 `_: Made the type annotations of :func:`pytest.skip` and friends more spec-complaint to have them work across more type checkers. + + +- `#13537 `_: Fixed a bug in which :class:`ExceptionGroup` with only ``Skipped`` exceptions in teardown was not handled correctly and showed as error. + + +- `#13598 `_: Fixed possible collection confusion on Windows when short paths and symlinks are involved. + + +- `#13716 `_: Fixed a bug where a nonsensical invocation like ``pytest x.py[a]`` (a file cannot be parametrized) was silently treated as ``pytest x.py``. This is now a usage error. + + +- `#13722 `_: Fixed a misleading assertion failure message when using :func:`pytest.approx` on mappings with differing lengths. + + +- `#13773 `_: Fixed the static fixture closure calculation to properly consider transitive dependencies requested by overridden fixtures. + + +- `#13816 `_: Fixed :func:`pytest.approx` which now returns a clearer error message when comparing mappings with different keys. + + +- `#13849 `_: Hidden ``.pytest.ini`` files are now picked up as the config file even if empty. + This was an inconsistency with non-hidden ``pytest.ini``. + + +- `#13865 `_: Fixed `--show-capture` with `--tb=line`. + + +- `#13522 `_: Fixed :fixture:`pytester` in subprocess mode ignored all :attr`pytester.plugins ` except the first. + + Fixed :fixture:`pytester` in subprocess mode silently ignored non-str :attr:`pytester.plugins `. + Now it errors instead. + If you are affected by this, specify the plugin by name, or switch the affected tests to use :func:`pytester.runpytest_inprocess ` explicitly instead. + + + +Packaging updates and notes for downstreams +------------------------------------------- + +- `#13791 `_: Minimum requirements on ``iniconfig`` and ``packaging`` were bumped to ``1.0.1`` and ``22.0.0``, respectively. + + + +Contributor-facing changes +-------------------------- + +- `#12244 `_: Fixed self-test failures when `TERM=dumb`. + + +- `#12474 `_: Added scheduled GitHub Action Workflow to run Sphinx linkchecks in repo documentation. + + +- `#13621 `_: pytest's own testsuite now handles the ``lsof`` command hanging (e.g. due to unreachable network filesystems), with the affected selftests being skipped after 10 seconds. + + +- `#13638 `_: Fixed deprecated :command:`gh pr new` command in :file:`scripts/prepare-release-pr.py`. + The script now uses :command:`gh pr create` which is compatible with GitHub CLI v2.0+. + + +- `#13695 `_: Flush `stdout` and `stderr` in `Pytester.run` to avoid truncated outputs in `test_faulthandler.py::test_timeout` on CI -- by :user:`ogrisel`. + + +- `#13771 `_: Skip `test_do_not_collect_symlink_siblings` on Windows environments without symlink support to avoid false negatives. + + +- `#13841 `_: ``tox>=4`` is now required when contributing to pytest. + +- `#13625 `_: Added missing docstrings to ``pytest_addoption()``, ``pytest_configure()``, and ``cacheshow()`` functions in ``cacheprovider.py``. + + + +Miscellaneous internal changes +------------------------------ + +- `#13830 `_: Configuration overrides (``-o``/``--override-ini``) are now processed during startup rather than during :func:`config.getini() `. + + pytest 8.4.2 (2025-09-03) ========================= diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst index c8f7c8c2fa2..afb1ece0fe8 100644 --- a/doc/en/example/markers.rst +++ b/doc/en/example/markers.rst @@ -262,7 +262,7 @@ You can ask which markers exist for your test suite - the list includes our just @pytest.mark.skipif(condition, ..., *, reason=...): skip the given test function if any of the conditions evaluate to True. Example: skipif(sys.platform == 'win32') skips the test if we are on the win32 platform. See https://docs.pytest.org/en/stable/reference/reference.html#pytest-mark-skipif - @pytest.mark.xfail(condition, ..., *, reason=..., run=True, raises=None, strict=xfail_strict): mark the test function as an expected failure if any of the conditions evaluate to True. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See https://docs.pytest.org/en/stable/reference/reference.html#pytest-mark-xfail + @pytest.mark.xfail(condition, ..., *, reason=..., run=True, raises=None, strict=strict_xfail): mark the test function as an expected failure if any of the conditions evaluate to True. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See https://docs.pytest.org/en/stable/reference/reference.html#pytest-mark-xfail @pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see https://docs.pytest.org/en/stable/how-to/parametrize.html for more info and examples. @@ -453,7 +453,7 @@ The ``--markers`` option always gives you a list of available markers: @pytest.mark.skipif(condition, ..., *, reason=...): skip the given test function if any of the conditions evaluate to True. Example: skipif(sys.platform == 'win32') skips the test if we are on the win32 platform. See https://docs.pytest.org/en/stable/reference/reference.html#pytest-mark-skipif - @pytest.mark.xfail(condition, ..., *, reason=..., run=True, raises=None, strict=xfail_strict): mark the test function as an expected failure if any of the conditions evaluate to True. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See https://docs.pytest.org/en/stable/reference/reference.html#pytest-mark-xfail + @pytest.mark.xfail(condition, ..., *, reason=..., run=True, raises=None, strict=strict_xfail): mark the test function as an expected failure if any of the conditions evaluate to True. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See https://docs.pytest.org/en/stable/reference/reference.html#pytest-mark-xfail @pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see https://docs.pytest.org/en/stable/how-to/parametrize.html for more info and examples. diff --git a/doc/en/example/nonpython.rst b/doc/en/example/nonpython.rst index aa463e2416b..a8d172937c5 100644 --- a/doc/en/example/nonpython.rst +++ b/doc/en/example/nonpython.rst @@ -40,7 +40,7 @@ now execute the test specification: spec failed: 'some': 'other' no further details known at this point. ========================= short test summary info ========================== - FAILED test_simple.yaml::hello + FAILED test_simple.yaml::hello - usecase execution failed ======================= 1 failed, 1 passed in 0.12s ======================== .. regendoc:wipe @@ -78,7 +78,7 @@ consulted when reporting in ``verbose`` mode: spec failed: 'some': 'other' no further details known at this point. ========================= short test summary info ========================== - FAILED test_simple.yaml::hello + FAILED test_simple.yaml::hello - usecase execution failed ======================= 1 failed, 1 passed in 0.12s ======================== .. regendoc:wipe diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index 6374e0edb3d..b27dae18c32 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -162,7 +162,7 @@ objects, they are still using the default pytest representation: rootdir: /home/sweet/project collected 8 items - + @@ -239,7 +239,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia rootdir: /home/sweet/project collected 4 items - + @@ -318,7 +318,7 @@ Let's first see how it looks like at collection time: rootdir: /home/sweet/project collected 2 items - + @@ -503,12 +503,10 @@ Running it results in some skips if we don't have all the python interpreters in .. code-block:: pytest . $ pytest -rs -q multipython.py - sssssssssssssssssssssssssss [100%] + ssssssssssss......sss...... [100%] ========================= short test summary info ========================== - SKIPPED [9] multipython.py:67: 'python3.9' not found - SKIPPED [9] multipython.py:67: 'python3.10' not found - SKIPPED [9] multipython.py:67: 'python3.11' not found - 27 skipped in 0.12s + SKIPPED [15] multipython.py:67: 'python3.11' not found + 12 passed, 15 skipped in 0.12s Parametrization of optional implementations/imports --------------------------------------------------- diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 46d15557fa8..09489418773 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -139,10 +139,10 @@ The test collection would look like this: =========================== test session starts ============================ platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project - configfile: pytest.ini + configfile: pytest.toml collected 2 items - + @@ -202,10 +202,10 @@ You can always peek at the collection tree without running tests like this: =========================== test session starts ============================ platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project - configfile: pytest.ini + configfile: pytest.toml collected 3 items - + @@ -286,7 +286,7 @@ file will be left out: =========================== test session starts ============================ platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project - configfile: pytest.ini + configfile: pytest.toml collected 0 items ======================= no tests collected in 0.12s ======================== diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index 928dcddae74..e150e7ca00b 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -166,6 +166,8 @@ Now we'll get feedback on a bad argument: $ pytest -q --cmdopt=type3 ERROR: usage: pytest [options] [file_or_dir] [file_or_dir] [...] pytest: error: argument --cmdopt: invalid choice: 'type3' (choose from type1, type2) + inifile: None + rootdir: /home/sweet/project If you need to provide more detailed error messages, you can use the @@ -726,7 +728,7 @@ We can run this: file /home/sweet/project/b/test_error.py, line 1 def test_root(db): # no db here, will error out E fixture 'db' not found - > available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, capteesys, doctest_namespace, monkeypatch, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory + > available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, capteesys, doctest_namespace, monkeypatch, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, subtests, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory > use 'pytest --fixtures [testpath]' for help on them. /home/sweet/project/b/test_error.py:1 diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 24501f53a69..ec1ef60a605 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -20,7 +20,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 8.4.2 + pytest 9.0.0 .. _`simpletest`: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index 73a3eeb15c1..0c4ddb8b4dc 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1423,7 +1423,7 @@ Running the above tests results in the following test IDs being used: rootdir: /home/sweet/project collected 12 items - + diff --git a/doc/en/how-to/subtests.rst b/doc/en/how-to/subtests.rst index 956405bc7cf..c8d9461c983 100644 --- a/doc/en/how-to/subtests.rst +++ b/doc/en/how-to/subtests.rst @@ -29,7 +29,37 @@ Each assertion failure or error is caught by the context manager and reported in .. code-block:: pytest $ pytest -q test_subtest.py - + uuuuuF [100%] + ================================= FAILURES ================================= + _______________________ test [custom message] (i=1) ________________________ + + subtests = <_pytest.subtests.Subtests object at 0xdeadbeef0001> + + def test(subtests): + for i in range(5): + with subtests.test(msg="custom message", i=i): + > assert i % 2 == 0 + E assert (1 % 2) == 0 + + test_subtest.py:6: AssertionError + _______________________ test [custom message] (i=3) ________________________ + + subtests = <_pytest.subtests.Subtests object at 0xdeadbeef0001> + + def test(subtests): + for i in range(5): + with subtests.test(msg="custom message", i=i): + > assert i % 2 == 0 + E assert (3 % 2) == 0 + + test_subtest.py:6: AssertionError + ___________________________________ test ___________________________________ + contains 2 failed subtests + ========================= short test summary info ========================== + SUBFAILED[custom message] (i=1) test_subtest.py::test - assert (1 % 2) == 0 + SUBFAILED[custom message] (i=3) test_subtest.py::test - assert (3 % 2) == 0 + FAILED test_subtest.py::test - contains 2 failed subtests + 3 failed, 3 subtests passed in 0.12s In the output above: diff --git a/doc/en/how-to/writing_plugins.rst b/doc/en/how-to/writing_plugins.rst index 3cf49ebb0c6..6382edc4797 100644 --- a/doc/en/how-to/writing_plugins.rst +++ b/doc/en/how-to/writing_plugins.rst @@ -448,7 +448,7 @@ in our configuration file to tell pytest where to look for example files. =========================== test session starts ============================ platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project - configfile: pytest.ini + configfile: pytest.toml collected 2 items test_example.py .. [100%] diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 108ad660af3..1c51b712ee1 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -2692,11 +2692,9 @@ All the command-line flags can be obtained by running ``pytest --help``:: --markers show markers (builtin, plugin and per-project ones). -x, --exitfirst Exit instantly on first error or failed test --maxfail=num Exit after first num failures or errors - --strict-config Any warnings encountered while parsing the `pytest` - section of the configuration file raise errors - --strict-markers Markers not registered in the `markers` section of - the configuration file raise errors - --strict (Deprecated) alias to --strict-markers + --strict-config Enables the strict_config option + --strict-markers Enables the strict_markers option + --strict Enables the strict option --fixtures, --funcargs Show available fixtures, sorted by plugin appearance (fixtures with leading '_' are only shown with '-v') @@ -2845,8 +2843,9 @@ All the command-line flags can be obtained by running ``pytest --help``:: file. This file is opened with 'w' and truncated as a result, care advised. Default: pytestdebug.log. -o, --override-ini OVERRIDE_INI - Override ini option with "option=value" style, e.g. - `-o xfail_strict=True -o cache_dir=cache`. + Override configuration option with "option=value" + style, e.g. `-o strict_xfail=True -o + cache_dir=cache`. --assert=MODE Control assertion debugging tools. 'plain' performs no assertion debugging. 'rewrite' (the default) rewrites assert statements @@ -2888,11 +2887,19 @@ All the command-line flags can be obtained by running ``pytest --help``:: Disable a logger by name. Can be passed multiple times. - [pytest] ini-options in the first pytest.ini|tox.ini|setup.cfg|pyproject.toml file found: + [pytest] configuration options in the first pytest.toml|pytest.ini|tox.ini|setup.cfg|pyproject.toml file found: markers (linelist): Register new markers for test functions empty_parameter_set_mark (string): Default marker for empty parametersets + strict_config (bool): Any warnings encountered while parsing the `pytest` + section of the configuration file raise errors + strict_markers (bool): + Markers not registered in the `markers` section of + the configuration file raise errors + strict (bool): Enables all strictness options, currently: + strict_config, strict_markers, strict_xfail, + strict_parametrization_ids filterwarnings (linelist): Each line specifies a pattern for warnings.filterwarnings. Processed after @@ -2919,6 +2926,9 @@ All the command-line flags can be obtained by running ``pytest --help``:: disable_test_id_escaping_and_forfeit_all_rights_to_community_support (bool): Disable string escape non-ASCII characters, might cause unwanted side effects(use at your own risk) + strict_parametrization_ids (bool): + Emit an error if non-unique parameter set IDs are + detected console_output_style (string): Console output: "classic", or with additional progress information ("progress" (percentage) | @@ -2929,8 +2939,9 @@ All the command-line flags can be obtained by running ``pytest --help``:: overriding the main level. Higher levels will provide more detailed information about each test case executed. - xfail_strict (bool): Default for the strict parameter of xfail markers - when not given explicitly (default: False) + strict_xfail (bool): Default for the strict parameter of xfail markers + when not given explicitly (default: False) (alias: + xfail_strict) tmp_path_retention_count (string): How many sessions should we keep the `tmp_path` directories, according to @@ -2998,6 +3009,10 @@ All the command-line flags can be obtained by running ``pytest --help``:: faulthandler_exit_on_timeout (bool): Exit the test process if a test takes more than faulthandler_timeout seconds to finish + verbosity_subtests (string): + Specify verbosity level for subtests. Higher levels + will generate output for passed subtests. Failed + subtests are always reported. addopts (args): Extra command line options minversion (string): Minimally required pytest version pythonpath (paths): Add paths to sys.path @@ -3011,6 +3026,9 @@ All the command-line flags can be obtained by running ``pytest --help``:: PYTEST_PLUGINS Comma-separated plugins to load during startup PYTEST_DISABLE_PLUGIN_AUTOLOAD Set to disable plugin auto-loading PYTEST_DEBUG Set to enable debug tracing of pytest's internals + PYTEST_DEBUG_TEMPROOT Override the system temporary directory + PYTEST_THEME The Pygments style to use for code output + PYTEST_THEME_MODE Set the PYTEST_THEME to be either 'dark' or 'light' to see available markers type: pytest --markers diff --git a/doc/en/requirements.txt b/doc/en/requirements.txt index 5483bb46063..fcaaee695c9 100644 --- a/doc/en/requirements.txt +++ b/doc/en/requirements.txt @@ -1,6 +1,6 @@ -c broken-dep-constraints.txt pluggy>=1.5.0 -pygments-pytest>=2.3.0 +pygments-pytest>=2.5.0 sphinx-removed-in>=0.2.0 sphinx>=7 sphinxcontrib-trio From 436032b1a224da87ab31ee11867fd11eb16f2e78 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 9 Nov 2025 00:32:33 +0200 Subject: [PATCH 02/74] Merge pull request #13894 from bluetech/plugin-asyncio-disable testing: temporarily disable pytest-asyncio integration test (cherry picked from commit f9ab35fa31a62bab9e93bec8ee1e98a8decd5039) --- testing/plugins_integration/pytest.ini | 3 ++- testing/plugins_integration/requirements.txt | 3 ++- tox.ini | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/testing/plugins_integration/pytest.ini b/testing/plugins_integration/pytest.ini index b0eb9c3806f..258b4143177 100644 --- a/testing/plugins_integration/pytest.ini +++ b/testing/plugins_integration/pytest.ini @@ -1,6 +1,7 @@ [pytest] strict_markers = True -asyncio_mode = strict +; Temporarily disabled until adds support for pytest 9. +; asyncio_mode = strict filterwarnings = error::pytest.PytestWarning ignore:usefixtures.* without arguments has no effect:pytest.PytestWarning diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 22d13f87b96..d62f25743f0 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,6 +1,7 @@ anyio[trio]==4.11.0 django==5.2.8 -pytest-asyncio==1.2.0 +# Temporarily disabled until adds support for pytest 9. +#pytest-asyncio==1.2.0 pytest-bdd==8.1.0 pytest-cov==7.0.0 pytest-django==4.11.1 diff --git a/tox.ini b/tox.ini index b6fcecc886a..bbd62b7e7c5 100644 --- a/tox.ini +++ b/tox.ini @@ -175,7 +175,8 @@ commands = pytest --html=simple.html simple_integration.py pytest --reruns 5 simple_integration.py pytest_rerunfailures_integration.py pytest pytest_anyio_integration.py - pytest pytest_asyncio_integration.py + # Temporarily disabled until adds support for pytest 9. + # pytest pytest_asyncio_integration.py pytest pytest_mock_integration.py pytest pytest_trio_integration.py pytest pytest_twisted_integration.py From 49c7ac2aa5660365b1592955f733e8bab9890269 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 9 Nov 2025 00:32:45 +0200 Subject: [PATCH 03/74] Merge pull request #13891 from bluetech/fix-gh-release ci: `gh release create` needs a checkout (cherry picked from commit 4b73dcab02e2414496daf2683ef870719a461ec9) --- .github/workflows/deploy.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 176daa1b4d7..ad7cc029c5e 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -120,6 +120,11 @@ jobs: permissions: contents: write steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + persist-credentials: true + - name: Download Package uses: actions/download-artifact@v6 with: From 9db3995c82c1fd1d51be3d30baf03ec2a80fe08f Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 10 Nov 2025 19:18:47 +0200 Subject: [PATCH 04/74] Merge pull request #13897 from bluetech/iterm-terminalprogress terminal: disable terminal progress plugin on iTerm2 (cherry picked from commit 1ff8c9b429d888e3f9020d015fa088f828899457) --- changelog/13896.bugfix.rst | 1 + src/_pytest/terminal.py | 12 ++++++++++-- testing/test_terminal.py | 11 +++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 changelog/13896.bugfix.rst diff --git a/changelog/13896.bugfix.rst b/changelog/13896.bugfix.rst new file mode 100644 index 00000000000..821af0c96b4 --- /dev/null +++ b/changelog/13896.bugfix.rst @@ -0,0 +1 @@ +The terminal progress plugin added in pytest 9.0 is now automatically disabled when iTerm2 is detected, it generated desktop notifications instead of the desired functionality. diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 158558b4571..4517b05bdee 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -16,6 +16,7 @@ import datetime from functools import partial import inspect +import os from pathlib import Path import platform import sys @@ -299,8 +300,15 @@ def mywriter(tags, args): config.trace.root.setprocessor("pytest:config", mywriter) if reporter.isatty(): - plugin = TerminalProgressPlugin(reporter) - config.pluginmanager.register(plugin, "terminalprogress") + # Some terminals interpret OSC 9;4 as desktop notification, + # skip on those we know (#13896). + should_skip_terminal_progress = ( + # iTerm2 (reported on version 3.6.5). + "ITERM_SESSION_ID" in os.environ + ) + if not should_skip_terminal_progress: + plugin = TerminalProgressPlugin(reporter) + config.pluginmanager.register(plugin, "terminalprogress") def getreportopt(config: Config) -> str: diff --git a/testing/test_terminal.py b/testing/test_terminal.py index ee540b65135..a981e14f0a2 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -3443,6 +3443,17 @@ def test_disabled_for_non_tty(self, pytester: pytest.Pytester) -> None: plugin = config.pluginmanager.get_plugin("terminalprogress") assert plugin is None + def test_disabled_for_iterm2(self, pytester: pytest.Pytester, monkeypatch) -> None: + """Should not register the plugin on iTerm2 terminal since it interprets + OSC 9;4 as desktop notifications, not progress (#13896).""" + monkeypatch.setenv( + "ITERM_SESSION_ID", "w0t1p0:3DB6DF06-FE11-40C3-9A66-9E10A193A632" + ) + with patch.object(sys.stdout, "isatty", return_value=True): + config = pytester.parseconfigure() + plugin = config.pluginmanager.get_plugin("terminalprogress") + assert plugin is None + @pytest.mark.parametrize( ["state", "progress", "expected"], [ From 908a0ba5644781de49cedad7f4b728c316d25c61 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 10 Nov 2025 19:32:10 +0200 Subject: [PATCH 05/74] Merge pull request #13906 from bluetech/doc-fix-verbosity-toml doc: fix toml type of verbosity options in API reference (cherry picked from commit e82651074d18a9a905d3beefb62bd7eb8196b6cd) --- changelog/13904.bugfix.rst | 1 + doc/en/reference/reference.rst | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 changelog/13904.bugfix.rst diff --git a/changelog/13904.bugfix.rst b/changelog/13904.bugfix.rst new file mode 100644 index 00000000000..739c16e12bd --- /dev/null +++ b/changelog/13904.bugfix.rst @@ -0,0 +1 @@ +Fixed the TOML type of the verbosity settings in the API reference from number to string. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 1c51b712ee1..139140afdfa 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -2596,7 +2596,7 @@ passed multiple times. The expected format is ``name=value``. For example:: .. code-block:: toml [pytest] - verbosity_assertions = 2 + verbosity_assertions = "2" .. tab:: ini @@ -2618,7 +2618,7 @@ passed multiple times. The expected format is ``name=value``. For example:: .. code-block:: toml [pytest] - verbosity_subtests = 1 + verbosity_subtests = "1" .. tab:: ini @@ -2645,7 +2645,7 @@ passed multiple times. The expected format is ``name=value``. For example:: .. code-block:: toml [pytest] - verbosity_test_cases = 2 + verbosity_test_cases = "2" .. tab:: ini From 17b82a4643bd3b1b57bf48ec997f4bc893b4c17a Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Mon, 10 Nov 2025 18:22:23 +0000 Subject: [PATCH 06/74] Restore skipping tests via `raise unittest.SkipTest` (#13912) (#13916) Revert "Remove unused code related to `nose` (#13528)" This reverts commit a620d24376eb2c4bc964f2b6efcc694a4adbbe21 and modifies it adding tests and docs. Fixes #13895 (cherry picked from commit 6a47389c7813ec7ed395c0279c4b7685fde9f95a) Co-authored-by: Bruno Oliveira --- changelog/13895.bugfix.rst | 1 + src/_pytest/unittest.py | 8 +++++++ testing/test_unittest.py | 43 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 changelog/13895.bugfix.rst diff --git a/changelog/13895.bugfix.rst b/changelog/13895.bugfix.rst new file mode 100644 index 00000000000..5acd47cff38 --- /dev/null +++ b/changelog/13895.bugfix.rst @@ -0,0 +1 @@ +Restore support for skipping tests via ``raise unittest.SkipTest``. diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 64321050853..7498f1b0002 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -476,6 +476,14 @@ def pytest_runtest_makereport(item: Item, call: CallInfo[None]) -> None: except AttributeError: pass + # Convert unittest.SkipTest to pytest.skip. + # This covers explicit `raise unittest.SkipTest`. + unittest = sys.modules.get("unittest") + if unittest and call.excinfo and isinstance(call.excinfo.value, unittest.SkipTest): + excinfo = call.excinfo + call2 = CallInfo[None].from_call(lambda: skip(str(excinfo.value)), call.when) + call.excinfo = call2.excinfo + def _is_skipped(obj) -> bool: """Return True if the given object has been marked with @unittest.skip.""" diff --git a/testing/test_unittest.py b/testing/test_unittest.py index d6757077847..395c9fe647e 100644 --- a/testing/test_unittest.py +++ b/testing/test_unittest.py @@ -1094,6 +1094,49 @@ def test_two(self): result.assert_outcomes(passed=2) +def test_skip_setup_class(pytester: Pytester) -> None: + """Skipping tests in a class by raising unittest.SkipTest in `setUpClass` (#13985).""" + pytester.makepyfile( + """ + import unittest + + class Test(unittest.TestCase): + + @classmethod + def setUpClass(cls): + raise unittest.SkipTest('Skipping setupclass') + + def test_foo(self): + assert False + + def test_bar(self): + assert False + """ + ) + result = pytester.runpytest() + result.assert_outcomes(skipped=2) + + +def test_unittest_skip_function(pytester: Pytester) -> None: + """ + Ensure raising an explicit unittest.SkipTest skips standard pytest functions. + + Support for this is debatable -- technically we only support unittest.SkipTest in TestCase subclasses, + but stating this support here in this test because users currently expect this to work, + so if we ever break it we at least know we are breaking this use case (#13985). + """ + pytester.makepyfile( + """ + import unittest + + def test_foo(): + raise unittest.SkipTest('Skipping test_foo') + """ + ) + result = pytester.runpytest() + result.assert_outcomes(skipped=1) + + def test_testcase_handles_init_exceptions(pytester: Pytester) -> None: """ Regression test to make sure exceptions in the __init__ method are bubbled up correctly. From 32602a3ae3f1c122b9a93d72e3715bf732a137b9 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 10 Nov 2025 22:39:55 +0200 Subject: [PATCH 07/74] Merge pull request #13918 from bluetech/restore-pytest-asyncio testing: restore pytest-asyncio integration test (cherry picked from commit 3fe80c714fe18f2926b42997b55b05e6b2e90ab0) --- testing/plugins_integration/pytest.ini | 3 +-- testing/plugins_integration/requirements.txt | 3 +-- tox.ini | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/testing/plugins_integration/pytest.ini b/testing/plugins_integration/pytest.ini index 258b4143177..b0eb9c3806f 100644 --- a/testing/plugins_integration/pytest.ini +++ b/testing/plugins_integration/pytest.ini @@ -1,7 +1,6 @@ [pytest] strict_markers = True -; Temporarily disabled until adds support for pytest 9. -; asyncio_mode = strict +asyncio_mode = strict filterwarnings = error::pytest.PytestWarning ignore:usefixtures.* without arguments has no effect:pytest.PytestWarning diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index d62f25743f0..f33ac01f848 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,7 +1,6 @@ anyio[trio]==4.11.0 django==5.2.8 -# Temporarily disabled until adds support for pytest 9. -#pytest-asyncio==1.2.0 +pytest-asyncio==1.3.0 pytest-bdd==8.1.0 pytest-cov==7.0.0 pytest-django==4.11.1 diff --git a/tox.ini b/tox.ini index bbd62b7e7c5..b6fcecc886a 100644 --- a/tox.ini +++ b/tox.ini @@ -175,8 +175,7 @@ commands = pytest --html=simple.html simple_integration.py pytest --reruns 5 simple_integration.py pytest_rerunfailures_integration.py pytest pytest_anyio_integration.py - # Temporarily disabled until adds support for pytest 9. - # pytest pytest_asyncio_integration.py + pytest pytest_asyncio_integration.py pytest pytest_mock_integration.py pytest pytest_trio_integration.py pytest pytest_twisted_integration.py From 3b43b31c771c743e5283ec94febad77e360b7cfb Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 11 Nov 2025 09:48:48 +0200 Subject: [PATCH 08/74] Merge pull request #13919 from bluetech/doc-syntax-fix doc: a rendering fix & update RTD to Python 3.13 (cherry picked from commit d587e0cf84bd815f4545a5091ab26f992580ac37) --- .readthedocs.yaml | 2 +- doc/en/explanation/goodpractices.rst | 4 ++-- tox.ini | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index f7370f1bb98..6380b34adec 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -17,7 +17,7 @@ build: os: ubuntu-24.04 tools: python: >- - 3.12 + 3.13 apt_packages: - inkscape jobs: diff --git a/doc/en/explanation/goodpractices.rst b/doc/en/explanation/goodpractices.rst index d97dda06417..4920309b9d6 100644 --- a/doc/en/explanation/goodpractices.rst +++ b/doc/en/explanation/goodpractices.rst @@ -354,7 +354,7 @@ See the :confval:`strict` documentation for the options it enables and their eff If pytest adds new strictness options in the future, they will also be enabled in strict mode. Therefore, you should only enable strict mode if you use a pinned/locked version of pytest, or if you want to proactively adopt new strictness options as they are added. -If you don't want to automatically pick up new options, you can enable options individually:: +If you don't want to automatically pick up new options, you can enable options individually: .. tab:: toml @@ -376,7 +376,7 @@ If you don't want to automatically pick up new options, you can enable options i strict_parametrization_ids = true strict_xfail = true -If you want to use strict mode but having trouble with a specific option, you can turn it off individually:: +If you want to use strict mode but having trouble with a specific option, you can turn it off individually: .. tab:: toml diff --git a/tox.ini b/tox.ini index b6fcecc886a..5c2106ee5b4 100644 --- a/tox.ini +++ b/tox.ini @@ -111,7 +111,7 @@ setenv = description = build the documentation site under \ `{toxinidir}{/}doc{/}en{/}_build{/}html` with `{basepython}` -basepython = python3.12 # sync with rtd to get errors +basepython = python3.13 # Sync with .readthedocs.yaml to get errors. usedevelop = True deps = -r{toxinidir}/doc/en/requirements.txt From b4e3973505a2b7a2caa17ccc392d91a6ad73e122 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 11 Nov 2025 09:51:17 +0200 Subject: [PATCH 09/74] Merge pull request #13922 from bluetech/fix-argparse-userwarning config: fix `UserWarning: Do not expect file_or_dir` on some Python 3.12 and 3.13 point versions (cherry picked from commit 3d80757431c209eaae411909119bcc38a6847739) --- changelog/13910.bugfix.rst | 1 + src/_pytest/config/argparsing.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelog/13910.bugfix.rst diff --git a/changelog/13910.bugfix.rst b/changelog/13910.bugfix.rst new file mode 100644 index 00000000000..f399f95b375 --- /dev/null +++ b/changelog/13910.bugfix.rst @@ -0,0 +1 @@ +Fixed `UserWarning: Do not expect file_or_dir` on some earlier Python 3.12 and 3.13 point versions. diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index 995408800a8..8216ad8b226 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -170,7 +170,7 @@ def parse_known_and_unknown_args( arguments, and a list of unknown flag arguments. """ strargs = [os.fspath(x) for x in args] - if sys.version_info < (3, 12): + if sys.version_info < (3, 12, 8) or (3, 13) <= sys.version_info < (3, 13, 1): # Older argparse have a bugged parse_known_intermixed_args. namespace, unknown = self.optparser.parse_known_args(strargs, namespace) assert namespace is not None From 15f93b332c1c3ec9c200c0ad3d55af5a2158e0db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BA=F0=9F=87=A6=20Sviatoslav=20Sydorenko=20=28?= =?UTF-8?q?=D0=A1=D0=B2=D1=8F=D1=82=D0=BE=D1=81=D0=BB=D0=B0=D0=B2=20=D0=A1?= =?UTF-8?q?=D0=B8=D0=B4=D0=BE=D1=80=D0=B5=D0=BD=D0=BA=D0=BE=29?= Date: Tue, 11 Nov 2025 20:28:42 +0100 Subject: [PATCH 10/74] Merge pull request #13933 from webknjaz/maintenance/tox-pep517-env-setuptools-scm-pretend-env-var MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 📦 Pass desired release to PEP 517 tox env (cherry picked from commit ce8b8a7b4b360ac5f3953b8c3b8b59e6bb420f37) --- changelog/13933.contrib.rst | 4 ++++ changelog/13933.packaging.rst | 1 + tox.ini | 23 ++++++++++++++++++++--- 3 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 changelog/13933.contrib.rst create mode 120000 changelog/13933.packaging.rst diff --git a/changelog/13933.contrib.rst b/changelog/13933.contrib.rst new file mode 100644 index 00000000000..feab3e0dc03 --- /dev/null +++ b/changelog/13933.contrib.rst @@ -0,0 +1,4 @@ +The tox configuration has been adjusted to make sure the desired +version string can be passed into its :ref:`package_env` through +the ``SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PYTEST`` environment +variable as a part of the release process -- by :user:`webknjaz`. diff --git a/changelog/13933.packaging.rst b/changelog/13933.packaging.rst new file mode 120000 index 00000000000..79139f98eed --- /dev/null +++ b/changelog/13933.packaging.rst @@ -0,0 +1 @@ +13933.contrib.rst \ No newline at end of file diff --git a/tox.ini b/tox.ini index 5c2106ee5b4..2e91ddcb2d6 100644 --- a/tox.ini +++ b/tox.ini @@ -23,6 +23,26 @@ envlist = +[pkgenv] +# NOTE: This section tweaks how Tox manages the PEP 517 build +# NOTE: environment where it assembles wheels (editable and regular) +# NOTE: for further installing them into regular testenvs. +# +# NOTE: `[testenv:.pkg]` does not work due to a regression in tox v4.14.1 +# NOTE: so `[pkgenv]` is being used in place of it. +# Refs: +# * https://github.com/tox-dev/tox/pull/3237 +# * https://github.com/tox-dev/tox/issues/3238 +# * https://github.com/tox-dev/tox/issues/3292 +# * https://hynek.me/articles/turbo-charge-tox/ +# +# NOTE: The `SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PYTEST` environment +# NOTE: variable allows enforcing a pre-determined version for use in +# NOTE: the wheel being installed into usual testenvs. +pass_env = + SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PYTEST + + [testenv] description = run the tests @@ -49,7 +69,6 @@ passenv = COVERAGE_* PYTEST_ADDOPTS TERM - SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PYTEST CI setenv = _PYTEST_TOX_DEFAULT_POSARGS={env:_PYTEST_TOX_POSARGS_DOCTESTING:} {env:_PYTEST_TOX_POSARGS_LSOF:} {env:_PYTEST_TOX_POSARGS_XDIST:} {env:_PYTEST_FILES:} @@ -141,8 +160,6 @@ setenv = description = regenerate documentation examples under `{basepython}` changedir = doc/en -passenv = - SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PYTEST deps = PyYAML regendoc>=0.8.1 From a999997e36c53d189ecded3369bf35bfe2be96ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BA=F0=9F=87=A6=20Sviatoslav=20Sydorenko=20=28?= =?UTF-8?q?=D0=A1=D0=B2=D1=8F=D1=82=D0=BE=D1=81=D0=BB=D0=B0=D0=B2=20=D0=A1?= =?UTF-8?q?=D0=B8=D0=B4=D0=BE=D1=80=D0=B5=D0=BD=D0=BA=D0=BE=29?= Date: Wed, 12 Nov 2025 04:00:21 +0100 Subject: [PATCH 11/74] Merge pull request #13941 from nicoddemus/min-pre-commit-version Add minimum-pre-commit-version (cherry picked from commit bef7d34f13d71f961a9dabf9d151dbe08ceb25f2) --- .pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a4af51ee0f2..e77d4cf52de 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,3 +1,4 @@ +minimum_pre_commit_version: "4.4.0" repos: - repo: https://github.com/astral-sh/ruff-pre-commit rev: "v0.14.3" From a9f7e6ed579b8844e302067b7f05122b82993355 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Wed, 12 Nov 2025 10:31:41 +0000 Subject: [PATCH 12/74] =?UTF-8?q?=F0=9F=A7=AA=20Run=20`gh=20release`=20w/o?= =?UTF-8?q?=20Git=20in=20CI/CD=20(#13942)=20(#13947)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🧪 Run `gh release` w/o Git in CI/CD It is possible to use `gh release create --repo=` [[1]] so that GH CLI does not need to infer the repository information from the Git repository. GH CLI supports passing such options via environment values [[2]], which is what this patch makes use of. It's a follow-up for #13891. [1]: https://cli.github.com/manual/gh_release_create [2]: https://cli.github.com/manual/gh_help_environment * 📝 Add a change note for PRs #13942 and #13891 (cherry picked from commit 21ad5c65c979dfd2352784b3e074cd34f208dfdf) Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) --- .github/workflows/deploy.yml | 6 +----- changelog/13891.contrib.rst | 1 + changelog/13942.contrib.rst | 3 +++ 3 files changed, 5 insertions(+), 5 deletions(-) create mode 120000 changelog/13891.contrib.rst create mode 100644 changelog/13942.contrib.rst diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ad7cc029c5e..c44ef2d8210 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -120,11 +120,6 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@v5 - with: - fetch-depth: 0 - persist-credentials: true - - name: Download Package uses: actions/download-artifact@v6 with: @@ -140,6 +135,7 @@ jobs: - name: Publish GitHub Release env: VERSION: ${{ github.event.inputs.version }} + GH_REPO: ${{ github.repository }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | gh release create --notes-file gh-release-notes.md --verify-tag "$VERSION" dist/* diff --git a/changelog/13891.contrib.rst b/changelog/13891.contrib.rst new file mode 120000 index 00000000000..b5cf5102ff8 --- /dev/null +++ b/changelog/13891.contrib.rst @@ -0,0 +1 @@ +13942.contrib.rst \ No newline at end of file diff --git a/changelog/13942.contrib.rst b/changelog/13942.contrib.rst new file mode 100644 index 00000000000..cdf23e68455 --- /dev/null +++ b/changelog/13942.contrib.rst @@ -0,0 +1,3 @@ +The CI/CD part of the release automation is now capable of +creating GitHub Releases without having a Git checkout on +disk -- by :user:`bluetech` and :user:`webknjaz`. From 0a497c7b213ea950821319fd80dce219b0033f32 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Wed, 12 Nov 2025 09:16:22 -0300 Subject: [PATCH 13/74] regendoc: remove CI environment variables (#13950) (#13951) pytest auto-detects and uses more verbose output when running in CI. Change tox:regendoc to remove those environment variables, because we do not want extra verbose output in the user documentation. See #13938 (comment). (cherry picked from commit 82e9b97caf576de2144b414c58edc87fed5873e7) Co-authored-by: Bruno Oliveira --- src/_pytest/compat.py | 1 + tox.ini | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 2f5a4c863f9..72c3d0918fb 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -309,5 +309,6 @@ def __call__(self) -> bool: def running_on_ci() -> bool: """Check if we're currently running on a CI system.""" # Only enable CI mode if one of these env variables is defined and non-empty. + # Note: review `regendoc` tox env in case this list is changed. env_vars = ["CI", "BUILD_NUMBER"] return any(os.environ.get(var) for var in env_vars) diff --git a/tox.ini b/tox.ini index 2e91ddcb2d6..70b439f7573 100644 --- a/tox.ini +++ b/tox.ini @@ -171,6 +171,10 @@ commands = setenv = # We don't want this warning to reach regen output. PYTHONWARNDEFAULTENCODING= + # Remove CI markers: pytest auto-detects those and uses more verbose output, which is undesirable + # for the example documentation. + CI= + BUILD_NUMBER= [testenv:plugins] description = From d1b64aa60b9e1a0fcfaf03af7ebeb185f1024a87 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Wed, 12 Nov 2025 12:20:38 +0000 Subject: [PATCH 14/74] Prepare release version 9.0.1 --- changelog/13891.contrib.rst | 1 - changelog/13895.bugfix.rst | 1 - changelog/13896.bugfix.rst | 1 - changelog/13904.bugfix.rst | 1 - changelog/13910.bugfix.rst | 1 - changelog/13933.contrib.rst | 4 --- changelog/13933.packaging.rst | 1 - changelog/13942.contrib.rst | 3 -- doc/en/announce/index.rst | 1 + doc/en/announce/release-9.0.1.rst | 18 +++++++++++ doc/en/builtin.rst | 2 +- doc/en/changelog.rst | 43 +++++++++++++++++++++++++ doc/en/example/customdirectory.rst | 4 +-- doc/en/example/markers.rst | 30 ++++++++--------- doc/en/example/nonpython.rst | 6 ++-- doc/en/example/parametrize.rst | 20 ++++++------ doc/en/example/pythoncollection.rst | 10 +++--- doc/en/example/reportingdemo.rst | 2 +- doc/en/example/simple.rst | 22 ++++++------- doc/en/getting-started.rst | 4 +-- doc/en/how-to/assert.rst | 4 +-- doc/en/how-to/cache.rst | 8 ++--- doc/en/how-to/capture-stdout-stderr.rst | 2 +- doc/en/how-to/capture-warnings.rst | 2 +- doc/en/how-to/doctest.rst | 4 +-- doc/en/how-to/fixtures.rst | 16 ++++----- doc/en/how-to/output.rst | 6 ++-- doc/en/how-to/parametrize.rst | 4 +-- doc/en/how-to/tmp_path.rst | 2 +- doc/en/how-to/unittest.rst | 2 +- doc/en/how-to/writing_plugins.rst | 2 +- doc/en/index.rst | 2 +- 32 files changed, 139 insertions(+), 90 deletions(-) delete mode 120000 changelog/13891.contrib.rst delete mode 100644 changelog/13895.bugfix.rst delete mode 100644 changelog/13896.bugfix.rst delete mode 100644 changelog/13904.bugfix.rst delete mode 100644 changelog/13910.bugfix.rst delete mode 100644 changelog/13933.contrib.rst delete mode 120000 changelog/13933.packaging.rst delete mode 100644 changelog/13942.contrib.rst create mode 100644 doc/en/announce/release-9.0.1.rst diff --git a/changelog/13891.contrib.rst b/changelog/13891.contrib.rst deleted file mode 120000 index b5cf5102ff8..00000000000 --- a/changelog/13891.contrib.rst +++ /dev/null @@ -1 +0,0 @@ -13942.contrib.rst \ No newline at end of file diff --git a/changelog/13895.bugfix.rst b/changelog/13895.bugfix.rst deleted file mode 100644 index 5acd47cff38..00000000000 --- a/changelog/13895.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Restore support for skipping tests via ``raise unittest.SkipTest``. diff --git a/changelog/13896.bugfix.rst b/changelog/13896.bugfix.rst deleted file mode 100644 index 821af0c96b4..00000000000 --- a/changelog/13896.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -The terminal progress plugin added in pytest 9.0 is now automatically disabled when iTerm2 is detected, it generated desktop notifications instead of the desired functionality. diff --git a/changelog/13904.bugfix.rst b/changelog/13904.bugfix.rst deleted file mode 100644 index 739c16e12bd..00000000000 --- a/changelog/13904.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed the TOML type of the verbosity settings in the API reference from number to string. diff --git a/changelog/13910.bugfix.rst b/changelog/13910.bugfix.rst deleted file mode 100644 index f399f95b375..00000000000 --- a/changelog/13910.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed `UserWarning: Do not expect file_or_dir` on some earlier Python 3.12 and 3.13 point versions. diff --git a/changelog/13933.contrib.rst b/changelog/13933.contrib.rst deleted file mode 100644 index feab3e0dc03..00000000000 --- a/changelog/13933.contrib.rst +++ /dev/null @@ -1,4 +0,0 @@ -The tox configuration has been adjusted to make sure the desired -version string can be passed into its :ref:`package_env` through -the ``SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PYTEST`` environment -variable as a part of the release process -- by :user:`webknjaz`. diff --git a/changelog/13933.packaging.rst b/changelog/13933.packaging.rst deleted file mode 120000 index 79139f98eed..00000000000 --- a/changelog/13933.packaging.rst +++ /dev/null @@ -1 +0,0 @@ -13933.contrib.rst \ No newline at end of file diff --git a/changelog/13942.contrib.rst b/changelog/13942.contrib.rst deleted file mode 100644 index cdf23e68455..00000000000 --- a/changelog/13942.contrib.rst +++ /dev/null @@ -1,3 +0,0 @@ -The CI/CD part of the release automation is now capable of -creating GitHub Releases without having a Git checkout on -disk -- by :user:`bluetech` and :user:`webknjaz`. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index f5e00d34cdb..2859e6210ff 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-9.0.1 release-9.0.0 release-8.4.2 release-8.4.1 diff --git a/doc/en/announce/release-9.0.1.rst b/doc/en/announce/release-9.0.1.rst new file mode 100644 index 00000000000..46af130e03c --- /dev/null +++ b/doc/en/announce/release-9.0.1.rst @@ -0,0 +1,18 @@ +pytest-9.0.1 +======================================= + +pytest 9.0.1 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. + +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 +* 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index a7b0ff2e5c8..5b66626fd20 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -18,7 +18,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a $ pytest --fixtures -v =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collected 0 items diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 5220afc46e3..85a509dff3f 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -31,6 +31,49 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 9.0.1 (2025-11-12) +========================= + +Bug fixes +--------- + +- `#13895 `_: Restore support for skipping tests via ``raise unittest.SkipTest``. + + +- `#13896 `_: The terminal progress plugin added in pytest 9.0 is now automatically disabled when iTerm2 is detected, it generated desktop notifications instead of the desired functionality. + + +- `#13904 `_: Fixed the TOML type of the verbosity settings in the API reference from number to string. + + +- `#13910 `_: Fixed `UserWarning: Do not expect file_or_dir` on some earlier Python 3.12 and 3.13 point versions. + + + +Packaging updates and notes for downstreams +------------------------------------------- + +- `#13933 `_: The tox configuration has been adjusted to make sure the desired + version string can be passed into its :ref:`package_env` through + the ``SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PYTEST`` environment + variable as a part of the release process -- by :user:`webknjaz`. + + + +Contributor-facing changes +-------------------------- + +- `#13891 `_, `#13942 `_: The CI/CD part of the release automation is now capable of + creating GitHub Releases without having a Git checkout on + disk -- by :user:`bluetech` and :user:`webknjaz`. + + +- `#13933 `_: The tox configuration has been adjusted to make sure the desired + version string can be passed into its :ref:`package_env` through + the ``SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PYTEST`` environment + variable as a part of the release process -- by :user:`webknjaz`. + + pytest 9.0.0 (2025-11-05) ========================= diff --git a/doc/en/example/customdirectory.rst b/doc/en/example/customdirectory.rst index 1e4d7e370de..6e326352a7e 100644 --- a/doc/en/example/customdirectory.rst +++ b/doc/en/example/customdirectory.rst @@ -42,7 +42,7 @@ An you can now execute the test specification: customdirectory $ pytest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project/customdirectory configfile: pytest.ini collected 2 items @@ -62,7 +62,7 @@ You can verify that your custom collector appears in the collection tree: customdirectory $ pytest --collect-only =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project/customdirectory configfile: pytest.ini collected 2 items diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst index afb1ece0fe8..cbe417e8a3e 100644 --- a/doc/en/example/markers.rst +++ b/doc/en/example/markers.rst @@ -47,7 +47,7 @@ You can then restrict a test run to only run tests marked with ``webtest``: $ pytest -v -m webtest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 4 items / 3 deselected / 1 selected @@ -62,7 +62,7 @@ Or the inverse, running all tests except the webtest ones: $ pytest -v -m "not webtest" =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 4 items / 1 deselected / 3 selected @@ -82,7 +82,7 @@ keyword arguments, e.g. to run only tests marked with ``device`` and the specifi $ pytest -v -m "device(serial='123')" =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 4 items / 3 deselected / 1 selected @@ -106,7 +106,7 @@ tests based on their module, class, method, or function name: $ pytest -v test_server.py::TestClass::test_method =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 1 item @@ -121,7 +121,7 @@ You can also select on the class: $ pytest -v test_server.py::TestClass =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 1 item @@ -136,7 +136,7 @@ Or select multiple nodes: $ pytest -v test_server.py::TestClass test_server.py::test_send_http =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 2 items @@ -180,7 +180,7 @@ The expression matching is now case-insensitive. $ pytest -v -k http # running with the above defined example module =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 4 items / 3 deselected / 1 selected @@ -195,7 +195,7 @@ And you can also run all tests except the ones that match the keyword: $ pytest -k "not send_http" -v =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 4 items / 1 deselected / 3 selected @@ -212,7 +212,7 @@ Or to select "http" and "quick" tests: $ pytest -k "http or quick" -v =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 4 items / 2 deselected / 2 selected @@ -418,7 +418,7 @@ the test needs: $ pytest -E stage2 =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 1 item @@ -432,7 +432,7 @@ and here is one that specifies exactly the environment needed: $ pytest -E stage1 =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 1 item @@ -625,7 +625,7 @@ then you will see two tests skipped and two executed tests as expected: $ pytest -rs # this option reports skip reasons =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 4 items @@ -641,7 +641,7 @@ Note that if you specify a platform via the marker-command line option like this $ pytest -m linux =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 4 items / 3 deselected / 1 selected @@ -704,7 +704,7 @@ We can now use the ``-m option`` to select one set: $ pytest -m interface --tb=short =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 4 items / 2 deselected / 2 selected @@ -730,7 +730,7 @@ or to select both "event" and "interface" tests: $ pytest -m "interface or event" --tb=short =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 4 items / 1 deselected / 3 selected diff --git a/doc/en/example/nonpython.rst b/doc/en/example/nonpython.rst index a8d172937c5..bb879fb51ab 100644 --- a/doc/en/example/nonpython.rst +++ b/doc/en/example/nonpython.rst @@ -28,7 +28,7 @@ now execute the test specification: nonpython $ pytest test_simple.yaml =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project/nonpython collected 2 items @@ -64,7 +64,7 @@ consulted when reporting in ``verbose`` mode: nonpython $ pytest -v =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project/nonpython collecting ... collected 2 items @@ -90,7 +90,7 @@ interesting to just look at the collection tree: nonpython $ pytest --collect-only =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project/nonpython collected 2 items diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index b27dae18c32..1cbeee27aad 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -158,11 +158,11 @@ objects, they are still using the default pytest representation: $ pytest test_time.py --collect-only =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 8 items - + @@ -221,7 +221,7 @@ this is a fully self-contained example which you can run with: $ pytest test_scenarios.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 4 items @@ -235,11 +235,11 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia $ pytest --collect-only test_scenarios.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 4 items - + @@ -314,11 +314,11 @@ Let's first see how it looks like at collection time: $ pytest test_backends.py --collect-only =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 2 items - + @@ -413,7 +413,7 @@ The result of this test will be successful: $ pytest -v test_indirect_list.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 1 item @@ -566,7 +566,7 @@ If you run this with reporting for skips enabled: $ pytest -rs test_module.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 2 items @@ -627,7 +627,7 @@ Then run ``pytest`` with verbose mode and with only the ``basic`` marker: $ pytest -v -m basic =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 24 items / 21 deselected / 3 selected diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 09489418773..eba40d50d1b 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -137,12 +137,12 @@ The test collection would look like this: $ pytest --collect-only =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project configfile: pytest.toml collected 2 items - + @@ -200,12 +200,12 @@ You can always peek at the collection tree without running tests like this: . $ pytest --collect-only pythoncollection.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project configfile: pytest.toml collected 3 items - + @@ -284,7 +284,7 @@ file will be left out: $ pytest --collect-only =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project configfile: pytest.toml collected 0 items diff --git a/doc/en/example/reportingdemo.rst b/doc/en/example/reportingdemo.rst index 8040ee9b957..29ba190b7e7 100644 --- a/doc/en/example/reportingdemo.rst +++ b/doc/en/example/reportingdemo.rst @@ -9,7 +9,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: assertion $ pytest failure_demo.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project/assertion collected 44 items diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index e150e7ca00b..09335153ad1 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -235,7 +235,7 @@ directory with the above conftest.py: $ pytest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 0 items @@ -299,7 +299,7 @@ and when running it will see a skipped "slow" test: $ pytest -rs # "-rs" means report details on the little 's' =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 2 items @@ -315,7 +315,7 @@ Or run it including the ``slow`` marked test: $ pytest --runslow =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 2 items @@ -444,7 +444,7 @@ which will add the string to the test header accordingly: $ pytest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y project deps: mylib-1.1 rootdir: /home/sweet/project collected 0 items @@ -472,7 +472,7 @@ which will add info only when run with "--v": $ pytest -v =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache info1: did you know that ... did you? @@ -487,7 +487,7 @@ and nothing when run plainly: $ pytest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 0 items @@ -526,7 +526,7 @@ Now we can profile which test functions execute the slowest: $ pytest --durations=3 =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 3 items @@ -632,7 +632,7 @@ If we run this: $ pytest -rx =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 4 items @@ -714,7 +714,7 @@ We can run this: $ pytest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 7 items @@ -836,7 +836,7 @@ and run them: $ pytest test_module.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 2 items @@ -947,7 +947,7 @@ and run it: $ pytest -s test_module.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 3 items diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index ec1ef60a605..e1932d96ef9 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -20,7 +20,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 9.0.0 + pytest 9.0.1 .. _`simpletest`: @@ -45,7 +45,7 @@ The test $ pytest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 1 item diff --git a/doc/en/how-to/assert.rst b/doc/en/how-to/assert.rst index 4dfceda0fad..a1fce9f8b90 100644 --- a/doc/en/how-to/assert.rst +++ b/doc/en/how-to/assert.rst @@ -29,7 +29,7 @@ you will see the return value of the function call: $ pytest test_assert1.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 1 item @@ -404,7 +404,7 @@ if you run this module: $ pytest test_assert2.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 1 item diff --git a/doc/en/how-to/cache.rst b/doc/en/how-to/cache.rst index e3209b79359..bfc1902cae0 100644 --- a/doc/en/how-to/cache.rst +++ b/doc/en/how-to/cache.rst @@ -86,7 +86,7 @@ If you then run it with ``--lf``: $ pytest --lf =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 2 items run-last-failure: rerun previous 2 failures @@ -132,7 +132,7 @@ of ``FF`` and dots): $ pytest --ff =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 50 items 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 =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project cachedir: /home/sweet/project/.pytest_cache --------------------------- cache values for '*' --------------------------- @@ -301,7 +301,7 @@ filtering: $ pytest --cache-show example/* =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project cachedir: /home/sweet/project/.pytest_cache ----------------------- cache values for 'example/*' ----------------------- diff --git a/doc/en/how-to/capture-stdout-stderr.rst b/doc/en/how-to/capture-stdout-stderr.rst index e6affd80ea1..cd5cb6d798f 100644 --- a/doc/en/how-to/capture-stdout-stderr.rst +++ b/doc/en/how-to/capture-stdout-stderr.rst @@ -89,7 +89,7 @@ of the failing function and hide the other one: $ pytest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 2 items diff --git a/doc/en/how-to/capture-warnings.rst b/doc/en/how-to/capture-warnings.rst index 8ed546bedf7..9cefdc39307 100644 --- a/doc/en/how-to/capture-warnings.rst +++ b/doc/en/how-to/capture-warnings.rst @@ -28,7 +28,7 @@ Running pytest now produces this output: $ pytest test_show_warnings.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 1 item diff --git a/doc/en/how-to/doctest.rst b/doc/en/how-to/doctest.rst index 601f5c0afd0..de6679bc452 100644 --- a/doc/en/how-to/doctest.rst +++ b/doc/en/how-to/doctest.rst @@ -30,7 +30,7 @@ then you can just invoke ``pytest`` directly: $ pytest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 1 item @@ -58,7 +58,7 @@ and functions, including from test modules: $ pytest --doctest-modules =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 2 items diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index 0c4ddb8b4dc..40e13e2afa8 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -433,7 +433,7 @@ marked ``smtp_connection`` fixture function. Running the test looks like this: $ pytest test_module.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 2 items @@ -773,7 +773,7 @@ For yield fixtures, the first teardown code to run is from the right-most fixtur $ pytest -s test_finalizers.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 1 item @@ -807,7 +807,7 @@ For finalizers, the first fixture to run is last call to `request.addfinalizer`. $ pytest -s test_finalizers.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 1 item @@ -1419,11 +1419,11 @@ Running the above tests results in the following test IDs being used: $ pytest --collect-only =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 12 items - + @@ -1474,7 +1474,7 @@ Running this test will *skip* the invocation of ``data_set`` with value ``2``: $ pytest test_fixture_marks.py -v =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 3 items @@ -1524,7 +1524,7 @@ Here we declare an ``app`` fixture which receives the previously defined $ pytest -v test_appsetup.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 2 items @@ -1604,7 +1604,7 @@ Let's run the tests in verbose mode and with looking at the print-output: $ pytest -v -s test_module.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 8 items diff --git a/doc/en/how-to/output.rst b/doc/en/how-to/output.rst index e03f477b22d..ec4ca05838e 100644 --- a/doc/en/how-to/output.rst +++ b/doc/en/how-to/output.rst @@ -421,7 +421,7 @@ Example: $ pytest -ra =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 6 items @@ -478,7 +478,7 @@ More than one character can be used, so for example to only see failed and skipp $ pytest -rfs =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 6 items @@ -513,7 +513,7 @@ captured output: $ pytest -rpP =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 6 items diff --git a/doc/en/how-to/parametrize.rst b/doc/en/how-to/parametrize.rst index dba2ac0b91e..5de28472705 100644 --- a/doc/en/how-to/parametrize.rst +++ b/doc/en/how-to/parametrize.rst @@ -57,7 +57,7 @@ them in turn: $ pytest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 3 items @@ -177,7 +177,7 @@ Let's run this: $ pytest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 3 items diff --git a/doc/en/how-to/tmp_path.rst b/doc/en/how-to/tmp_path.rst index d19950431e5..04c663bb986 100644 --- a/doc/en/how-to/tmp_path.rst +++ b/doc/en/how-to/tmp_path.rst @@ -35,7 +35,7 @@ Running this would result in a passed test except for the last $ pytest test_tmp_path.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 1 item diff --git a/doc/en/how-to/unittest.rst b/doc/en/how-to/unittest.rst index a8c56c266bd..12511fed262 100644 --- a/doc/en/how-to/unittest.rst +++ b/doc/en/how-to/unittest.rst @@ -137,7 +137,7 @@ the ``self.db`` values in the traceback: $ pytest test_unittest_db.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 2 items diff --git a/doc/en/how-to/writing_plugins.rst b/doc/en/how-to/writing_plugins.rst index 6382edc4797..ec10c0e261c 100644 --- a/doc/en/how-to/writing_plugins.rst +++ b/doc/en/how-to/writing_plugins.rst @@ -446,7 +446,7 @@ in our configuration file to tell pytest where to look for example files. $ pytest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project configfile: pytest.toml collected 2 items diff --git a/doc/en/index.rst b/doc/en/index.rst index 2d9e3bed42c..b98c886d981 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -67,7 +67,7 @@ To execute it: $ pytest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 1 item From 2e333ec1abc898602627bfd40dcd3777ed217c66 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Thu, 13 Nov 2025 18:00:45 +0200 Subject: [PATCH 15/74] config: restore `config.inicfg` Fix #13955. (cherry picked from commit 173892066bbeddecb2c05ab89cccbdd5b1916a02) --- changelog/13946.bugfix.rst | 3 ++ src/_pytest/config/__init__.py | 46 ++++++++++++++++++++++++------ testing/test_config.py | 52 ++++++++++++++++++++++++++++++---- 3 files changed, 88 insertions(+), 13 deletions(-) create mode 100644 changelog/13946.bugfix.rst diff --git a/changelog/13946.bugfix.rst b/changelog/13946.bugfix.rst new file mode 100644 index 00000000000..d6cc5b703e4 --- /dev/null +++ b/changelog/13946.bugfix.rst @@ -0,0 +1,3 @@ +The private ``config.inicfg`` attribute was changed in a breaking manner in pytest 9.0.0. +Due to its usage in the ecosystem, it is now restored to working order using a compatibility shim. +It will be deprecated in pytest 9.1 and removed in pytest 10. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 9b2afe3e8b4..39817aaa523 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -11,6 +11,7 @@ from collections.abc import Iterable from collections.abc import Iterator from collections.abc import Mapping +from collections.abc import MutableMapping from collections.abc import Sequence import contextlib import copy @@ -47,6 +48,7 @@ from .compat import PathAwareHookProxy from .exceptions import PrintHelp as PrintHelp from .exceptions import UsageError as UsageError +from .findpaths import ConfigValue from .findpaths import determine_setup from _pytest import __version__ import _pytest._code @@ -980,6 +982,30 @@ def _iter_rewritable_modules(package_files: Iterable[str]) -> Iterator[str]: yield from _iter_rewritable_modules(new_package_files) +class _DeprecatedInicfgProxy(MutableMapping[str, Any]): + """Compatibility proxy for the deprecated Config.inicfg.""" + + __slots__ = ("_config",) + + def __init__(self, config: Config) -> None: + self._config = config + + def __getitem__(self, key: str) -> Any: + return self._config._inicfg[key].value + + def __setitem__(self, key: str, value: Any) -> None: + self._config._inicfg[key] = ConfigValue(value, origin="override", mode="toml") + + def __delitem__(self, key: str) -> None: + del self._config._inicfg[key] + + def __iter__(self) -> Iterator[str]: + return iter(self._config._inicfg) + + def __len__(self) -> int: + return len(self._config._inicfg) + + @final class Config: """Access to configuration values, pluginmanager and plugin hooks. @@ -1100,6 +1126,10 @@ def __init__( self.args_source = Config.ArgsSource.ARGS self.args: list[str] = [] + @property + def inicfg(self) -> _DeprecatedInicfgProxy: + return _DeprecatedInicfgProxy(self) + @property def rootpath(self) -> pathlib.Path: """The path to the :ref:`rootdir `. @@ -1376,7 +1406,7 @@ def pytest_collection(self) -> Generator[None, object, object]: def _checkversion(self) -> None: import pytest - minver_ini_value = self.inicfg.get("minversion", None) + minver_ini_value = self._inicfg.get("minversion", None) minver = minver_ini_value.value if minver_ini_value is not None else None if minver: # Imported lazily to improve start-up time. @@ -1440,7 +1470,7 @@ def _warn_or_fail_if_strict(self, message: str) -> None: def _get_unknown_ini_keys(self) -> set[str]: known_keys = self._parser._inidict.keys() | self._parser._ini_aliases.keys() - return self.inicfg.keys() - known_keys + return self._inicfg.keys() - known_keys def parse(self, args: list[str], addopts: bool = True) -> None: # Parse given cmdline arguments into this config object. @@ -1471,7 +1501,7 @@ def parse(self, args: list[str], addopts: bool = True) -> None: self._rootpath = rootpath self._inipath = inipath self._ignored_config_files = ignored_config_files - self.inicfg = inicfg + self._inicfg = inicfg self._parser.extra_info["rootdir"] = str(self.rootpath) self._parser.extra_info["inifile"] = str(self.inipath) @@ -1648,14 +1678,14 @@ def _getini(self, name: str): except KeyError as e: raise ValueError(f"unknown configuration value: {name!r}") from e - # Collect all possible values (canonical name + aliases) from inicfg. + # Collect all possible values (canonical name + aliases) from _inicfg. # Each candidate is (ConfigValue, is_canonical). candidates = [] - if canonical_name in self.inicfg: - candidates.append((self.inicfg[canonical_name], True)) + if canonical_name in self._inicfg: + candidates.append((self._inicfg[canonical_name], True)) for alias, target in self._parser._ini_aliases.items(): - if target == canonical_name and alias in self.inicfg: - candidates.append((self.inicfg[alias], False)) + if target == canonical_name and alias in self._inicfg: + candidates.append((self._inicfg[alias], False)) if not candidates: return default diff --git a/testing/test_config.py b/testing/test_config.py index 98555e04452..d28b9110413 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -60,7 +60,7 @@ def test_getcfg_and_config( _, _, cfg, _ = locate_config(Path.cwd(), [sub]) assert cfg["name"] == ConfigValue("value", origin="file", mode="ini") config = pytester.parseconfigure(str(sub)) - assert config.inicfg["name"] == ConfigValue("value", origin="file", mode="ini") + assert config._inicfg["name"] == ConfigValue("value", origin="file", mode="ini") def test_setupcfg_uses_toolpytest_with_pytest(self, pytester: Pytester) -> None: p1 = pytester.makepyfile("def test(): pass") @@ -1434,10 +1434,10 @@ def test_inifilename(self, tmp_path: Path) -> None: # this indicates this is the file used for getting configuration values assert config.inipath == inipath - assert config.inicfg.get("name") == ConfigValue( + assert config._inicfg.get("name") == ConfigValue( "value", origin="file", mode="ini" ) - assert config.inicfg.get("should_not_be_set") is None + assert config._inicfg.get("should_not_be_set") is None def test_options_on_small_file_do_not_blow_up(pytester: Pytester) -> None: @@ -2277,7 +2277,7 @@ def test_addopts_before_initini( monkeypatch.setenv("PYTEST_ADDOPTS", f"-o cache_dir={cache_dir}") config = _config_for_test config.parse([], addopts=True) - assert config.inicfg.get("cache_dir") == ConfigValue( + assert config._inicfg.get("cache_dir") == ConfigValue( cache_dir, origin="override", mode="ini" ) @@ -2318,7 +2318,7 @@ def test_override_ini_does_not_contain_paths( """Check that -o no longer swallows all options after it (#3103)""" config = _config_for_test config.parse(["-o", "cache_dir=/cache", "/some/test/path"]) - assert config.inicfg.get("cache_dir") == ConfigValue( + assert config._inicfg.get("cache_dir") == ConfigValue( "/cache", origin="override", mode="ini" ) @@ -2999,3 +2999,45 @@ def pytest_addoption(parser): with pytest.raises(TypeError, match=r"expects a string.*got int"): config.getini("string_not_string") + + +class TestInicfgDeprecation: + """Tests for the upcoming deprecation of config.inicfg.""" + + def test_inicfg_deprecated(self, pytester: Pytester) -> None: + """Test that accessing config.inicfg issues a deprecation warning (not yet).""" + pytester.makeini( + """ + [pytest] + minversion = 3.0 + """ + ) + config = pytester.parseconfig() + + inicfg = config.inicfg + + assert config.getini("minversion") == "3.0" + assert inicfg["minversion"] == "3.0" + assert inicfg.get("minversion") == "3.0" + del inicfg["minversion"] + inicfg["minversion"] = "4.0" + assert list(inicfg.keys()) == ["minversion"] + assert list(inicfg.items()) == [("minversion", "4.0")] + assert len(inicfg) == 1 + + def test_issue_13946_setting_bool_no_longer_crashes( + self, pytester: Pytester + ) -> None: + """Regression test for #13946 - setting inicfg doesn't cause a crash.""" + pytester.makepyfile( + """ + def pytest_configure(config): + config.inicfg["xfail_strict"] = True + + def test(): + pass + """ + ) + + result = pytester.runpytest() + assert result.ret == 0 From 327766ca2564f4d275cbe078e9d796aab32bbff0 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 14 Nov 2025 00:21:02 +0200 Subject: [PATCH 16/74] Merge pull request #13958 from bluetech/fix-tmpdir-retention-toml doc: fix TOML example for `tmp_path_retention_count`, it's a string (cherry picked from commit 9652bc714d0cae7f849d285aaa9f5a7e42e89ee3) --- changelog/13904.bugfix.rst | 1 + doc/en/reference/reference.rst | 4 ++-- src/_pytest/tmpdir.py | 5 ++++- 3 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 changelog/13904.bugfix.rst diff --git a/changelog/13904.bugfix.rst b/changelog/13904.bugfix.rst new file mode 100644 index 00000000000..f5a42215ca8 --- /dev/null +++ b/changelog/13904.bugfix.rst @@ -0,0 +1 @@ +Fixed the TOML type of the :confval:`tmp_path_retention_count` settings in the API reference from number to string. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 139140afdfa..496fc1b7dbc 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -2460,14 +2460,14 @@ passed multiple times. The expected format is ``name=value``. For example:: .. confval:: tmp_path_retention_count How many sessions should we keep the `tmp_path` directories, - according to `tmp_path_retention_policy`. + according to :confval:`tmp_path_retention_policy`. .. tab:: toml .. code-block:: toml [pytest] - tmp_path_retention_count = 3 + tmp_path_retention_count = "3" .. tab:: ini diff --git a/src/_pytest/tmpdir.py b/src/_pytest/tmpdir.py index dcd5784f88f..855ad273ecf 100644 --- a/src/_pytest/tmpdir.py +++ b/src/_pytest/tmpdir.py @@ -225,13 +225,16 @@ def pytest_addoption(parser: Parser) -> None: parser.addini( "tmp_path_retention_count", help="How many sessions should we keep the `tmp_path` directories, according to `tmp_path_retention_policy`.", - default=3, + default="3", + # NOTE: Would have been better as an `int` but can't change it now. + type="string", ) parser.addini( "tmp_path_retention_policy", help="Controls which directories created by the `tmp_path` fixture are kept around, based on test outcome. " "(all/failed/none)", + type="string", default="all", ) From 492918107f163571ac574a8ce592c817f065ce9a Mon Sep 17 00:00:00 2001 From: Tom Most Date: Wed, 19 Nov 2025 02:22:15 -0800 Subject: [PATCH 17/74] Fix a typo in the 9.0 changelog (#13969) (cherry picked from commit fd47511afeb024d2fbad9257d1b44310672c6a0f) --- AUTHORS | 1 + doc/en/changelog.rst | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 83509281035..a089ca678f7 100644 --- a/AUTHORS +++ b/AUTHORS @@ -459,6 +459,7 @@ TJ Bruno Tobias Diez Tobias Petersen Tom Dalton +Tom Most Tom Viner Tomáš Gavenčiak Tomer Keren diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 85a509dff3f..1de9afaaa66 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -326,7 +326,7 @@ Bug fixes - `#13865 `_: Fixed `--show-capture` with `--tb=line`. -- `#13522 `_: Fixed :fixture:`pytester` in subprocess mode ignored all :attr`pytester.plugins ` except the first. +- `#13522 `_: Fixed :fixture:`pytester` in subprocess mode ignored all :attr:`pytester.plugins ` except the first. Fixed :fixture:`pytester` in subprocess mode silently ignored non-str :attr:`pytester.plugins `. Now it errors instead. From f23dbbbe1e034ab16776071675fd66bdb4e83c3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BA=F0=9F=87=A6=20Sviatoslav=20Sydorenko=20=28?= =?UTF-8?q?=D0=A1=D0=B2=D1=8F=D1=82=D0=BE=D1=81=D0=BB=D0=B0=D0=B2=20=D0=A1?= =?UTF-8?q?=D0=B8=D0=B4=D0=BE=D1=80=D0=B5=D0=BD=D0=BA=D0=BE=29?= Date: Thu, 20 Nov 2025 21:52:10 +0100 Subject: [PATCH 18/74] Merge pull request #13984 from bluetech/ci-windows-coverage ci: restore full windows coverage (cherry picked from commit dd389d7f9290d8581a1c3d14c5adc07a4dda9bec) --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fbee593f7c2..4914725f778 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -139,6 +139,7 @@ jobs: python: "3.14" os: windows-latest tox_env: "py314" + use_coverage: true # Use separate jobs for different unittest flavors (twisted, asynctest) to ensure proper coverage. - name: "ubuntu-py310-unittest-asynctest" From 1c27999785227377e2d0e60b997b36adfc9fa714 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Thu, 20 Nov 2025 23:42:01 +0200 Subject: [PATCH 19/74] Merge pull request #13971 from bluetech/disable-terminalprogress-by-default2 terminal: disable OSC 9;4; terminal progress by default, except on Windows (cherry picked from commit 66834f362e38e96eb7685e21f46bdb83ba52530b) --- changelog/13896.bugfix.rst | 5 +++ doc/en/changelog.rst | 4 ++ src/_pytest/config/__init__.py | 1 + src/_pytest/terminal.py | 15 ++----- src/_pytest/terminalprogress.py | 30 +++++++++++++ testing/test_terminal.py | 74 ++++++++++++++++++++------------- 6 files changed, 89 insertions(+), 40 deletions(-) create mode 100644 changelog/13896.bugfix.rst create mode 100644 src/_pytest/terminalprogress.py diff --git a/changelog/13896.bugfix.rst b/changelog/13896.bugfix.rst new file mode 100644 index 00000000000..187be00cc4d --- /dev/null +++ b/changelog/13896.bugfix.rst @@ -0,0 +1,5 @@ +The terminal progress feature added in pytest 9.0.0 has been disabled by default, except on Windows, due to compatibility issues with some terminal emulators. + +You may enable it again by passing ``-p terminalprogress``. We may enable it by default again once compatibility improves in the future. + +Additionally, when the environment variable ``TERM`` is ``dumb``, the escape codes are no longer emitted, even if the plugin is enabled. diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 1de9afaaa66..d9e9928db00 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -178,6 +178,10 @@ New features - `#13072 `_: Added support for displaying test session **progress in the terminal tab** using the `OSC 9;4; `_ ANSI sequence. + + **Note**: *This feature has been disabled by default in version 9.0.2, except on Windows, due to compatibility issues with some terminal emulators. + You may enable it again by passing* ``-p terminalprogress``. *We may enable it by default again once compatibility improves in the future.* + When pytest runs in a supported terminal emulator like ConEmu, Gnome Terminal, Ptyxis, Windows Terminal, Kitty or Ghostty, you'll see the progress in the terminal tab or window, allowing you to monitor pytest's progress at a glance. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 39817aaa523..6b02e160e1a 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -299,6 +299,7 @@ def directory_arg(path: str, optname: str) -> str: *default_plugins, "pytester", "pytester_assertions", + "terminalprogress", } diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 4517b05bdee..e66e4f48dd6 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -16,7 +16,6 @@ import datetime from functools import partial import inspect -import os from pathlib import Path import platform import sys @@ -299,16 +298,10 @@ def mywriter(tags, args): config.trace.root.setprocessor("pytest:config", mywriter) - if reporter.isatty(): - # Some terminals interpret OSC 9;4 as desktop notification, - # skip on those we know (#13896). - should_skip_terminal_progress = ( - # iTerm2 (reported on version 3.6.5). - "ITERM_SESSION_ID" in os.environ - ) - if not should_skip_terminal_progress: - plugin = TerminalProgressPlugin(reporter) - config.pluginmanager.register(plugin, "terminalprogress") + # See terminalprogress.py. + # On Windows it's safe to load by default. + if sys.platform == "win32": + config.pluginmanager.import_plugin("terminalprogress") def getreportopt(config: Config) -> str: diff --git a/src/_pytest/terminalprogress.py b/src/_pytest/terminalprogress.py new file mode 100644 index 00000000000..287f0d569ff --- /dev/null +++ b/src/_pytest/terminalprogress.py @@ -0,0 +1,30 @@ +# A plugin to register the TerminalProgressPlugin plugin. +# +# This plugin is not loaded by default due to compatibility issues (#13896), +# but can be enabled in one of these ways: +# - The terminal plugin enables it in a few cases where it's safe, and not +# blocked by the user (using e.g. `-p no:terminalprogress`). +# - The user explicitly requests it, e.g. using `-p terminalprogress`. +# +# In a few years, if it's safe, we can consider enabling it by default. Then, +# this file will become unnecessary and can be inlined into terminal.py. + +from __future__ import annotations + +import os + +from _pytest.config import Config +from _pytest.config import hookimpl +from _pytest.terminal import TerminalProgressPlugin +from _pytest.terminal import TerminalReporter + + +@hookimpl(trylast=True) +def pytest_configure(config: Config) -> None: + reporter: TerminalReporter | None = config.pluginmanager.get_plugin( + "terminalreporter" + ) + + if reporter is not None and reporter.isatty() and os.environ.get("TERM") != "dumb": + plugin = TerminalProgressPlugin(reporter) + config.pluginmanager.register(plugin, name="terminalprogress-plugin") diff --git a/testing/test_terminal.py b/testing/test_terminal.py index a981e14f0a2..3053f5ef9a1 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -12,8 +12,7 @@ from typing import cast from typing import Literal from typing import NamedTuple -from unittest.mock import Mock -from unittest.mock import patch +from unittest import mock import pluggy @@ -3419,40 +3418,57 @@ def mock_file(self) -> StringIO: @pytest.fixture def mock_tr(self, mock_file: StringIO) -> pytest.TerminalReporter: - tr = Mock(spec=pytest.TerminalReporter) + tr: pytest.TerminalReporter = mock.create_autospec(pytest.TerminalReporter) - def write_raw(s: str, *, flush: bool = False) -> None: - mock_file.write(s) + def write_raw(content: str, *, flush: bool = False) -> None: + mock_file.write(content) - tr.write_raw = write_raw + tr.write_raw = write_raw # type: ignore[method-assign] tr._progress_nodeids_reported = set() return tr - def test_plugin_registration(self, pytester: pytest.Pytester) -> None: - """Test that the plugin is registered correctly on TTY output.""" + @pytest.mark.skipif(sys.platform != "win32", reason="#13896") + def test_plugin_registration_enabled_by_default( + self, pytester: pytest.Pytester, monkeypatch: MonkeyPatch + ) -> None: + """Test that the plugin registration is enabled by default. + + Currently only on Windows (#13896). + """ + monkeypatch.setattr(sys.stdout, "isatty", lambda: True) # The plugin module should be registered as a default plugin. - with patch.object(sys.stdout, "isatty", return_value=True): - config = pytester.parseconfigure() - plugin = config.pluginmanager.get_plugin("terminalprogress") - assert plugin is not None + config = pytester.parseconfigure() + plugin = config.pluginmanager.get_plugin("terminalprogress") + assert plugin is not None - def test_disabled_for_non_tty(self, pytester: pytest.Pytester) -> None: + def test_plugin_registred_on_all_platforms_when_explicitly_requested( + self, pytester: pytest.Pytester, monkeypatch: MonkeyPatch + ) -> None: + """Test that the plugin is registered on any platform if explicitly requested.""" + monkeypatch.setattr(sys.stdout, "isatty", lambda: True) + # The plugin module should be registered as a default plugin. + config = pytester.parseconfigure("-p", "terminalprogress") + plugin = config.pluginmanager.get_plugin("terminalprogress") + assert plugin is not None + + def test_disabled_for_non_tty( + self, pytester: pytest.Pytester, monkeypatch: MonkeyPatch + ) -> None: """Test that plugin is disabled for non-TTY output.""" - with patch.object(sys.stdout, "isatty", return_value=False): - config = pytester.parseconfigure() - plugin = config.pluginmanager.get_plugin("terminalprogress") - assert plugin is None - - def test_disabled_for_iterm2(self, pytester: pytest.Pytester, monkeypatch) -> None: - """Should not register the plugin on iTerm2 terminal since it interprets - OSC 9;4 as desktop notifications, not progress (#13896).""" - monkeypatch.setenv( - "ITERM_SESSION_ID", "w0t1p0:3DB6DF06-FE11-40C3-9A66-9E10A193A632" - ) - with patch.object(sys.stdout, "isatty", return_value=True): - config = pytester.parseconfigure() - plugin = config.pluginmanager.get_plugin("terminalprogress") - assert plugin is None + monkeypatch.setattr(sys.stdout, "isatty", lambda: False) + config = pytester.parseconfigure("-p", "terminalprogress") + plugin = config.pluginmanager.get_plugin("terminalprogress-plugin") + assert plugin is None + + def test_disabled_for_dumb_terminal( + self, pytester: pytest.Pytester, monkeypatch: MonkeyPatch + ) -> None: + """Test that plugin is disabled when TERM=dumb.""" + monkeypatch.setenv("TERM", "dumb") + monkeypatch.setattr(sys.stdout, "isatty", lambda: True) + config = pytester.parseconfigure("-p", "terminalprogress") + plugin = config.pluginmanager.get_plugin("terminalprogress-plugin") + assert plugin is None @pytest.mark.parametrize( ["state", "progress", "expected"], @@ -3484,7 +3500,7 @@ def test_session_lifecycle( """Test progress updates during session lifecycle.""" plugin = TerminalProgressPlugin(mock_tr) - session = Mock(spec=pytest.Session) + session = mock.create_autospec(pytest.Session) session.testscollected = 3 # Session start - should emit indeterminate progress. From 7db819560f9bb4183cabdb4c7ea0820f5ee27ba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BA=F0=9F=87=A6=20Sviatoslav=20Sydorenko=20=28?= =?UTF-8?q?=D0=A1=D0=B2=D1=8F=D1=82=D0=BE=D1=81=D0=BB=D0=B0=D0=B2=20=D0=A1?= =?UTF-8?q?=D0=B8=D0=B4=D0=BE=D1=80=D0=B5=D0=BD=D0=BA=D0=BE=29?= Date: Fri, 21 Nov 2025 12:20:13 +0100 Subject: [PATCH 20/74] Merge pull request #13991 from bluetech/ci-slow-coverage coverage: use `ctrace` core to avoid CI slowdown on Python 3.14 (cherry picked from commit 1b5200c0f056ec58f5620417d3157aea3ba33c87) --- .coveragerc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.coveragerc b/.coveragerc index 4eab3e33381..e5a68198b84 100644 --- a/.coveragerc +++ b/.coveragerc @@ -10,6 +10,9 @@ include = *\Lib\site-packages\pytest.py parallel = 1 branch = 1 +# The sysmon core (default since Python 3.14) is much slower. +# Perhaps: https://github.com/coveragepy/coveragepy/issues/2082 +core = ctrace [paths] source = src/ From 40dd92fb7faefd6a85dace792fcbf9f542c8f07f Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Fri, 21 Nov 2025 16:08:51 +0000 Subject: [PATCH 21/74] [PR #13980/9f992b8b backport][9.0.x] config: Add a test for -o with invalid option (#13994) * config: Add a test for -o with invalid option (#13980) This was ignored until #13830. With that change, it now gets correctly surfaced to the user as a warning (or error with --strict-config), so we should have a test for it. (cherry picked from commit 9f992b8b61264ef5d010783e0d31b63d859f0071) * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Florian Bruhin Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- testing/test_config.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/testing/test_config.py b/testing/test_config.py index d28b9110413..2556e4e00aa 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -2356,7 +2356,16 @@ def test_override_ini_without_config_file(self, pytester: Pytester) -> None: } ) result = pytester.runpytest("--override-ini", "pythonpath=src") - assert result.parseoutcomes() == {"passed": 1} + result.assert_outcomes(passed=1) + + def test_override_ini_invalid_option(self, pytester: Pytester) -> None: + result = pytester.runpytest("--override-ini", "doesnotexist=true") + result.stdout.fnmatch_lines( + [ + "=*= warnings summary =*=", + "*PytestConfigWarning:*Unknown config option: doesnotexist", + ] + ) def test_help_via_addopts(pytester: Pytester) -> None: From c60fbe63a26f64a42738e3f3527a8f79024fdf50 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sat, 22 Nov 2025 12:21:16 +0000 Subject: [PATCH 22/74] Fix quadratic-time behavior when handling `unittest` subtests in Python 3.10 (#13993) (#13998) Fix #13965 Close #13970 (cherry picked from commit 342dba6c9fa2262fb6baa7eee3eaa62d12cfdd88) Co-authored-by: Bruno Oliveira --- changelog/13965.bugfix.rst | 1 + src/_pytest/unittest.py | 48 ++++++++++++++++++++++++-------------- 2 files changed, 32 insertions(+), 17 deletions(-) create mode 100644 changelog/13965.bugfix.rst diff --git a/changelog/13965.bugfix.rst b/changelog/13965.bugfix.rst new file mode 100644 index 00000000000..b910d6c5361 --- /dev/null +++ b/changelog/13965.bugfix.rst @@ -0,0 +1 @@ +Fixed quadratic-time behavior when handling ``unittest`` subtests in Python 3.10. diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 7498f1b0002..23b92724f5d 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -225,6 +225,10 @@ def setup(self) -> None: # A bound method to be called during teardown() if set (see 'runtest()'). self._explicit_tearDown: Callable[[], None] | None = None super().setup() + if sys.version_info < (3, 11): + # A cache of the subTest errors and non-subtest skips in self._outcome. + # Compute and cache these lists once, instead of computing them again and again for each subtest (#13965). + self._cached_errors_and_skips: tuple[list[Any], list[Any]] | None = None def teardown(self) -> None: if self._explicit_tearDown is not None: @@ -313,11 +317,7 @@ def add_skip() -> None: # We also need to check if `self.instance._outcome` is `None` (this happens if the test # class/method is decorated with `unittest.skip`, see pytest-dev/pytest-subtests#173). if sys.version_info < (3, 11) and self.instance._outcome is not None: - subtest_errors = [ - x - for x, y in self.instance._outcome.errors - if isinstance(x, _SubTest) and y is not None - ] + subtest_errors, _ = self._obtain_errors_and_skips() if len(subtest_errors) == 0: add_skip() else: @@ -443,18 +443,8 @@ def addSubTest( # For python < 3.11: add non-subtest skips once all subtest failures are processed by # `_addSubTest`. if sys.version_info < (3, 11): - from unittest.case import _SubTest # type: ignore[attr-defined] - - non_subtest_skip = [ - (x, y) - for x, y in self.instance._outcome.skipped - if not isinstance(x, _SubTest) - ] - subtest_errors = [ - (x, y) - for x, y in self.instance._outcome.errors - if isinstance(x, _SubTest) and y is not None - ] + subtest_errors, non_subtest_skip = self._obtain_errors_and_skips() + # Check if we have non-subtest skips: if there are also sub failures, non-subtest skips are not treated in # `_addSubTest` and have to be added using `add_skip` after all subtest failures are processed. if len(non_subtest_skip) > 0 and len(subtest_errors) > 0: @@ -465,6 +455,30 @@ def addSubTest( for testcase, reason in non_subtest_skip: self.addSkip(testcase, reason, handle_subtests=False) + def _obtain_errors_and_skips(self) -> tuple[list[Any], list[Any]]: + """Compute or obtain the cached values for subtest errors and non-subtest skips.""" + from unittest.case import _SubTest # type: ignore[attr-defined] + + assert sys.version_info < (3, 11), ( + "This workaround only should be used in Python 3.10" + ) + if self._cached_errors_and_skips is not None: + return self._cached_errors_and_skips + + subtest_errors = [ + (x, y) + for x, y in self.instance._outcome.errors + if isinstance(x, _SubTest) and y is not None + ] + + non_subtest_skips = [ + (x, y) + for x, y in self.instance._outcome.skipped + if not isinstance(x, _SubTest) + ] + self._cached_errors_and_skips = (subtest_errors, non_subtest_skips) + return subtest_errors, non_subtest_skips + @hookimpl(tryfirst=True) def pytest_runtest_makereport(item: Item, call: CallInfo[None]) -> None: From 556f6a22e12d13d1ffeceaf64424eb95d5e0fb87 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sun, 23 Nov 2025 05:27:43 +0000 Subject: [PATCH 23/74] pre-commit: fix rst-lint after new release (#13999) (#14001) https://github.com/twolfson/restructuredtext-lint?tab=readme-ov-file#breaking-changes-in-200 (cherry picked from commit 9b688f08dce00097a37bde808d9dafb4038b2bfa) Co-authored-by: Ran Benita --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e77d4cf52de..2f9f56256b6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -93,10 +93,10 @@ repos: stages: [manual] - id: rst name: rst - entry: rst-lint --encoding utf-8 + entry: rst-lint files: ^(RELEASING.rst|README.rst|TIDELIFT.rst)$ language: python - additional_dependencies: [pygments, restructuredtext_lint] + additional_dependencies: [pygments, restructuredtext_lint>=2.0.0] - id: changelogs-rst name: changelog filenames language: fail From d7ae6df394398168bf9d926f803c26849c8f07ee Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Wed, 26 Nov 2025 15:20:15 +0000 Subject: [PATCH 24/74] Merge pull request #14006 from pytest-dev/maintenance/update-plugin-list-tmpl-rst-backtick-typo (#14007) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop an accidental backtick from the plugin list doc template (cherry picked from commit a05da8a520be8cdf31ce9f1e9ba8c5c9a6e6e767) Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) --- scripts/update-plugin-list.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update-plugin-list.py b/scripts/update-plugin-list.py index 61debb44043..be57d436966 100644 --- a/scripts/update-plugin-list.py +++ b/scripts/update-plugin-list.py @@ -30,7 +30,7 @@ Pytest Plugin List ================== -Below is an automated compilation of ``pytest``` plugins available on `PyPI `_. +Below is an automated compilation of ``pytest`` plugins available on `PyPI `_. It includes PyPI projects whose names begin with ``pytest-`` or ``pytest_`` and a handful of manually selected projects. Packages classified as inactive are excluded. From 5a4e398ce89bc23d2cf3fd98c042fdffb6fa8afa Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Wed, 26 Nov 2025 15:26:44 +0000 Subject: [PATCH 25/74] Fix docs typo (#14005) (#14008) "there may files" should be "there may be files" (cherry picked from commit 3e75c0a2c1b785651b12bd22f8d1bbc2bfbd6cfa) Co-authored-by: Alex Waygood --- doc/en/example/pythoncollection.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index eba40d50d1b..f422e51ab76 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -231,7 +231,7 @@ You can easily instruct ``pytest`` to discover tests from every Python file: python_files = ["*.py"] However, many projects will have a ``setup.py`` which they don't want to be -imported. Moreover, there may files only importable by a specific python +imported. Moreover, there may be files only importable by a specific python version. For such cases you can dynamically define files to be ignored by listing them in a ``conftest.py`` file: From bc783862991241c442c9f9c068e51737ec15ea10 Mon Sep 17 00:00:00 2001 From: Fazeel Usmani Date: Thu, 27 Nov 2025 02:43:00 +0530 Subject: [PATCH 26/74] Add CLI options reference documentation (#13930) Co-authored-by: Ran Benita (cherry picked from commit 922b60377a38238b282c062e9589fdbe7eac1804) --- changelog/4492.doc.rst | 1 + doc/en/backwards-compatibility.rst | 2 +- doc/en/builtin.rst | 6 +- doc/en/example/markers.rst | 10 +- doc/en/example/parametrize.rst | 4 +- doc/en/example/pythoncollection.rst | 14 +- doc/en/example/simple.rst | 6 +- doc/en/explanation/goodpractices.rst | 4 +- doc/en/explanation/pythonpath.rst | 4 +- doc/en/getting-started.rst | 2 +- doc/en/how-to/assert.rst | 2 +- doc/en/how-to/cache.rst | 22 +- doc/en/how-to/capture-stdout-stderr.rst | 8 +- doc/en/how-to/capture-warnings.rst | 2 +- doc/en/how-to/doctest.rst | 4 +- doc/en/how-to/failures.rst | 4 +- doc/en/how-to/fixtures.rst | 4 +- doc/en/how-to/logging.rst | 26 +- doc/en/how-to/mark.rst | 2 +- doc/en/how-to/monkeypatch.rst | 2 +- doc/en/how-to/output.rst | 16 +- doc/en/how-to/plugins.rst | 4 +- doc/en/how-to/skipping.rst | 4 +- doc/en/how-to/subtests.rst | 4 +- doc/en/how-to/tmp_path.rst | 8 +- doc/en/how-to/unittest.rst | 2 +- doc/en/how-to/usage.rst | 6 +- doc/en/how-to/writing_plugins.rst | 2 +- doc/en/reference/customize.rst | 4 +- doc/en/reference/fixtures.rst | 10 +- doc/en/reference/reference.rst | 591 +++++++++++++++++++++++- 31 files changed, 675 insertions(+), 105 deletions(-) create mode 100644 changelog/4492.doc.rst diff --git a/changelog/4492.doc.rst b/changelog/4492.doc.rst new file mode 100644 index 00000000000..811994afb5c --- /dev/null +++ b/changelog/4492.doc.rst @@ -0,0 +1 @@ +The API Reference now contains cross-reference-able documentation of :ref:`pytest's command-line flags `. diff --git a/doc/en/backwards-compatibility.rst b/doc/en/backwards-compatibility.rst index 82f678b4dea..d79d112df2d 100644 --- a/doc/en/backwards-compatibility.rst +++ b/doc/en/backwards-compatibility.rst @@ -60,7 +60,7 @@ Keeping backwards compatibility has a very high priority in the pytest project. With the pytest 3.0 release, we introduced a clear communication scheme for when we will actually remove the old busted joint and politely ask you to use the new hotness instead, while giving you enough time to adjust your tests or raise concerns if there are valid reasons to keep deprecated functionality around. -To communicate changes, we issue deprecation warnings using a custom warning hierarchy (see :ref:`internal-warnings`). These warnings may be suppressed using the standard means: ``-W`` command-line flag or ``filterwarnings`` ini options (see :ref:`warnings`), but we suggest to use these sparingly and temporarily, and heed the warnings when possible. +To communicate changes, we issue deprecation warnings using a custom warning hierarchy (see :ref:`internal-warnings`). These warnings may be suppressed using the standard means: :option:`-W` command-line flag or :confval:`filterwarnings` configuration option (see :ref:`warnings`), but we suggest to use these sparingly and temporarily, and heed the warnings when possible. 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). diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 5b66626fd20..1a8d32effee 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -12,7 +12,7 @@ For information on plugin hooks and objects, see :ref:`plugins`. For information on the ``pytest.mark`` mechanism, see :ref:`mark`. -For information about fixtures, see :ref:`fixtures`. To see a complete list of available fixtures (add ``-v`` to also see fixtures with leading ``_``), type : +For information about fixtures, see :ref:`fixtures`. To see a complete list of available fixtures (add :option:`-v` to also see fixtures with leading ``_``), type : .. code-block:: pytest @@ -53,7 +53,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a capteesys -- .../_pytest/capture.py:1028 Enable simultaneous text capturing and pass-through of writes - to ``sys.stdout`` and ``sys.stderr`` as defined by ``--capture=``. + to ``sys.stdout`` and ``sys.stderr`` as defined by :option:`--capture`. The captured output is made available via ``capteesys.readouterr()`` method @@ -61,7 +61,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a ``out`` and ``err`` will be ``text`` objects. The output is also passed-through, allowing it to be "live-printed", - reported, or both as defined by ``--capture=``. + reported, or both as defined by :option:`--capture`. Returns an instance of :class:`CaptureFixture[str] `. diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst index cbe417e8a3e..4f6738207e1 100644 --- a/doc/en/example/markers.rst +++ b/doc/en/example/markers.rst @@ -167,9 +167,9 @@ Using ``-k expr`` to select tests based on their name .. versionadded:: 2.0/2.3.4 -You can use the ``-k`` command line option to specify an expression +You can use the :option:`-k` command line option to specify an expression which implements a substring match on the test names instead of the -exact match on markers that ``-m`` provides. This makes it easy to +exact match on markers that :option:`-m` provides. This makes it easy to select tests based on their names: .. versionchanged:: 5.4 @@ -225,7 +225,7 @@ Or to select "http" and "quick" tests: You can use ``and``, ``or``, ``not`` and parentheses. -In addition to the test's name, ``-k`` also matches the names of the test's parents (usually, the name of the file and class it's in), +In addition to the test's name, :option:`-k` also matches the names of the test's parents (usually, the name of the file and class it's in), attributes set on the test function, markers applied to it or its parents and any :attr:`extra keywords <_pytest.nodes.Node.extra_keyword_matches>` explicitly added to it or its parents. @@ -440,7 +440,7 @@ and here is one that specifies exactly the environment needed: ============================ 1 passed in 0.12s ============================= -The ``--markers`` option always gives you a list of available markers: +The :option:`--markers` option always gives you a list of available markers: .. code-block:: pytest @@ -658,7 +658,7 @@ Automatically adding markers based on test names If you have a test suite where test function names indicate a certain type of test, you can implement a hook that automatically defines -markers so that you can use the ``-m`` option with it. Let's look +markers so that you can use the :option:`-m` option with it. Let's look at this test module: .. code-block:: python diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index 1cbeee27aad..40b63b28ec6 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -83,9 +83,9 @@ Different options for test IDs ------------------------------------ pytest will build a string that is the test ID for each set of values in a -parametrized test. These IDs can be used with ``-k`` to select specific cases +parametrized test. These IDs can be used with :option:`-k` to select specific cases to run, and they will also identify the specific case when one is failing. -Running pytest with ``--collect-only`` will show the generated IDs. +Running pytest with :option:`--collect-only` will show the generated IDs. Numbers, strings, booleans and None will have their usual string representation used in the test ID. For other objects, pytest will make a string based on diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index f422e51ab76..ff694f746d7 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -5,7 +5,7 @@ Ignore paths during test collection ----------------------------------- You can easily ignore certain test directories and modules during collection -by passing the ``--ignore=path`` option on the cli. ``pytest`` allows multiple +by passing the :option:`--ignore=path` option on the cli. ``pytest`` allows multiple ``--ignore`` options. Example: .. code-block:: text @@ -43,16 +43,16 @@ you will see that ``pytest`` only collects test-modules, which do not match the ========================= 5 passed in 0.02 seconds ========================= -The ``--ignore-glob`` option allows to ignore test file paths based on Unix shell-style wildcards. -If you want to exclude test-modules that end with ``_01.py``, execute ``pytest`` with ``--ignore-glob='*_01.py'``. +The :option:`--ignore-glob` option allows to ignore test file paths based on Unix shell-style wildcards. +If you want to exclude test-modules that end with ``_01.py``, execute ``pytest`` with :option:`--ignore-glob='*_01.py'`. Deselect tests during test collection ------------------------------------- -Tests can individually be deselected during collection by passing the ``--deselect=item`` option. +Tests can individually be deselected during collection by passing the :option:`--deselect=item` option. For example, say ``tests/foobar/test_foobar_01.py`` contains ``test_a`` and ``test_b``. You can run all of the tests within ``tests/`` *except* for ``tests/foobar/test_foobar_01.py::test_a`` -by invoking ``pytest`` with ``--deselect tests/foobar/test_foobar_01.py::test_a``. +by invoking ``pytest`` with ``--deselect=tests/foobar/test_foobar_01.py::test_a``. ``pytest`` allows multiple ``--deselect`` options. .. _duplicate-paths: @@ -73,7 +73,7 @@ Example: Just collect tests once. -To collect duplicate tests, use the ``--keep-duplicates`` option on the cli. +To collect duplicate tests, use the :option:`--keep-duplicates` option on the cli. Example: .. code-block:: pytest @@ -168,7 +168,7 @@ You can check for multiple glob patterns by adding a space between the patterns: Interpreting cmdline arguments as Python packages ----------------------------------------------------- -You can use the ``--pyargs`` option to make ``pytest`` try +You can use the :option:`--pyargs` option to make ``pytest`` try interpreting arguments as python package names, deriving their file system path and then running the test. For example if you have unittest2 installed you can type: diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index 09335153ad1..8b35f0ebca5 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -43,7 +43,7 @@ The actual command line executed is: pytest -ra -q -v -m slow Note that as usual for other command-line applications, in case of conflicting options the last one wins, so the example -above will show verbose output because ``-v`` overwrites ``-q``. +above will show verbose output because :option:`-v` overwrites :option:`-q`. .. _request example: @@ -353,7 +353,7 @@ Example: The ``__tracebackhide__`` setting influences ``pytest`` showing of tracebacks: the ``checkconfig`` function will not be shown -unless the ``--full-trace`` command line option is specified. +unless the :option:`--full-trace` command line option is specified. Let's run our little function: .. code-block:: pytest @@ -998,7 +998,7 @@ information. Sometimes a test session might get stuck and there might be no easy way to figure out -which test got stuck, for example if pytest was run in quiet mode (``-q``) or you don't have access to the console +which test got stuck, for example if pytest was run in quiet mode (:option:`-q`) or you don't have access to the console output. This is particularly a problem if the problem happens only sporadically, the famous "flaky" kind of tests. ``pytest`` sets the :envvar:`PYTEST_CURRENT_TEST` environment variable when running tests, which can be inspected diff --git a/doc/en/explanation/goodpractices.rst b/doc/en/explanation/goodpractices.rst index 4920309b9d6..bbc64ec662d 100644 --- a/doc/en/explanation/goodpractices.rst +++ b/doc/en/explanation/goodpractices.rst @@ -170,7 +170,7 @@ want to distribute them along with your application: test_view.py ... -In this scheme, it is easy to run your tests using the ``--pyargs`` option: +In this scheme, it is easy to run your tests using the :option:`--pyargs` option: .. code-block:: bash @@ -217,7 +217,7 @@ Note that this layout also works in conjunction with the ``src`` layout mentione from each other and thus deriving a canonical import name helps to avoid surprises such as a test module getting imported twice. - With ``--import-mode=importlib`` things are less convoluted because + With :option:`--import-mode=importlib` things are less convoluted because pytest doesn't need to change ``sys.path``, making things much less surprising. diff --git a/doc/en/explanation/pythonpath.rst b/doc/en/explanation/pythonpath.rst index ddcbd304f89..cb3ae67216a 100644 --- a/doc/en/explanation/pythonpath.rst +++ b/doc/en/explanation/pythonpath.rst @@ -11,7 +11,7 @@ Import modes pytest as a testing framework needs to import test modules and ``conftest.py`` files for execution. Importing files in Python is a non-trivial process, so aspects of the -import process can be controlled through the ``--import-mode`` command-line flag, which can assume +import process can be controlled through the :option:`--import-mode` command-line flag, which can assume these values: .. _`import-mode-prepend`: @@ -44,7 +44,7 @@ these values: pkg_under_test/ the tests will run against the installed version - of ``pkg_under_test`` when ``--import-mode=append`` is used whereas + of ``pkg_under_test`` when :option:`--import-mode=append` is used whereas with ``prepend``, they would pick up the local version. This kind of confusion is why we advocate for using :ref:`src-layouts `. diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index e1932d96ef9..7365dcdc491 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -262,7 +262,7 @@ Find out what kind of builtin :ref:`pytest fixtures ` exist with the c pytest --fixtures # shows builtin and custom fixtures -Note that this command omits fixtures with leading ``_`` unless the ``-v`` option is added. +Note that this command omits fixtures with leading ``_`` unless the :option:`-v` option is added. Continue reading ------------------------------------- diff --git a/doc/en/how-to/assert.rst b/doc/en/how-to/assert.rst index a1fce9f8b90..4ef2664b1d5 100644 --- a/doc/en/how-to/assert.rst +++ b/doc/en/how-to/assert.rst @@ -599,4 +599,4 @@ If this is the case you have two options: * Disable rewriting for a specific module by adding the string ``PYTEST_DONT_REWRITE`` to its docstring. -* Disable rewriting for all modules by using ``--assert=plain``. +* Disable rewriting for all modules by using :option:`--assert=plain`. diff --git a/doc/en/how-to/cache.rst b/doc/en/how-to/cache.rst index bfc1902cae0..4271ab469dc 100644 --- a/doc/en/how-to/cache.rst +++ b/doc/en/how-to/cache.rst @@ -13,11 +13,11 @@ Usage The plugin provides two command line options to rerun failures from the last ``pytest`` invocation: -* ``--lf``, ``--last-failed`` - to only re-run the failures. -* ``--ff``, ``--failed-first`` - to run the failures first and then the rest of +* :option:`--lf, --last-failed <--lf>` - to only re-run the failures. +* :option:`--ff, --failed-first <--ff>` - to run the failures first and then the rest of the tests. -For cleanup (usually not needed), a ``--cache-clear`` option allows to remove +For cleanup (usually not needed), a :option:`--cache-clear` option allows to remove all cross-session cache contents ahead of a test run. Other plugins may access the `config.cache`_ object to set/get @@ -80,7 +80,7 @@ If you run this for the first time you will see two failures: FAILED test_50.py::test_num[25] - Failed: bad luck 2 failed, 48 passed in 0.12s -If you then run it with ``--lf``: +If you then run it with :option:`--lf`: .. code-block:: pytest @@ -124,7 +124,7 @@ If you then run it with ``--lf``: You have run only the two failing tests from the last run, while the 48 passing tests have not been run ("deselected"). -Now, if you run with the ``--ff`` option, all tests will be run but the first +Now, if you run with the :option:`--ff` option, all tests will be run but the first previous failures will be executed first (as can be seen from the series of ``FF`` and dots): @@ -169,14 +169,14 @@ of ``FF`` and dots): .. _`config.cache`: -New ``--nf``, ``--new-first`` options: run new tests first followed by the rest +New :option:`--nf, --new-first <--nf>` option: run new tests first followed by the rest of the tests, in both cases tests are also sorted by the file modified time, with more recent files coming first. Behavior when no tests failed in the last run --------------------------------------------- -The ``--lfnf/--last-failed-no-failures`` option governs the behavior of ``--last-failed``. +The :option:`--lfnf, --last-failed-no-failures <--lfnf>` option governs the behavior of :option:`--last-failed`. Determines whether to execute tests when there are no previously (known) failures or when no cached ``lastfailed`` data was found. @@ -275,7 +275,7 @@ Inspecting Cache content ------------------------ You can always peek at the content of the cache using the -``--cache-show`` command line option: +:option:`--cache-show` command line option: .. code-block:: pytest @@ -294,7 +294,7 @@ You can always peek at the content of the cache using the ========================== no tests ran in 0.12s =========================== -``--cache-show`` takes an optional argument to specify a glob pattern for +:option:`--cache-show` takes an optional argument to specify a glob pattern for filtering: .. code-block:: pytest @@ -314,7 +314,7 @@ Clearing Cache content ---------------------- You can instruct pytest to clear all cache files and values -by adding the ``--cache-clear`` option like this: +by adding the :option:`--cache-clear` option like this: .. code-block:: bash @@ -330,4 +330,4 @@ than speed. Stepwise -------- -As an alternative to ``--lf -x``, especially for cases where you expect a large part of the test suite will fail, ``--sw``, ``--stepwise`` allows you to fix them one at a time. The test suite will run until the first failure and then stop. At the next invocation, tests will continue from the last failing test and then run until the next failing test. You may use the ``--stepwise-skip`` option to ignore one failing test and stop the test execution on the second failing test instead. This is useful if you get stuck on a failing test and just want to ignore it until later. Providing ``--stepwise-skip`` will also enable ``--stepwise`` implicitly. +As an alternative to :option:`--lf` :option:`-x`, especially for cases where you expect a large part of the test suite will fail, :option:`--sw, --stepwise <--sw>` allows you to fix them one at a time. The test suite will run until the first failure and then stop. At the next invocation, tests will continue from the last failing test and then run until the next failing test. You may use the :option:`--stepwise-skip` option to ignore one failing test and stop the test execution on the second failing test instead. This is useful if you get stuck on a failing test and just want to ignore it until later. Providing ``--stepwise-skip`` will also enable ``--stepwise`` implicitly. diff --git a/doc/en/how-to/capture-stdout-stderr.rst b/doc/en/how-to/capture-stdout-stderr.rst index cd5cb6d798f..14807b9b777 100644 --- a/doc/en/how-to/capture-stdout-stderr.rst +++ b/doc/en/how-to/capture-stdout-stderr.rst @@ -4,19 +4,19 @@ How to capture stdout/stderr output ========================================================= -Pytest intercepts stdout and stderr as configured by the ``--capture=`` +Pytest intercepts stdout and stderr as configured by the :option:`--capture=` command-line argument or by using fixtures. The ``--capture=`` flag configures reporting, whereas the fixtures offer more granular control and allows inspection of output during testing. The reports can be customized with the -`-r flag <../reference/reference.html#command-line-flags>`_. +:option:`-r` flag. Default stdout/stderr/stdin capturing behaviour --------------------------------------------------------- During test execution any output sent to ``stdout`` and ``stderr`` is captured. If a test or a setup method fails its according captured -output will usually be shown along with the failure traceback. (this -behavior can be configured by the ``--show-capture`` command-line option). +output will usually be shown along with the failure traceback. (This +behavior can be configured by the :option:`--show-capture` command-line option). In addition, ``stdin`` is set to a "null" object which will fail on attempts to read from it because it is rarely desired diff --git a/doc/en/how-to/capture-warnings.rst b/doc/en/how-to/capture-warnings.rst index 9cefdc39307..3f55467b434 100644 --- a/doc/en/how-to/capture-warnings.rst +++ b/doc/en/how-to/capture-warnings.rst @@ -198,7 +198,7 @@ decorator or to all tests in a module by setting the :globalvar:`pytestmark` var Disabling warnings summary -------------------------- -Although not recommended, you can use the ``--disable-warnings`` command-line option to suppress the +Although not recommended, you can use the :option:`--disable-warnings` command-line option to suppress the warning summary entirely from the test run output. Disabling warning capture entirely diff --git a/doc/en/how-to/doctest.rst b/doc/en/how-to/doctest.rst index de6679bc452..433b35b61ce 100644 --- a/doc/en/how-to/doctest.rst +++ b/doc/en/how-to/doctest.rst @@ -11,7 +11,7 @@ can change the pattern by issuing: pytest --doctest-glob="*.rst" -on the command line. ``--doctest-glob`` can be given multiple times in the command-line. +on the command line. :option:`--doctest-glob` can be given multiple times in the command-line. If you then have a text file like this: @@ -39,7 +39,7 @@ then you can just invoke ``pytest`` directly: ============================ 1 passed in 0.12s ============================= By default, pytest will collect ``test*.txt`` files looking for doctest directives, but you -can pass additional globs using the ``--doctest-glob`` option (multi-allowed). +can pass additional globs using the :option:`--doctest-glob` option (multi-allowed). In addition to text files, you can also execute doctests directly from docstrings of your classes and functions, including from test modules: diff --git a/doc/en/how-to/failures.rst b/doc/en/how-to/failures.rst index 0c45cd7b118..878c869d525 100644 --- a/doc/en/how-to/failures.rst +++ b/doc/en/how-to/failures.rst @@ -93,8 +93,8 @@ Pytest supports the use of ``breakpoint()`` with the following behaviours: - When ``breakpoint()`` is called and ``PYTHONBREAKPOINT`` is set to the default value, pytest will use the custom internal PDB trace UI instead of the system default ``Pdb``. - When tests are complete, the system will default back to the system ``Pdb`` trace UI. - - With ``--pdb`` passed to pytest, the custom internal Pdb trace UI is used with both ``breakpoint()`` and failed tests/unhandled exceptions. - - ``--pdbcls`` can be used to specify a custom debugger class. + - With :option:`--pdb` passed to pytest, the custom internal Pdb trace UI is used with both ``breakpoint()`` and failed tests/unhandled exceptions. + - :option:`--pdbcls` can be used to specify a custom debugger class. .. _faulthandler: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index 40e13e2afa8..b15b3a5497b 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1368,9 +1368,9 @@ different server string is expected than what arrived. pytest will build a string that is the test ID for each fixture value in a parametrized fixture, e.g. ``test_ehlo[smtp.gmail.com]`` and ``test_ehlo[mail.python.org]`` in the above examples. These IDs can -be used with ``-k`` to select specific cases to run, and they will +be used with :option:`-k` to select specific cases to run, and they will also identify the specific case when one is failing. Running pytest -with ``--collect-only`` will show the generated IDs. +with :option:`--collect-only` will show the generated IDs. Numbers, strings, booleans and ``None`` will have their usual string representation used in the test ID. For other objects, pytest will diff --git a/doc/en/how-to/logging.rst b/doc/en/how-to/logging.rst index d6d87f03bbf..c0762e60928 100644 --- a/doc/en/how-to/logging.rst +++ b/doc/en/how-to/logging.rst @@ -65,7 +65,7 @@ These options can also be customized through a configuration file: log_format = %(asctime)s %(levelname)s %(message)s log_date_format = %Y-%m-%d %H:%M:%S -Specific loggers can be disabled via ``--log-disable={logger_name}``. +Specific loggers can be disabled via :option:`--log-disable={logger_name}`. This argument can be passed multiple times: .. code-block:: bash @@ -199,13 +199,13 @@ By setting the :confval:`log_cli` configuration option to ``true``, pytest will logging records as they are emitted directly into the console. You can specify the logging level for which log records with equal or higher -level are printed to the console by passing ``--log-cli-level``. This setting +level are printed to the console by passing :option:`--log-cli-level`. This setting accepts the logging level names or numeric values as seen in :ref:`logging's documentation `. -Additionally, you can also specify ``--log-cli-format`` and -``--log-cli-date-format`` which mirror and default to ``--log-format`` and -``--log-date-format`` if not provided, but are applied only to the console +Additionally, you can also specify :option:`--log-cli-format` and +:option:`--log-cli-date-format` which mirror and default to :option:`--log-format` and +:option:`--log-date-format` if not provided, but are applied only to the console logging handler. All of the CLI log options can also be set in the configuration file. The @@ -216,19 +216,19 @@ option names are: * :confval:`log_cli_date_format` If you need to record the whole test suite logging calls to a file, you can pass -``--log-file=/path/to/log/file``. This log file is opened in write mode by default which +:option:`--log-file=/path/to/log/file`. This log file is opened in write mode by default which means that it will be overwritten at each run tests session. -If you'd like the file opened in append mode instead, then you can pass ``--log-file-mode=a``. +If you'd like the file opened in append mode instead, then you can pass :option:`--log-file-mode=a`. Note that relative paths for the log-file location, whether passed on the CLI or declared in a config file, are always resolved relative to the current working directory. You can also specify the logging level for the log file by passing -``--log-file-level``. This setting accepts the logging level names or numeric +:option:`--log-file-level`. This setting accepts the logging level names or numeric values as seen in :ref:`logging's documentation `. -Additionally, you can also specify ``--log-file-format`` and -``--log-file-date-format`` which are equal to ``--log-format`` and -``--log-date-format`` but are applied to the log file logging handler. +Additionally, you can also specify :option:`--log-file-format` and +:option:`--log-file-date-format` which are equal to ``--log-format`` and +:option:`--log-date-format` but are applied to the log file logging handler. All of the log file options can also be set in the configuration file. The option names are: @@ -302,14 +302,14 @@ This feature was introduced in ``3.3`` and some **incompatible changes** have be made in ``3.4`` after community feedback: * Log levels are no longer changed unless explicitly requested by the :confval:`log_level` configuration - or ``--log-level`` command-line options. This allows users to configure logger objects themselves. + or :option:`--log-level` command-line options. This allows users to configure logger objects themselves. Setting :confval:`log_level` will set the level that is captured globally so if a specific test requires a lower level than this, use the ``caplog.set_level()`` functionality otherwise that test will be prone to failure. * :ref:`Live Logs ` is now disabled by default and can be enabled setting the :confval:`log_cli` configuration option to ``true``. When enabled, the verbosity is increased so logging for each test is visible. -* :ref:`Live Logs ` are now sent to ``sys.stdout`` and no longer require the ``-s`` command-line option +* :ref:`Live Logs ` are now sent to ``sys.stdout`` and no longer require the :option:`-s` command-line option to work. If you want to partially restore the logging behavior of version ``3.3``, you can add this options to your configuration diff --git a/doc/en/how-to/mark.rst b/doc/en/how-to/mark.rst index 575ce2f41c2..e22219414a0 100644 --- a/doc/en/how-to/mark.rst +++ b/doc/en/how-to/mark.rst @@ -21,7 +21,7 @@ Here are some of the builtin markers: It's easy to create custom markers or to apply markers to whole test classes or modules. Those markers can be used by plugins, and also -are commonly used to :ref:`select tests ` on the command-line with the ``-m`` option. +are commonly used to :ref:`select tests ` on the command-line with the :option:`-m` option. See :ref:`mark examples` for examples which also serve as documentation. diff --git a/doc/en/how-to/monkeypatch.rst b/doc/en/how-to/monkeypatch.rst index a9504dcb32a..ad0c6e0e1c5 100644 --- a/doc/en/how-to/monkeypatch.rst +++ b/doc/en/how-to/monkeypatch.rst @@ -235,7 +235,7 @@ so that any attempts within tests to create http requests will fail. Be advised that it is not recommended to patch builtin functions such as ``open``, ``compile``, etc., because it might break pytest's internals. If that's - unavoidable, passing ``--tb=native``, ``--assert=plain`` and ``--capture=no`` might + unavoidable, passing :option:`--tb=native`, :option:`--assert=plain` and :option:`--capture=no` might help although there's no guarantee. .. note:: diff --git a/doc/en/how-to/output.rst b/doc/en/how-to/output.rst index ec4ca05838e..d92b2131701 100644 --- a/doc/en/how-to/output.rst +++ b/doc/en/how-to/output.rst @@ -30,8 +30,8 @@ Examples for modifying traceback printing: pytest --tb=native # Python standard library formatting pytest --tb=no # no traceback at all -The ``--full-trace`` causes very long traces to be printed on error (longer -than ``--tb=long``). It also ensures that a stack trace is printed on +The :option:`--full-trace` causes very long traces to be printed on error (longer +than :option:`--tb=long`). It also ensures that a stack trace is printed on **KeyboardInterrupt** (Ctrl+C). This is very useful if the tests are taking too long and you interrupt them with Ctrl+C to find out where the tests are *hanging*. By default no output @@ -52,8 +52,8 @@ Examples for modifying printing verbosity: pytest -vv # more verbose, display more details from the test output pytest -vvv # not a standard , but may be used for even more detail in certain setups -The ``-v`` flag controls the verbosity of pytest output in various aspects: test session progress, assertion -details when tests fail, fixtures details with ``--fixtures``, etc. +The :option:`-v` flag controls the verbosity of pytest output in various aspects: test session progress, assertion +details when tests fail, fixtures details with :option:`--fixtures`, etc. .. regendoc:wipe @@ -372,7 +372,7 @@ test inside the file gets its own line in the output. Producing a detailed summary report -------------------------------------------------- -The ``-r`` flag can be used to display a "short test summary info" at the end of the test session, +The :option:`-r` flag can be used to display a "short test summary info" at the end of the test session, making it easy in large test suites to get a clear picture of all failures, skips, xfails, etc. It defaults to ``fE`` to list failures and errors. @@ -453,7 +453,7 @@ Example: FAILED test_example.py::test_fail - assert 0 == 1 failed, 1 passed, 1 skipped, 1 xfailed, 1 xpassed, 1 error in 0.12s === -The ``-r`` options accepts a number of characters after it, with ``a`` used +The :option:`-r` options accepts a number of characters after it, with ``a`` used above meaning "all except passes". Here is the full list of available characters that can be used: @@ -547,7 +547,7 @@ captured output: .. note:: By default, parametrized variants of skipped tests are grouped together if - they share the same skip reason. You can use ``--no-fold-skipped`` to print each skipped test separately. + they share the same skip reason. You can use :option:`--no-fold-skipped` to print each skipped test separately. .. _truncation-params: @@ -822,7 +822,7 @@ Sending test report to an online pastebin service This will submit test run information to a remote Paste service and provide a URL for each failure. You may select tests as usual or add -for example ``-x`` if you only want to send one particular failure. +for example :option:`-x` if you only want to send one particular failure. **Creating a URL for a whole test session log**: diff --git a/doc/en/how-to/plugins.rst b/doc/en/how-to/plugins.rst index 591c44dfa4d..48a45619324 100644 --- a/doc/en/how-to/plugins.rst +++ b/doc/en/how-to/plugins.rst @@ -148,7 +148,7 @@ Disabling plugins from autoloading ---------------------------------- If you want to disable plugins from loading automatically, instead of requiring you to -manually specify each plugin with ``-p`` or :envvar:`PYTEST_PLUGINS`, you can use ``--disable-plugin-autoload`` or :envvar:`PYTEST_DISABLE_PLUGIN_AUTOLOAD`. +manually specify each plugin with :option:`-p` or :envvar:`PYTEST_PLUGINS`, you can use :option:`--disable-plugin-autoload` or :envvar:`PYTEST_DISABLE_PLUGIN_AUTOLOAD`. .. code-block:: bash @@ -179,4 +179,4 @@ manually specify each plugin with ``-p`` or :envvar:`PYTEST_PLUGINS`, you can us .. versionadded:: 8.4 - The ``--disable-plugin-autoload`` command-line flag. + The :option:`--disable-plugin-autoload` command-line flag. diff --git a/doc/en/how-to/skipping.rst b/doc/en/how-to/skipping.rst index 1887fbd53ef..3b4d412843d 100644 --- a/doc/en/how-to/skipping.rst +++ b/doc/en/how-to/skipping.rst @@ -21,14 +21,14 @@ it's an **xpass** and will be reported in the test summary. ``pytest`` counts and lists *skip* and *xfail* tests separately. Detailed information about skipped/xfailed tests is not shown by default to avoid -cluttering the output. You can use the ``-r`` option to see details +cluttering the output. You can use the :option:`-r` option to see details corresponding to the "short" letters shown in the test progress: .. code-block:: bash pytest -rxXs # show extra info on xfailed, xpassed, and skipped tests -More details on the ``-r`` option can be found by running ``pytest -h``. +More details on the :option:`-r` option can be found by running ``pytest -h``. (See :ref:`how to change command line options defaults`) diff --git a/doc/en/how-to/subtests.rst b/doc/en/how-to/subtests.rst index c8d9461c983..5a08dbc4769 100644 --- a/doc/en/how-to/subtests.rst +++ b/doc/en/how-to/subtests.rst @@ -90,7 +90,7 @@ outside the ``subtests.test`` block: Verbosity --------- -By default, only **subtest failures** are shown. Higher verbosity levels (``-v``) will also show progress output for **passed** subtests. +By default, only **subtest failures** are shown. Higher verbosity levels (:option:`-v`) will also show progress output for **passed** subtests. It is possible to control the verbosity of subtests by setting :confval:`verbosity_subtests`. @@ -118,7 +118,7 @@ Parametrization * Happens at collection time. * Generates individual tests. * Parametrized tests can be referenced from the command line. -* Plays well with plugins that handle test execution, such as ``--last-failed``. +* Plays well with plugins that handle test execution, such as :option:`--last-failed`. * Ideal for decision table testing. Subtests diff --git a/doc/en/how-to/tmp_path.rst b/doc/en/how-to/tmp_path.rst index 04c663bb986..e73c55878a6 100644 --- a/doc/en/how-to/tmp_path.rst +++ b/doc/en/how-to/tmp_path.rst @@ -136,9 +136,9 @@ Temporary directory location and retention The temporary directories, as returned by the :fixture:`tmp_path` and (now deprecated) :fixture:`tmpdir` fixtures, are automatically created under a base temporary directory, -in a structure that depends on the ``--basetemp`` option: +in a structure that depends on the :option:`--basetemp` option: -- By default (when the ``--basetemp`` option is not set), +- By default (when the :option:`--basetemp` option is not set), the temporary directories will follow this template: .. code-block:: text @@ -160,7 +160,7 @@ in a structure that depends on the ``--basetemp`` option: but this behavior can be configured with :confval:`tmp_path_retention_count` and :confval:`tmp_path_retention_policy`. -- When the ``--basetemp`` option is used (e.g. ``pytest --basetemp=mydir``), +- When the :option:`--basetemp` option is used (e.g. ``pytest --basetemp=mydir``), it will be used directly as base temporary directory: .. code-block:: text @@ -172,7 +172,7 @@ in a structure that depends on the ``--basetemp`` option: .. warning:: - The directory given to ``--basetemp`` will be cleared blindly before each test run, + The directory given to :option:`--basetemp` will be cleared blindly before each test run, so make sure to use a directory for that purpose only. When distributing tests on the local machine using ``pytest-xdist``, care is taken to diff --git a/doc/en/how-to/unittest.rst b/doc/en/how-to/unittest.rst index 12511fed262..0762e7d4cf8 100644 --- a/doc/en/how-to/unittest.rst +++ b/doc/en/how-to/unittest.rst @@ -42,7 +42,7 @@ in most cases without having to modify existing code: * Obtain :ref:`more informative tracebacks `; * :ref:`stdout and stderr ` capturing; -* :ref:`Test selection options ` using ``-k`` and ``-m`` flags; +* :ref:`Test selection options ` using :option:`-k` and :option:`-m` flags; * :ref:`maxfail`; * :ref:`--pdb ` command-line option for debugging on test failures (see :ref:`note ` below); diff --git a/doc/en/how-to/usage.rst b/doc/en/how-to/usage.rst index 0e0a0310fd8..94e6d94d834 100644 --- a/doc/en/how-to/usage.rst +++ b/doc/en/how-to/usage.rst @@ -4,7 +4,7 @@ How to invoke pytest ========================================== -.. seealso:: :ref:`Complete pytest command-line flag reference ` +.. seealso:: :ref:`Complete pytest command-line flags reference ` In general, pytest is invoked with the command ``pytest`` (see below for :ref:`other ways to invoke pytest `). This will execute all tests in all files whose names follow the form ``test_*.py`` or ``\*_test.py`` @@ -155,7 +155,7 @@ Managing loading of plugins Early loading plugins ~~~~~~~~~~~~~~~~~~~~~~~ -You can early-load plugins (internal and external) explicitly in the command-line with the ``-p`` option:: +You can early-load plugins (internal and external) explicitly in the command-line with the :option:`-p` option:: pytest -p mypluginmodule @@ -171,7 +171,7 @@ The option receives a ``name`` parameter, which can be: Disabling plugins ~~~~~~~~~~~~~~~~~~ -To disable loading specific plugins at invocation time, use the ``-p`` option +To disable loading specific plugins at invocation time, use the :option:`-p` option together with the prefix ``no:``. Example: to disable loading the plugin ``doctest``, which is responsible for diff --git a/doc/en/how-to/writing_plugins.rst b/doc/en/how-to/writing_plugins.rst index ec10c0e261c..6b7e2a7e496 100644 --- a/doc/en/how-to/writing_plugins.rst +++ b/doc/en/how-to/writing_plugins.rst @@ -295,7 +295,7 @@ the plugin manager like this: plugin = config.pluginmanager.get_plugin("name_of_plugin") If you want to look at the names of existing plugins, use -the ``--trace-config`` option. +the :option:`--trace-config` option. .. _registering-markers: diff --git a/doc/en/reference/customize.rst b/doc/en/reference/customize.rst index 500e5519bdd..b2e7d64cc26 100644 --- a/doc/en/reference/customize.rst +++ b/doc/en/reference/customize.rst @@ -173,7 +173,7 @@ Here's a summary what ``pytest`` uses ``rootdir`` for: ``rootdir`` is **NOT** used to modify ``sys.path``/``PYTHONPATH`` or influence how modules are imported. See :ref:`pythonpath` for more details. -The ``--rootdir=path`` command-line option can be used to force a specific directory. +The :option:`--rootdir=path` command-line option can be used to force a specific directory. Note that contrary to other command-line options, ``--rootdir`` cannot be used with :confval:`addopts` inside a configuration file because the ``rootdir`` is used to *find* the configuration file already. @@ -183,7 +183,7 @@ Finding the ``rootdir`` Here is the algorithm which finds the rootdir from ``args``: -- If ``-c`` is passed in the command-line, use that as configuration file, and its directory as ``rootdir``. +- If :option:`-c` is passed in the command-line, use that as configuration file, and its directory as ``rootdir``. - Determine the common ancestor directory for the specified ``args`` that are recognised as paths that exist in the file system. If no such paths are diff --git a/doc/en/reference/fixtures.rst b/doc/en/reference/fixtures.rst index 02e235ceb9e..b0fa8660f9b 100644 --- a/doc/en/reference/fixtures.rst +++ b/doc/en/reference/fixtures.rst @@ -34,7 +34,7 @@ Built-in fixtures :fixture:`capteesys` Capture in the same manner as :fixture:`capsys`, but also pass text - through according to ``--capture=``. + through according to :option:`--capture`. :fixture:`capsysbinary` Capture, as bytes, output to ``sys.stdout`` and ``sys.stderr``. @@ -281,9 +281,9 @@ searching for them first in the scopes inside ``tests/``. pytest can tell you what fixtures are available for a given test if you call ``pytests`` along with the test's name (or the scope it's in), and provide - the ``--fixtures`` flag, e.g. ``pytest --fixtures test_something.py`` + the :option:`--fixtures` flag, e.g. ``pytest --fixtures test_something.py`` (fixtures with names that start with ``_`` will only be shown if you also - provide the ``-v`` flag). + provide the :option:`-v` flag). .. _`fixture order`: @@ -452,6 +452,6 @@ can't see ``c3``. pytest can tell you what order the fixtures will execute in for a given test if you call ``pytests`` along with the test's name (or the scope it's in), - and provide the ``--setup-plan`` flag, e.g. + and provide the :option:`--setup-plan` flag, e.g. ``pytest --setup-plan test_something.py`` (fixtures with names that start - with ``_`` will only be shown if you also provide the ``-v`` flag). + with ``_`` will only be shown if you also provide the :option:`-v` flag). diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 496fc1b7dbc..7c0a7916684 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1212,7 +1212,7 @@ as discussed in :ref:`temporary directory location and retention`. When set, disables plugin auto-loading through :std:doc:`entry point packaging metadata `. Only plugins -explicitly specified in :envvar:`PYTEST_PLUGINS` or with ``-p`` will be loaded. +explicitly specified in :envvar:`PYTEST_PLUGINS` or with :option:`-p` will be loaded. See also :ref:`--disable-plugin-autoload `. .. envvar:: PYTEST_PLUGINS @@ -1223,7 +1223,7 @@ Contains comma-separated list of modules that should be loaded as plugins: export PYTEST_PLUGINS=mymodule.plugin,xdist -See also ``-p``. +See also :option:`-p`. .. envvar:: PYTEST_THEME @@ -1406,7 +1406,7 @@ passed multiple times. The expected format is ``name=value``. For example:: when collecting Python modules. Default is ``False``. Set to ``True`` if the package you are testing is part of a namespace package. - Namespace packages are also supported as ``--pyargs`` target. + Namespace packages are also supported as :option:`--pyargs` target. Only `native namespace packages `__ are supported, with no plans to support `legacy namespace packages `__. @@ -1739,7 +1739,7 @@ passed multiple times. The expected format is ``name=value``. For example:: Allow selective auto-indentation of multiline log messages. - Supports command line option ``--log-auto-indent [value]`` + Supports command line option :option:`--log-auto-indent=[value]` and config option ``log_auto_indent = [value]`` to set the auto-indentation behavior for all logging. @@ -2123,7 +2123,7 @@ passed multiple times. The expected format is ``name=value``. For example:: Additionally, ``pytest`` will attempt to intelligently identify and ignore a virtualenv. Any directory deemed to be the root of a virtual environment will not be considered during test collection unless - ``--collect-in-virtualenv`` is given. Note also that ``norecursedirs`` + :option:`--collect-in-virtualenv` is given. Note also that ``norecursedirs`` takes precedence over ``--collect-in-virtualenv``; e.g. if you intend to run tests in a virtualenv with a base directory that matches ``'.*'`` you *must* override ``norecursedirs`` in addition to using the @@ -2605,7 +2605,7 @@ passed multiple times. The expected format is ``name=value``. For example:: [pytest] verbosity_assertions = 2 - If not set, defaults to application wide verbosity level (via the ``-v`` command-line option). A special value of + If not set, defaults to application wide verbosity level (via the :option:`-v` command-line option). A special value of ``"auto"`` can be used to explicitly use the global verbosity level. @@ -2628,9 +2628,9 @@ passed multiple times. The expected format is ``name=value``. For example:: verbosity_subtests = 1 A value of ``1`` or higher will show output for **passed** subtests (**failed** subtests are always reported). - Passed subtests output can be suppressed with the value ``0``, which overwrites the ``-v`` command-line option. + Passed subtests output can be suppressed with the value ``0``, which overwrites the :option:`-v` command-line option. - If not set, defaults to application wide verbosity level (via the ``-v`` command-line option). A special value of + If not set, defaults to application wide verbosity level (via the :option:`-v` command-line option). A special value of ``"auto"`` can be used to explicitly use the global verbosity level. See also: :ref:`subtests`. @@ -2654,7 +2654,7 @@ passed multiple times. The expected format is ``name=value``. For example:: [pytest] verbosity_test_cases = 2 - If not set, defaults to application wide verbosity level (via the ``-v`` command-line option). A special value of + If not set, defaults to application wide verbosity level (via the :option:`-v` command-line option). A special value of ``"auto"`` can be used to explicitly use the global verbosity level. @@ -2663,7 +2663,576 @@ passed multiple times. The expected format is ``name=value``. For example:: Command-line Flags ------------------ -All the command-line flags can be obtained by running ``pytest --help``:: +This section documents all command-line options provided by pytest's core plugins. + +.. note:: + + External plugins can add their own command-line options. + This reference documents only the options from pytest's core plugins. + To see all available options including those from installed plugins, run ``pytest --help``. + +Test Selection +~~~~~~~~~~~~~~ + +.. option:: -k EXPRESSION + + Only run tests which match the given substring expression. + An expression is a Python evaluable expression where all names are substring-matched against test names and their parent classes. + + Examples:: + + pytest -k "test_method or test_other" # matches names containing 'test_method' OR 'test_other' + pytest -k "not test_method" # matches names NOT containing 'test_method' + pytest -k "not test_method and not test_other" # excludes both + + The matching is case-insensitive. + Keywords are also matched to classes and functions containing extra names in their ``extra_keyword_matches`` set. + + See :ref:`select-tests` for more information and examples. + +.. option:: -m MARKEXPR + + Only run tests matching given mark expression. + Supports ``and``, ``or``, and ``not`` operators. + + Examples:: + + pytest -m slow # run tests marked with @pytest.mark.slow + pytest -m "not slow" # run tests NOT marked slow + pytest -m "mark1 and not mark2" # run tests marked mark1 but not mark2 + + See :ref:`mark` for more information on markers. + +.. option:: --markers + + Show all available markers (builtin, plugin, and per-project markers defined in configuration). + +Test Execution Control +~~~~~~~~~~~~~~~~~~~~~~~ + +.. option:: -x, --exitfirst + + Exit instantly on first error or failed test. + +.. option:: --maxfail=NUM + + Exit after first ``num`` failures or errors. + Useful for CI environments where you want to fail fast but see a few failures. + +.. option:: --last-failed, --lf + + Rerun only the tests that failed at the last run. + If no tests failed (or no cached data exists), all tests are run. + See also :confval:`cache_dir` and :ref:`cache`. + +.. option:: --failed-first, --ff + + Run all tests, but run the last failures first. + This may re-order tests and thus lead to repeated fixture setup/teardown. + +.. option:: --new-first, --nf + + Run tests from new files first, then the rest of the tests sorted by file modification time. + +.. option:: --stepwise, --sw + + Exit on test failure and continue from last failing test next time. + Useful for fixing multiple test failures one at a time. + + See :ref:`cache stepwise` for more information. + +.. option:: --stepwise-skip, --sw-skip + + Ignore the first failing test but stop on the next failing test. + Implicitly enables :option:`--stepwise`. + +.. option:: --stepwise-reset, --sw-reset + + Resets stepwise state, restarting the stepwise workflow. + Implicitly enables :option:`--stepwise`. + +.. option:: --last-failed-no-failures, --lfnf + + With :option:`--last-failed`, determines whether to execute tests when there are no previously known failures or when no cached ``lastfailed`` data was found. + + * ``all`` (default): runs the full test suite again + * ``none``: just emits a message about no known failures and exits successfully + +.. option:: --runxfail + + Report the results of xfail tests as if they were not marked. + Useful for debugging xfailed tests. + See :ref:`xfail`. + +Collection +~~~~~~~~~~ + +.. option:: --collect-only, --co + + Only collect tests, don't execute them. + Shows which tests would be collected and run. + +.. option:: --pyargs + + Try to interpret all arguments as Python packages. + Useful for running tests of installed packages:: + + pytest --pyargs pkg.testing + +.. option:: --ignore=PATH + + Ignore path during collection (multi-allowed). + Can be specified multiple times. + +.. option:: --ignore-glob=PATTERN + + Ignore path pattern during collection (multi-allowed). + Supports glob patterns. + +.. option:: --deselect=NODEID_PREFIX + + Deselect item (via node id prefix) during collection (multi-allowed). + +.. option:: --confcutdir=DIR + + Only load ``conftest.py`` files relative to specified directory. + +.. option:: --noconftest + + Don't load any ``conftest.py`` files. + +.. option:: --keep-duplicates + + Keep duplicate tests. By default, pytest removes duplicate test items. + +.. option:: --collect-in-virtualenv + + Don't ignore tests in a local virtualenv directory. + By default, pytest skips tests in virtualenv directories. + +.. option:: --continue-on-collection-errors + + Force test execution even if collection errors occur. + +.. option:: --import-mode + + Prepend/append to sys.path when importing test modules and conftest files. + + * ``prepend`` (default): prepend to sys.path + * ``append``: append to sys.path + * ``importlib``: use importlib to import test modules + + See :ref:`pythonpath` for more information. + +Fixtures +~~~~~~~~ + +.. option:: --fixtures, --funcargs + + Show available fixtures, sorted by plugin appearance. + Fixtures with leading ``_`` are only shown with :option:`--verbose`. + +.. option:: --fixtures-per-test + + Show fixtures per test. + +.. option:: --setup-only + + Only setup fixtures, do not execute tests. + See :ref:`how-to-fixtures`. + +.. option:: --setup-show + + Show setup of fixtures while executing tests. + +.. option:: --setup-plan + + Show what fixtures and tests would be executed but don't execute anything. + +Debugging +~~~~~~~~~ + +.. option:: --pdb + + Start the interactive Python debugger on errors or KeyboardInterrupt. + See :ref:`pdb-option`. + +.. option:: --pdbcls=MODULENAME:CLASSNAME + + Specify a custom interactive Python debugger for use with :option:`--pdb`. + + Example:: + + pytest --pdbcls=IPython.terminal.debugger:TerminalPdb + +.. option:: --trace + + Immediately break when running each test. + + See :ref:`trace-option` for more information. + +.. option:: --full-trace + + Don't cut any tracebacks (default is to cut). + + See :ref:`how-to-modifying-python-tb-printing` for more information. + +.. option:: --debug, --debug=DEBUG_FILE_NAME + + Store internal tracing debug information in this log file. + This file is opened with ``'w'`` and truncated as a result, care advised. + Default file name if not specified: ``pytestdebug.log``. + +.. option:: --trace-config + + Trace considerations of conftest.py files. + +Output and Reporting +~~~~~~~~~~~~~~~~~~~~ + +.. option:: -v, --verbose + + Increase verbosity. + Can be specified multiple times (e.g., ``-vv``) for even more verbose output. + + See :ref:`pytest.fine_grained_verbosity` for fine-grained control over verbosity. + +.. option:: -q, --quiet + + Decrease verbosity. + +.. option:: --verbosity=NUM + + Set verbosity level explicitly. Default: 0. + +.. option:: -r CHARS + + Show extra test summary info as specified by chars: + + * ``f``: failed + * ``E``: error + * ``s``: skipped + * ``x``: xfailed + * ``X``: xpassed + * ``p``: passed + * ``P``: passed with output + * ``a``: all except passed (p/P) + * ``A``: all + * ``w``: warnings (enabled by default) + * ``N``: resets the list + + Default: ``'fE'`` + + Examples:: + + pytest -rA # show all outcomes + pytest -rfE # show only failed and errors (default) + pytest -rfs # show failed and skipped + + See :ref:`pytest.detailed_failed_tests_usage` for more information. + +.. option:: --no-header + + Disable header. + +.. option:: --no-summary + + Disable summary. + +.. option:: --no-fold-skipped + + Do not fold skipped tests in short summary. + +.. option:: --force-short-summary + + Force condensed summary output regardless of verbosity level. + +.. option:: -l, --showlocals + + Show locals in tracebacks (disabled by default). + +.. option:: --no-showlocals + + Hide locals in tracebacks (negate :option:`--showlocals` passed through addopts). + +.. option:: --tb=STYLE + + Traceback print mode: + + * ``auto``: intelligent traceback formatting (default) + * ``long``: exhaustive, informative traceback formatting + * ``short``: shorter traceback format + * ``line``: only the failing line + * ``native``: Python's standard traceback + * ``no``: no traceback + + See :ref:`how-to-modifying-python-tb-printing` for examples. + +.. option:: --xfail-tb + + Show tracebacks for xfail (as long as :option:`--tb` != ``no``). + +.. option:: --show-capture + + Controls how captured stdout/stderr/log is shown on failed tests. + + * ``no``: don't show captured output + * ``stdout``: show captured stdout + * ``stderr``: show captured stderr + * ``log``: show captured logging + * ``all`` (default): show all captured output + +.. option:: --color=WHEN + + Color terminal output: + + * ``yes``: always use color + * ``no``: never use color + * ``auto`` (default): use color if terminal supports it + +.. option:: --code-highlight={yes,no} + + Whether code should be highlighted (only if :option:`--color` is also enabled). + Default: ``yes``. + +.. option:: --pastebin=MODE + + Send failed|all info to bpaste.net pastebin service. + +.. option:: --durations=NUM + + Show N slowest setup/test durations (N=0 for all). + See :ref:`durations`. + +.. option:: --durations-min=NUM + + Minimal duration in seconds for inclusion in slowest list. + Default: 0.005 (or 0.0 if ``-vv`` is given). + +Output Capture +~~~~~~~~~~~~~~ + +.. option:: --capture=METHOD + + Per-test capturing method: + + * ``fd``: capture at file descriptor level (default) + * ``sys``: capture at sys level + * ``no``: don't capture output + * ``tee-sys``: capture but also show output on terminal + + See :ref:`captures`. + +.. option:: -s + + Shortcut for :option:`--capture=no`. + +JUnit XML +~~~~~~~~~ + +.. option:: --junit-xml=PATH, --junitxml=PATH + + Create junit-xml style report file at given path. + +.. option:: --junit-prefix=STR, --junitprefix=STR + + Prepend prefix to classnames in junit-xml output. + +Cache +~~~~~ + +.. option:: --cache-show[=PATTERN] + + Show cache contents, don't perform collection or tests. + Default glob pattern: ``'*'``. + +.. option:: --cache-clear + + Remove all cache contents at start of test run. + See :ref:`cache`. + +Warnings +~~~~~~~~ + +.. option:: --disable-pytest-warnings, --disable-warnings + + Disable warnings summary. + +.. option:: -W WARNING, --pythonwarnings=WARNING + + Set which warnings to report, see ``-W`` option of Python itself. + Can be specified multiple times. + +Doctest +~~~~~~~ + +.. option:: --doctest-modules + + Run doctests in all .py modules. + + See :ref:`doctest` for more information on using doctests with pytest. + +.. option:: --doctest-report + + Choose another output format for diffs on doctest failure: + + * ``none`` + * ``cdiff`` + * ``ndiff`` + * ``udiff`` + * ``only_first_failure`` + +.. option:: --doctest-glob=PATTERN + + Doctests file matching pattern. + Default: ``test*.txt``. + +.. option:: --doctest-ignore-import-errors + + Ignore doctest collection errors. + +.. option:: --doctest-continue-on-failure + + For a given doctest, continue to run after the first failure. + +Configuration +~~~~~~~~~~~~~ + +.. option:: -c FILE, --config-file=FILE + + Load configuration from ``FILE`` instead of trying to locate one of the implicit configuration files. + +.. option:: --rootdir=ROOTDIR + + Define root directory for tests. + Can be relative path: ``'root_dir'``, ``'./root_dir'``, ``'root_dir/another_dir/'``; absolute path: ``'/home/user/root_dir'``; path with variables: ``'$HOME/root_dir'``. + +.. option:: --basetemp=DIR + + Base temporary directory for this test run. + Warning: this directory is removed if it exists. + + See :ref:`temporary directory location and retention` for more information. + +.. option:: -o OPTION=VALUE, --override-ini=OPTION=VALUE + + Override configuration option with ``option=value`` style. + Can be specified multiple times. + + Example:: + + pytest -o strict_xfail=true -o cache_dir=cache + +.. option:: --strict-config + + Enables the :confval:`strict_config` option. + +.. option:: --strict-markers + + Enables the :confval:`strict_markers` option. + +.. option:: --strict + + Enables the :confval:`strict` option (which enables all strictness options). + +.. option:: --assert=MODE + + Control assertion debugging tools: + + * ``plain``: performs no assertion debugging + * ``rewrite`` (default): rewrites assert statements in test modules on import to provide assert expression information + +Logging +~~~~~~~ + +See :ref:`logging` for a guide on using these flags. + +.. option:: --log-level=LEVEL + + Level of messages to catch/display. + Not set by default, so it depends on the root/parent log handler's effective level, where it is ``WARNING`` by default. + +.. option:: --log-format=FORMAT + + Log format used by the logging module. + +.. option:: --log-date-format=FORMAT + + Log date format used by the logging module. + +.. option:: --log-cli-level=LEVEL + + CLI logging level. See :ref:`live_logs`. + +.. option:: --log-cli-format=FORMAT + + Log format used by the logging module for CLI output. + +.. option:: --log-cli-date-format=FORMAT + + Log date format used by the logging module for CLI output. + +.. option:: --log-file=PATH + + Path to a file when logging will be written to. + +.. option:: --log-file-mode + + Log file open mode: + + * ``w`` (default): recreate the file + * ``a``: append to the file + +.. option:: --log-file-level=LEVEL + + Log file logging level. + +.. option:: --log-file-format=FORMAT + + Log format used by the logging module for the log file. + +.. option:: --log-file-date-format=FORMAT + + Log date format used by the logging module for the log file. + +.. option:: --log-auto-indent=VALUE + + Auto-indent multiline messages passed to the logging module. + Accepts ``true|on``, ``false|off`` or an integer. + +.. option:: --log-disable=LOGGER + + Disable a logger by name. Can be passed multiple times. + +Plugin and Extension Management +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. option:: -p NAME + + Early-load given plugin module name or entry point (multi-allowed). + To avoid loading of plugins, use the ``no:`` prefix, e.g. ``no:doctest``. + See also :option:`--disable-plugin-autoload`. + +.. option:: --disable-plugin-autoload + + Disable plugin auto-loading through entry point packaging metadata. + Only plugins explicitly specified in :option:`-p` or env var :envvar:`PYTEST_PLUGINS` will be loaded. + +Version and Help +~~~~~~~~~~~~~~~~ + +.. option:: -V, --version + + Display pytest version and information about plugins. When given twice, also display information about plugins. + +.. option:: -h, --help + + Show help message and configuration info. + +Complete Help Output +~~~~~~~~~~~~~~~~~~~~ + +All the command-line flags can also be obtained by running ``pytest --help``:: $ pytest --help usage: pytest [options] [file_or_dir] [file_or_dir] [...] @@ -2722,7 +3291,7 @@ All the command-line flags can be obtained by running ``pytest --help``:: tests. Optional argument: glob (default: '*'). --cache-clear Remove all cache contents at start of test run --lfnf, --last-failed-no-failures={all,none} - With ``--lf``, determines whether to execute tests + With :option:`--lf`, determines whether to execute tests when there are no previously (known) failures or when no cached ``lastfailed`` data was found. ``all`` (the default) runs the full test suite From b7d7bef90cb9a6db8ac1d3dd5b9ae0eb9abd6c58 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 6 Dec 2025 22:21:50 +0200 Subject: [PATCH 27/74] Merge pull request #14014 from bluetech/compat-note doc: add compat note about `config.args` to pytest 9.0.0 changelog (cherry picked from commit 1e4b01d1fd637cd2d293c562807a2c79042c692d) --- doc/en/changelog.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index d9e9928db00..8f869634c73 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -266,6 +266,9 @@ Removals and backward incompatible breaking changes now, CI mode is only activated if at least one of those variables is defined and set to a *non-empty* value. +- The non-public ``config.args`` attribute used to be able to contain ``pathlib.Path`` instances; now it can only contain strings. + + - `#13779 `_: **PytestRemovedIn9Warning deprecation warnings are now errors by default.** Following our plan to remove deprecated features with as little disruption as From 3d10b5148e03eb82b3ee29181dbdc73cf82699e2 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sat, 6 Dec 2025 21:07:49 +0000 Subject: [PATCH 28/74] Prepare release version 9.0.2 --- changelog/13896.bugfix.rst | 5 ----- changelog/13904.bugfix.rst | 1 - changelog/13946.bugfix.rst | 3 --- changelog/13965.bugfix.rst | 1 - changelog/4492.doc.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-9.0.2.rst | 22 ++++++++++++++++++++ doc/en/builtin.rst | 8 ++++---- doc/en/changelog.rst | 31 +++++++++++++++++++++++++++++ doc/en/example/parametrize.rst | 6 +++--- doc/en/example/pythoncollection.rst | 4 ++-- doc/en/getting-started.rst | 2 +- doc/en/how-to/fixtures.rst | 2 +- doc/en/reference/reference.rst | 2 +- 14 files changed, 66 insertions(+), 23 deletions(-) delete mode 100644 changelog/13896.bugfix.rst delete mode 100644 changelog/13904.bugfix.rst delete mode 100644 changelog/13946.bugfix.rst delete mode 100644 changelog/13965.bugfix.rst delete mode 100644 changelog/4492.doc.rst create mode 100644 doc/en/announce/release-9.0.2.rst diff --git a/changelog/13896.bugfix.rst b/changelog/13896.bugfix.rst deleted file mode 100644 index 187be00cc4d..00000000000 --- a/changelog/13896.bugfix.rst +++ /dev/null @@ -1,5 +0,0 @@ -The terminal progress feature added in pytest 9.0.0 has been disabled by default, except on Windows, due to compatibility issues with some terminal emulators. - -You may enable it again by passing ``-p terminalprogress``. We may enable it by default again once compatibility improves in the future. - -Additionally, when the environment variable ``TERM`` is ``dumb``, the escape codes are no longer emitted, even if the plugin is enabled. diff --git a/changelog/13904.bugfix.rst b/changelog/13904.bugfix.rst deleted file mode 100644 index f5a42215ca8..00000000000 --- a/changelog/13904.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed the TOML type of the :confval:`tmp_path_retention_count` settings in the API reference from number to string. diff --git a/changelog/13946.bugfix.rst b/changelog/13946.bugfix.rst deleted file mode 100644 index d6cc5b703e4..00000000000 --- a/changelog/13946.bugfix.rst +++ /dev/null @@ -1,3 +0,0 @@ -The private ``config.inicfg`` attribute was changed in a breaking manner in pytest 9.0.0. -Due to its usage in the ecosystem, it is now restored to working order using a compatibility shim. -It will be deprecated in pytest 9.1 and removed in pytest 10. diff --git a/changelog/13965.bugfix.rst b/changelog/13965.bugfix.rst deleted file mode 100644 index b910d6c5361..00000000000 --- a/changelog/13965.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed quadratic-time behavior when handling ``unittest`` subtests in Python 3.10. diff --git a/changelog/4492.doc.rst b/changelog/4492.doc.rst deleted file mode 100644 index 811994afb5c..00000000000 --- a/changelog/4492.doc.rst +++ /dev/null @@ -1 +0,0 @@ -The API Reference now contains cross-reference-able documentation of :ref:`pytest's command-line flags `. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 2859e6210ff..b92b8d4a56b 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-9.0.2 release-9.0.1 release-9.0.0 release-8.4.2 diff --git a/doc/en/announce/release-9.0.2.rst b/doc/en/announce/release-9.0.2.rst new file mode 100644 index 00000000000..f15a2dc8e13 --- /dev/null +++ b/doc/en/announce/release-9.0.2.rst @@ -0,0 +1,22 @@ +pytest-9.0.2 +======================================= + +pytest 9.0.2 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Alex Waygood +* Bruno Oliveira +* Fazeel Usmani +* Florian Bruhin +* Ran Benita +* Tom Most +* 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 1a8d32effee..6a96bb0a304 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -53,7 +53,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a capteesys -- .../_pytest/capture.py:1028 Enable simultaneous text capturing and pass-through of writes - to ``sys.stdout`` and ``sys.stderr`` as defined by :option:`--capture`. + to ``sys.stdout`` and ``sys.stderr`` as defined by ``--capture=``. The captured output is made available via ``capteesys.readouterr()`` method @@ -61,7 +61,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a ``out`` and ``err`` will be ``text`` objects. The output is also passed-through, allowing it to be "live-printed", - reported, or both as defined by :option:`--capture`. + reported, or both as defined by ``--capture=``. Returns an instance of :class:`CaptureFixture[str] `. @@ -257,10 +257,10 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a subtests -- .../_pytest/subtests.py:129 Provides subtests functionality. - tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:240 + tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:243 Return a :class:`pytest.TempPathFactory` instance for the test session. - tmp_path -- .../_pytest/tmpdir.py:255 + tmp_path -- .../_pytest/tmpdir.py:258 Return a temporary directory (as :class:`pathlib.Path` object) which is unique to each test function invocation. The temporary directory is created as a subdirectory diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 8f869634c73..b4e5cee694e 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -31,6 +31,37 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 9.0.2 (2025-12-06) +========================= + +Bug fixes +--------- + +- `#13896 `_: The terminal progress feature added in pytest 9.0.0 has been disabled by default, except on Windows, due to compatibility issues with some terminal emulators. + + You may enable it again by passing ``-p terminalprogress``. We may enable it by default again once compatibility improves in the future. + + Additionally, when the environment variable ``TERM`` is ``dumb``, the escape codes are no longer emitted, even if the plugin is enabled. + + +- `#13904 `_: Fixed the TOML type of the :confval:`tmp_path_retention_count` settings in the API reference from number to string. + + +- `#13946 `_: The private ``config.inicfg`` attribute was changed in a breaking manner in pytest 9.0.0. + Due to its usage in the ecosystem, it is now restored to working order using a compatibility shim. + It will be deprecated in pytest 9.1 and removed in pytest 10. + + +- `#13965 `_: Fixed quadratic-time behavior when handling ``unittest`` subtests in Python 3.10. + + + +Improved documentation +---------------------- + +- `#4492 `_: The API Reference now contains cross-reference-able documentation of :ref:`pytest's command-line flags `. + + pytest 9.0.1 (2025-11-12) ========================= diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index 40b63b28ec6..7aec1364953 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -162,7 +162,7 @@ objects, they are still using the default pytest representation: rootdir: /home/sweet/project collected 8 items - + @@ -239,7 +239,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia rootdir: /home/sweet/project collected 4 items - + @@ -318,7 +318,7 @@ Let's first see how it looks like at collection time: rootdir: /home/sweet/project collected 2 items - + diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index ff694f746d7..339944c4758 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -142,7 +142,7 @@ The test collection would look like this: configfile: pytest.toml collected 2 items - + @@ -205,7 +205,7 @@ You can always peek at the collection tree without running tests like this: configfile: pytest.toml collected 3 items - + diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 7365dcdc491..3ba30a90b34 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -20,7 +20,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 9.0.1 + pytest 9.0.2 .. _`simpletest`: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index b15b3a5497b..5c5a239e8d4 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1423,7 +1423,7 @@ Running the above tests results in the following test IDs being used: rootdir: /home/sweet/project collected 12 items - + diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 7c0a7916684..9d14e9147fc 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -3291,7 +3291,7 @@ All the command-line flags can also be obtained by running ``pytest --help``:: tests. Optional argument: glob (default: '*'). --cache-clear Remove all cache contents at start of test run --lfnf, --last-failed-no-failures={all,none} - With :option:`--lf`, determines whether to execute tests + With ``--lf``, determines whether to execute tests when there are no previously (known) failures or when no cached ``lastfailed`` data was found. ``all`` (the default) runs the full test suite From 0075f8e885f28cdaf42c524941d60148c2fad44c Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Tue, 9 Dec 2025 19:33:56 +0000 Subject: [PATCH 29/74] Docs: `deprecated_call` also catches `FutureWarning` (#14038) (#14040) (cherry picked from commit 980bb5c12bac5a765dc0fc76142ba62177d1dba9) Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- doc/en/how-to/capture-warnings.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/how-to/capture-warnings.rst b/doc/en/how-to/capture-warnings.rst index 3f55467b434..46f53b3b462 100644 --- a/doc/en/how-to/capture-warnings.rst +++ b/doc/en/how-to/capture-warnings.rst @@ -286,8 +286,8 @@ Ensuring code triggers a deprecation warning -------------------------------------------- You can also use :func:`pytest.deprecated_call` for checking -that a certain function call triggers a ``DeprecationWarning`` or -``PendingDeprecationWarning``: +that a certain function call triggers a ``DeprecationWarning``, ``PendingDeprecationWarning`` or +``FutureWarning``: .. code-block:: python From 9a70eba7fd991022b83eecc65277e2248a965dcb Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sun, 14 Dec 2025 11:51:09 +0000 Subject: [PATCH 30/74] don't crash if exceptiongroup has only hidden tb frames (#14025) (#14045) * don't crash if exceptiongroup has only hidden tb frames (cherry picked from commit fa6a232d529b33f6388dc788d7613cf206c08130) Co-authored-by: John Litborn <11260241+jakkdl@users.noreply.github.com> --- changelog/13734.bugfix.rst | 1 + src/_pytest/_code/code.py | 8 +++++++- testing/code/test_excinfo.py | 12 ++++++++---- 3 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 changelog/13734.bugfix.rst diff --git a/changelog/13734.bugfix.rst b/changelog/13734.bugfix.rst new file mode 100644 index 00000000000..de1d7368cd4 --- /dev/null +++ b/changelog/13734.bugfix.rst @@ -0,0 +1 @@ +Fixed crash when a test raises an exceptiongroup with ``__tracebackhide__ = True``. diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index add2a493ca7..4cf99a77340 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -1193,9 +1193,15 @@ def repr_excinfo(self, excinfo: ExceptionInfo[BaseException]) -> ExceptionChainR format_exception( type(excinfo.value), excinfo.value, - traceback[0]._rawentry, + traceback[0]._rawentry if traceback else None, ) ) + if not traceback: + reprtraceback.extraline = ( + "All traceback entries are hidden. " + "Pass `--full-trace` to see hidden and internal frames." + ) + else: reprtraceback = self.repr_traceback(excinfo_) reprcrash = excinfo_._getreprcrash() diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 476720f0bbe..70499fec893 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -1897,19 +1897,23 @@ def test_nested_multiple() -> None: @pytest.mark.parametrize("tbstyle", ("long", "short", "auto", "line", "native")) -def test_all_entries_hidden(pytester: Pytester, tbstyle: str) -> None: +@pytest.mark.parametrize("group", (True, False), ids=("group", "bare")) +def test_all_entries_hidden(pytester: Pytester, tbstyle: str, group: bool) -> None: """Regression test for #10903.""" pytester.makepyfile( - """ + f""" + import sys + if sys.version_info < (3, 11): + from exceptiongroup import ExceptionGroup def test(): __tracebackhide__ = True - 1 / 0 + raise {'ExceptionGroup("", [ValueError("bar")])' if group else 'ValueError("bar")'} """ ) result = pytester.runpytest("--tb", tbstyle) assert result.ret == 1 if tbstyle != "line": - result.stdout.fnmatch_lines(["*ZeroDivisionError: division by zero"]) + result.stdout.fnmatch_lines(["*ValueError: bar"]) if tbstyle not in ("line", "native"): result.stdout.fnmatch_lines(["All traceback entries are hidden.*"]) From d5896ad8aa90f53fbf312aefb74dff36af9d6c97 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sat, 27 Dec 2025 23:37:38 +0000 Subject: [PATCH 31/74] Docs: pin sphinx to `<9.0` (#14067) (#14068) Pinning to `<9.0` to fix doc building. Related to https://github.com/python-trio/sphinxcontrib-trio/issues/399. (cherry picked from commit cdb8366e634f429fccb3db5f566d3c57cc298b05) Co-authored-by: Bruno Oliveira --- doc/en/requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/en/requirements.txt b/doc/en/requirements.txt index fcaaee695c9..d672a9d7e15 100644 --- a/doc/en/requirements.txt +++ b/doc/en/requirements.txt @@ -2,7 +2,8 @@ pluggy>=1.5.0 pygments-pytest>=2.5.0 sphinx-removed-in>=0.2.0 -sphinx>=7 +# Pinning to <9.0 due to https://github.com/python-trio/sphinxcontrib-trio/issues/399. +sphinx>=7,<9.0 sphinxcontrib-trio sphinxcontrib-svg2pdfconverter furo From 35dfe8d0ce4311c5336ed23839da64e738da8d79 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sun, 28 Dec 2025 20:01:02 +0000 Subject: [PATCH 32/74] Docs: clarify capture fixture precedence over -s (#14053) (#14073) Clarify in the capturing tutorial that using capture fixtures such as capsys or capfd re-enables capturing for the duration of the test, even when global capturing is disabled via `-s` or `--capture=no`. Closes #13731 (cherry picked from commit 8f5b07d87bf803622bb96227ed939f3c95f8809b) Co-authored-by: Bubble-Interface --- changelog/13731.doc.rst | 1 + doc/en/how-to/capture-stdout-stderr.rst | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 changelog/13731.doc.rst diff --git a/changelog/13731.doc.rst b/changelog/13731.doc.rst new file mode 100644 index 00000000000..0cfdbebfc40 --- /dev/null +++ b/changelog/13731.doc.rst @@ -0,0 +1 @@ +Clarified that capture fixtures (e.g. ``capsys`` and ``capfd``) take precedence over the ``-s`` / ``--capture=no`` command-line options in :ref:`Accessing captured output from a test function `. diff --git a/doc/en/how-to/capture-stdout-stderr.rst b/doc/en/how-to/capture-stdout-stderr.rst index 14807b9b777..8a6a42d4134 100644 --- a/doc/en/how-to/capture-stdout-stderr.rst +++ b/doc/en/how-to/capture-stdout-stderr.rst @@ -109,6 +109,8 @@ of the failing function and hide the other one: FAILED test_module.py::test_func2 - assert False ======================= 1 failed, 1 passed in 0.12s ======================== +.. _accessing-captured-output: + Accessing captured output from a test function --------------------------------------------------- @@ -162,3 +164,13 @@ as a context manager, disabling capture inside the ``with`` block: with capsys.disabled(): print("output not captured, going directly to sys.stdout") print("this output is also captured") + +.. note:: + + When a capture fixture such as :fixture:`capsys` or :fixture:`capfd` is used, + it takes precedence over the global capturing configuration set via + command-line options such as ``-s`` or ``--capture=no``. + + This means that output produced within a test using a capture fixture will + still be captured and available via ``readouterr()``, even if global capturing + is disabled. From e2d53d131eb45734cf53a21c30fb1680ff6f961b Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Mon, 29 Dec 2025 10:23:48 -0300 Subject: [PATCH 33/74] Show better error when blocking conftest files via `-p` (#14018) (#14074) Show a clear message when `-p` is used for a `conftest.py` file, instead of raising an internal assertion error. Fixes #13634 (cherry picked from commit 004a96740fb990c7d6dc39bd305b08852635ec5d) Co-authored-by: Bubble-Interface --- AUTHORS | 1 + changelog/13634.bugfix.rst | 5 +++++ src/_pytest/config/__init__.py | 6 ++++++ testing/test_config.py | 4 ++++ 4 files changed, 16 insertions(+) create mode 100644 changelog/13634.bugfix.rst diff --git a/AUTHORS b/AUTHORS index a089ca678f7..ff37c8fbf26 100644 --- a/AUTHORS +++ b/AUTHORS @@ -311,6 +311,7 @@ Michael Goerz Michael Krebs Michael Seifert Michael Vogt +Michael Reznik Michal Wajszczuk Michał Górny Michał Zięba diff --git a/changelog/13634.bugfix.rst b/changelog/13634.bugfix.rst new file mode 100644 index 00000000000..ee12aeafc3a --- /dev/null +++ b/changelog/13634.bugfix.rst @@ -0,0 +1,5 @@ +Blocking a ``conftest.py`` file using the ``-p no:`` option is now explicitly disallowed. + +Previously this resulted in an internal assertion failure during plugin loading. + +Pytest now raises a clear ``UsageError`` explaining that conftest files are not plugins and cannot be disabled via ``-p``. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 6b02e160e1a..a027dbc02a4 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -814,6 +814,12 @@ def consider_pluginarg(self, arg: str) -> None: if name in essential_plugins: raise UsageError(f"plugin {name} cannot be disabled") + if name.endswith("conftest.py"): + raise UsageError( + f"Blocking conftest files using -p is not supported: -p no:{name}\n" + "conftest.py files are not plugins and cannot be disabled via -p.\n" + ) + # PR #4304: remove stepwise if cacheprovider is blocked. if name == "cacheprovider": self.set_blocked("stepwise") diff --git a/testing/test_config.py b/testing/test_config.py index 2556e4e00aa..f086778ad1e 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -2460,6 +2460,10 @@ def test_config_does_not_load_blocked_plugin_from_args(pytester: Pytester) -> No result.stderr.fnmatch_lines(["*: error: unrecognized arguments: -s"]) assert result.ret == ExitCode.USAGE_ERROR + result = pytester.runpytest(str(p), "-p no:/path/to/conftest.py", "-s") + result.stderr.fnmatch_lines(["ERROR:*Blocking conftest files*"]) + assert result.ret == ExitCode.USAGE_ERROR + def test_invocation_args(pytester: Pytester) -> None: """Ensure that Config.invocation_* arguments are correctly defined""" From 0d3347509b7523c780af69af619f2dd652b464cc Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Tue, 6 Jan 2026 12:07:07 +0000 Subject: [PATCH 34/74] Clarify `pytest_collection_finish` occurs after setting `session.items` (#14088) (#14089) (cherry picked from commit 0e9db5fa5a8de151ab43e5d71e0e8192e0456b9d) Co-authored-by: Liam DeVoe --- .gitignore | 1 + changelog/14088.doc.rst | 1 + doc/en/reference/reference.rst | 1 + src/_pytest/hookspec.py | 4 ++-- 4 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 changelog/14088.doc.rst diff --git a/.gitignore b/.gitignore index c4557b33a1c..d0e8dc54ba1 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ coverage.xml .vscode __pycache__/ .python-version +.claude/settings.local.json # generated by pip pip-wheel-metadata/ diff --git a/changelog/14088.doc.rst b/changelog/14088.doc.rst new file mode 100644 index 00000000000..3f3a0963516 --- /dev/null +++ b/changelog/14088.doc.rst @@ -0,0 +1 @@ +Clarified that the default :hook:`pytest_collection` hook sets ``session.items`` before it calls :hook:`pytest_collection_finish`, not after. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 9d14e9147fc..9206e48ca81 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -757,6 +757,7 @@ items, delete or otherwise amend the test items: If this hook is implemented in ``conftest.py`` files, it always receives all collected items, not only those under the ``conftest.py`` where it is implemented. +.. hook:: pytest_collection_finish .. autofunction:: pytest_collection_finish Test running (runtest) hooks diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index c5bcc36ad4b..dab3fb698a2 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -251,8 +251,8 @@ def pytest_collection(session: Session) -> object | None: 1. ``pytest_deselected(items)`` for any deselected items (may be called multiple times) - 3. ``pytest_collection_finish(session)`` - 4. Set ``session.items`` to the list of collected items + 3. Set ``session.items`` to the list of collected items + 4. ``pytest_collection_finish(session)`` 5. Set ``session.testscollected`` to the number of collected items You can implement this hook to only perform some action before collection, From 28c4da8b984d853b6f9d2c93c4cadab7a8013998 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 12 Jan 2026 13:27:23 +0200 Subject: [PATCH 35/74] Merge pull request #14106 from flying-sheep/xfail-default typing: default for xfail condition is `True` (cherry picked from commit 317ea9a7c887cccede7e42bc6d82533d3be68c26) --- src/_pytest/mark/structures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 16bb6d81119..97842fc5704 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -496,7 +496,7 @@ def __call__(self, arg: Markable) -> Markable: ... @overload def __call__( self, - condition: str | bool = False, + condition: str | bool = True, *conditions: str | bool, reason: str = ..., run: bool = ..., From 7cb6f8e7a52d05bd15fe6dd467491fc2bc0877bf Mon Sep 17 00:00:00 2001 From: Denis Cherednichenko Date: Mon, 12 Jan 2026 15:00:34 +0300 Subject: [PATCH 36/74] doc: use new-style dict/tuple annotations in simple.rst examples (#14100) (cherry picked from commit c6f7d54996a0b7dde57c57801f92ef3d7f827b07) --- AUTHORS | 1 + doc/en/example/simple.rst | 7 ++----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/AUTHORS b/AUTHORS index ff37c8fbf26..a8c306bb945 100644 --- a/AUTHORS +++ b/AUTHORS @@ -130,6 +130,7 @@ David Szotten David Vierra Daw-Ran Liou Debi Mishra +Denis Cherednichenko Denis Kirisov Denivy Braiam Rück Deysha Rivera diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index 8b35f0ebca5..0640160e3bb 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -553,12 +553,10 @@ an ``incremental`` marker which is to be used on classes: # content of conftest.py - from typing import Dict, Tuple - import pytest # store history of failures per test class name and per index in parametrize (if parametrize used) - _test_failed_incremental: Dict[str, Dict[Tuple[int, ...], str]] = {} + _test_failed_incremental: dict[str, dict[tuple[int, ...], str]] = {} def pytest_runtest_makereport(item, call): @@ -883,11 +881,10 @@ here is a little example implemented via a local plugin: .. code-block:: python # content of conftest.py - from typing import Dict import pytest from pytest import StashKey, CollectReport - phase_report_key = StashKey[Dict[str, CollectReport]]() + phase_report_key = StashKey[dict[str, CollectReport]]() @pytest.hookimpl(wrapper=True, tryfirst=True) From ea26980d87c2681c2e3779ce928774ba7a3b3874 Mon Sep 17 00:00:00 2001 From: Vladimir <51440383+even-even@users.noreply.github.com> Date: Mon, 12 Jan 2026 15:13:44 +0300 Subject: [PATCH 37/74] docs: actualize pytest_version (#14099) (cherry picked from commit fe7e4d5690f691d87cc7adf8cb974c9e614fe51c) --- doc/en/backwards-compatibility.rst | 7 ++++--- doc/en/reference/reference.rst | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/doc/en/backwards-compatibility.rst b/doc/en/backwards-compatibility.rst index d79d112df2d..b62046ae2ac 100644 --- a/doc/en/backwards-compatibility.rst +++ b/doc/en/backwards-compatibility.rst @@ -83,9 +83,10 @@ Released pytest versions support all Python versions that are actively maintaine ============== =================== pytest version min. Python version ============== =================== -8.4+ 3.9+ -8.0+ 3.8+ -7.1+ 3.7+ +9.0+ 3.10+ +8.4 3.9+ +8.0 - 8.3 3.8+ +7.1 - 7.4 3.7+ 6.2 - 7.0 3.6+ 5.0 - 6.1 3.5+ 3.3 - 4.6 2.7, 3.4+ diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 9206e48ca81..b609dc9a810 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -18,7 +18,7 @@ The current pytest version, as a string:: >>> import pytest >>> pytest.__version__ - '7.0.0' + '9.0.2' .. _`hidden-param`: @@ -2539,7 +2539,7 @@ passed multiple times. The expected format is ``name=value``. For example:: .. confval:: truncation_limit_lines - Controls maximum number of linesto truncate assertion message contents. + Controls maximum number of lines to truncate assertion message contents. Setting value to ``0`` disables the lines limit for truncation. From 54f2b3f1d51cb7e68943cdebba2358897767e9cf Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sat, 17 Jan 2026 11:26:04 +0000 Subject: [PATCH 38/74] Docs: clarify -p vs PYTEST_PLUGINS plugin loading (#14113) (#14117) Closes #13388 (cherry picked from commit 6d0aff14ef1aea1636b543c173124a18e61772ee) Co-authored-by: Tejas Verma <98054444+Dooopinder@users.noreply.github.com> --- changelog/13388.doc.rst | 1 + doc/en/how-to/plugins.rst | 30 +++++++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 changelog/13388.doc.rst diff --git a/changelog/13388.doc.rst b/changelog/13388.doc.rst new file mode 100644 index 00000000000..bade402a60d --- /dev/null +++ b/changelog/13388.doc.rst @@ -0,0 +1 @@ +Clarified documentation for ``-p`` vs ``PYTEST_PLUGINS`` plugin loading and fixed an incorrect ``-p`` example. diff --git a/doc/en/how-to/plugins.rst b/doc/en/how-to/plugins.rst index 48a45619324..c6641eb8484 100644 --- a/doc/en/how-to/plugins.rst +++ b/doc/en/how-to/plugins.rst @@ -158,7 +158,7 @@ manually specify each plugin with :option:`-p` or :envvar:`PYTEST_PLUGINS`, you .. code-block:: bash - pytest --disable-plugin-autoload -p NAME,NAME2 + pytest --disable-plugin-autoload -p NAME -p NAME2 .. tab:: toml @@ -180,3 +180,31 @@ manually specify each plugin with :option:`-p` or :envvar:`PYTEST_PLUGINS`, you .. versionadded:: 8.4 The :option:`--disable-plugin-autoload` command-line flag. + +.. note:: + + :option:`-p` and :envvar:`PYTEST_PLUGINS` are both ways to explicitly control which + plugins are loaded, but they serve slightly different use-cases. + + * :option:`-p` loads (or disables with ``-p no:``) a plugin by name or entry point + for a specific pytest invocation, and is processed early during startup. + * :envvar:`PYTEST_PLUGINS` is a comma-separated list of Python modules that are imported + and registered as plugins during startup. This mechanism is commonly used by test + suites, for example when testing a plugin. + + When explicitly controlling plugin loading (especially with + :envvar:`PYTEST_DISABLE_PLUGIN_AUTOLOAD` or :option:`--disable-plugin-autoload`), + avoid specifying the same plugin via multiple mechanisms. Registering the same plugin + more than once can lead to errors during plugin registration. + +Examples: + +.. code-block:: bash + + # Disable auto-loading and load only specific plugins for this invocation + PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 pytest -p xdist + +.. code-block:: bash + + # Disable auto-loading and load plugin modules during startup + PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 PYTEST_PLUGINS=mymodule.plugin,xdist pytest From b3d4f149497d9e1201e3fde10eacce7330f09c9e Mon Sep 17 00:00:00 2001 From: jxramos Date: Sun, 18 Jan 2026 12:38:58 -0800 Subject: [PATCH 39/74] Update changelog to state the removal of the `pytest_cmdline_preparse` hook (#14124) (cherry picked from commit eb0061b74e730a9ac38adc591a8f12312300d4bc) --- doc/en/changelog.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index b4e5cee694e..2133c1b33e3 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -2805,6 +2805,7 @@ Breaking Changes - `#8246 `_: ``--version`` now writes version information to ``stdout`` rather than ``stderr``. +- `#8592 `_: The ``pytest_cmdline_preparse`` hook has been removed following its deprecation. See :ref:`the deprecation note ` for more details. - `#8733 `_: Drop a workaround for `pyreadline `__ that made it work with ``--pdb``. From 72ae54ce6072191c1b16483a5b83e989fa2660dd Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sun, 25 Jan 2026 13:23:01 +0000 Subject: [PATCH 40/74] Fix pytest.approx to correctly take account Mapping keys order to compare them (#13815) (#14142) This fixes an issue with `pytest.approx` where the error message incorrectly reported all elements as mismatched when comparing mappings with different key orders, even when only some values differed. The original code paired values by position rather than by key. This caused incorrect mismatch reporting when dictionary keys were in different orders. Fixes #12444 (cherry picked from commit e95a843a5dbf8af618d0714705bbf97dfdb04044) Co-authored-by: Charles-Meldhine Madi Mnemoi <63333367+cmnemoi@users.noreply.github.com> --- changelog/12444.bugfix.rst | 1 + src/_pytest/python_api.py | 7 +++---- testing/python/approx.py | 40 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 changelog/12444.bugfix.rst diff --git a/changelog/12444.bugfix.rst b/changelog/12444.bugfix.rst new file mode 100644 index 00000000000..146cfc7ab24 --- /dev/null +++ b/changelog/12444.bugfix.rst @@ -0,0 +1 @@ +Fixed :func:`pytest.approx` which now correctly takes account Mapping keys order to compare them. diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 1e389eb0663..bab70aa4a8c 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -242,7 +242,7 @@ def _repr_compare(self, other_side: Mapping[object, float]) -> list[str]: f"Lengths: {len(self.expected)} and {len(other_side)}", ] - if set(self.expected.keys()) != set(other_side.keys()): + if self.expected.keys() != other_side.keys(): return [ "comparison failed.", f"Mappings has different keys: expected {self.expected.keys()} but got {other_side.keys()}", @@ -256,9 +256,8 @@ def _repr_compare(self, other_side: Mapping[object, float]) -> list[str]: max_abs_diff = -math.inf max_rel_diff = -math.inf different_ids = [] - for (approx_key, approx_value), other_value in zip( - approx_side_as_map.items(), other_side.values(), strict=True - ): + for approx_key, approx_value in approx_side_as_map.items(): + other_value = other_side[approx_key] if approx_value != other_value: if approx_value.expected is not None and other_value is not None: try: diff --git a/testing/python/approx.py b/testing/python/approx.py index f870b9bd4d8..481df80565c 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -1062,6 +1062,46 @@ def test_approx_dicts_with_mismatch_on_keys(self) -> None: ): assert actual == approx(expected) + def test_approx_on_unordered_mapping_with_mismatch( + self, pytester: Pytester + ) -> None: + """https://github.com/pytest-dev/pytest/issues/12444""" + pytester.makepyfile( + """ + import pytest + + def test_approx_on_unordered_mapping_with_mismatch(): + expected = {"a": 1, "b": 2, "c": 3, "d": 4} + actual = {"d": 4, "c": 5, "a": 8, "b": 2} + assert actual == pytest.approx(expected) + """ + ) + result = pytester.runpytest() + result.assert_outcomes(failed=1) + result.stdout.fnmatch_lines( + [ + "*comparison failed.**Mismatched elements: 2 / 4:*", + "*Max absolute difference: 7*", + "*Index | Obtained | Expected *", + "* a * | 8 * | 1 *", + "* c * | 5 * | 3 *", + ] + ) + + def test_approx_on_unordered_mapping_matching(self, pytester: Pytester) -> None: + """https://github.com/pytest-dev/pytest/issues/12444""" + pytester.makepyfile( + """ + import pytest + def test_approx_on_unordered_mapping_matching(): + expected = {"a": 1, "b": 2, "c": 3, "d": 4} + actual = {"d": 4, "c": 3, "a": 1, "b": 2} + assert actual == pytest.approx(expected) + """ + ) + result = pytester.runpytest() + result.assert_outcomes(passed=1) + class MyVec3: # incomplete """sequence like""" From e5e48ced9f09bc240d3d855ed48e206aced01f9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BA=F0=9F=87=A6=20Sviatoslav=20Sydorenko=20=28?= =?UTF-8?q?=D0=A1=D0=B2=D1=8F=D1=82=D0=BE=D1=81=D0=BB=D0=B0=D0=B2=20=D0=A1?= =?UTF-8?q?=D0=B8=D0=B4=D0=BE=D1=80=D0=B5=D0=BD=D0=BA=D0=BE=29?= Date: Mon, 9 Feb 2026 09:32:40 +0100 Subject: [PATCH 41/74] Merge pull request #14171 from pytest-dev/dependabot/github_actions/re-actors/alls-green-a638d6464689bbb24c325bb3fe9404d63a913030 build(deps): Bump re-actors/alls-green from 2765efec08f0fd63e83ad900f5fd75646be69ff6 to a638d6464689bbb24c325bb3fe9404d63a913030 (cherry picked from commit d49c94b5c13111790a4b6bc7f320bbc23b2c61e0) --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4914725f778..394ea9b33d7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -306,6 +306,6 @@ jobs: steps: - name: Decide whether the needed jobs succeeded or failed - uses: re-actors/alls-green@2765efec08f0fd63e83ad900f5fd75646be69ff6 + uses: re-actors/alls-green@a638d6464689bbb24c325bb3fe9404d63a913030 with: jobs: ${{ toJSON(needs) }} From 0d0b344856e78dd6443aa8a319e92852a1c8738b Mon Sep 17 00:00:00 2001 From: Freya Bruhin Date: Tue, 10 Feb 2026 16:03:38 +0100 Subject: [PATCH 42/74] Change my name Manually backported from 2a522af6169e014a76871ff1820ed96160ebfb25 --- .mailmap | 2 ++ AUTHORS | 2 +- CITATION | 8 ++++---- CODE_OF_CONDUCT.md | 2 +- doc/en/announce/release-2.8.2.rst | 2 +- doc/en/announce/release-2.8.3.rst | 2 +- doc/en/announce/release-2.8.4.rst | 6 +++--- doc/en/announce/release-2.8.6.rst | 2 +- doc/en/announce/release-2.9.0.rst | 2 +- doc/en/announce/release-2.9.1.rst | 2 +- doc/en/announce/release-2.9.2.rst | 2 +- doc/en/announce/release-3.0.0.rst | 2 +- doc/en/announce/release-3.0.1.rst | 2 +- doc/en/announce/release-3.0.2.rst | 2 +- doc/en/announce/release-3.0.3.rst | 2 +- doc/en/announce/release-3.0.4.rst | 2 +- doc/en/announce/release-3.0.7.rst | 2 +- doc/en/announce/release-3.1.0.rst | 2 +- doc/en/announce/release-3.1.1.rst | 2 +- doc/en/announce/release-3.1.2.rst | 2 +- doc/en/announce/release-3.2.0.rst | 2 +- doc/en/announce/release-3.2.1.rst | 2 +- doc/en/announce/release-3.2.4.rst | 2 +- doc/en/announce/release-3.3.0.rst | 2 +- doc/en/announce/release-3.3.1.rst | 2 +- doc/en/announce/release-3.3.2.rst | 2 +- doc/en/announce/release-3.4.0.rst | 2 +- doc/en/announce/release-3.4.1.rst | 2 +- doc/en/announce/release-3.4.2.rst | 2 +- doc/en/announce/release-3.5.0.rst | 2 +- doc/en/announce/release-5.0.0.rst | 2 +- doc/en/announce/release-5.0.1.rst | 2 +- doc/en/announce/release-5.1.0.rst | 2 +- doc/en/announce/release-5.1.1.rst | 2 +- doc/en/announce/release-5.2.1.rst | 2 +- doc/en/announce/release-5.2.2.rst | 2 +- doc/en/announce/release-5.2.3.rst | 2 +- doc/en/announce/release-5.3.1.rst | 2 +- doc/en/announce/release-6.0.0rc1.rst | 2 +- doc/en/announce/release-6.1.0.rst | 2 +- doc/en/announce/release-6.2.0.rst | 2 +- doc/en/announce/release-6.2.4.rst | 2 +- doc/en/announce/release-6.2.5.rst | 2 +- doc/en/announce/release-7.0.0.rst | 2 +- doc/en/announce/release-7.0.0rc1.rst | 2 +- doc/en/announce/release-7.1.0.rst | 2 +- doc/en/announce/release-7.2.0.rst | 2 +- doc/en/announce/release-7.3.0.rst | 2 +- doc/en/announce/release-7.4.0.rst | 2 +- doc/en/announce/release-7.4.1.rst | 2 +- doc/en/announce/release-8.0.0rc1.rst | 2 +- doc/en/announce/release-8.1.0.rst | 2 +- doc/en/announce/release-8.2.0.rst | 2 +- doc/en/announce/release-8.3.0.rst | 2 +- doc/en/announce/release-8.3.3.rst | 2 +- doc/en/announce/release-8.3.4.rst | 2 +- doc/en/announce/release-8.3.5.rst | 2 +- doc/en/announce/release-8.4.0.rst | 2 +- doc/en/announce/release-8.4.2.rst | 2 +- doc/en/announce/release-9.0.0.rst | 2 +- doc/en/announce/release-9.0.2.rst | 2 +- doc/en/changelog.rst | 12 ++++++------ doc/en/contact.rst | 4 ++-- doc/en/talks.rst | 12 ++++++------ pyproject.toml | 2 +- 65 files changed, 82 insertions(+), 80 deletions(-) create mode 100644 .mailmap diff --git a/.mailmap b/.mailmap new file mode 100644 index 00000000000..682334c7430 --- /dev/null +++ b/.mailmap @@ -0,0 +1,2 @@ +Freya Bruhin +Freya Bruhin diff --git a/AUTHORS b/AUTHORS index a8c306bb945..8b307cd5626 100644 --- a/AUTHORS +++ b/AUTHORS @@ -171,11 +171,11 @@ faph Felix Hofstätter Felix Nieuwenhuizen Feng Ma -Florian Bruhin Florian Dahlitz Floris Bruynooghe Frank Hoffmann Fraser Stark +Freya Bruhin Gabriel Landau Gabriel Reis Garvit Shubham diff --git a/CITATION b/CITATION index 98beee72209..ac7c5d6f312 100644 --- a/CITATION +++ b/CITATION @@ -10,19 +10,19 @@ BibLaTeX: @software{pytest, title = {pytest x.y}, - author = {Holger Krekel and Bruno Oliveira and Ronny Pfannschmidt and Floris Bruynooghe and Brianna Laugher and Florian Bruhin}, + author = {Holger Krekel and Bruno Oliveira and Ronny Pfannschmidt and Floris Bruynooghe and Brianna Laugher and Freya Bruhin}, year = {2004}, version = {x.y}, url = {https://github.com/pytest-dev/pytest}, - note = {Contributors: Holger Krekel and Bruno Oliveira and Ronny Pfannschmidt and Floris Bruynooghe and Brianna Laugher and Florian Bruhin and others} + note = {Contributors: Holger Krekel and Bruno Oliveira and Ronny Pfannschmidt and Floris Bruynooghe and Brianna Laugher and Freya Bruhin and others} } BibTeX: @misc{pytest, - author = {Holger Krekel and Bruno Oliveira and Ronny Pfannschmidt and Floris Bruynooghe and Brianna Laugher and Florian Bruhin}, + author = {Holger Krekel and Bruno Oliveira and Ronny Pfannschmidt and Floris Bruynooghe and Brianna Laugher and Freya Bruhin}, title = {pytest x.y}, year = {2004}, howpublished = {\url{https://github.com/pytest-dev/pytest}}, - note = {Version x.y. Contributors include Holger Krekel, Bruno Oliveira, Ronny Pfannschmidt, Floris Bruynooghe, Brianna Laugher, Florian Bruhin, and others.} + note = {Version x.y. Contributors include Holger Krekel, Bruno Oliveira, Ronny Pfannschmidt, Floris Bruynooghe, Brianna Laugher, Freya Bruhin, and others.} } diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index f0ca304be4e..14d56263449 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -70,7 +70,7 @@ contacted individually: - Brianna Laugher ([@pfctdayelise](https://github.com/pfctdayelise)): brianna@laugher.id.au - Bruno Oliveira ([@nicoddemus](https://github.com/nicoddemus)): nicoddemus@gmail.com -- Florian Bruhin ([@the-compiler](https://github.com/the-compiler)): pytest@the-compiler.org +- Freya Bruhin ([@the-compiler](https://github.com/the-compiler)): pytest@the-compiler.org ## Attribution diff --git a/doc/en/announce/release-2.8.2.rst b/doc/en/announce/release-2.8.2.rst index e4726338852..f64ea9bb29a 100644 --- a/doc/en/announce/release-2.8.2.rst +++ b/doc/en/announce/release-2.8.2.rst @@ -17,7 +17,7 @@ Thanks to all who contributed to this release, among them: Bruno Oliveira Demian Brecht - Florian Bruhin + Freya Bruhin Ionel Cristian Mărieș Raphael Pierzina Ronny Pfannschmidt diff --git a/doc/en/announce/release-2.8.3.rst b/doc/en/announce/release-2.8.3.rst index 3f357252bb6..1ea7aac6d74 100644 --- a/doc/en/announce/release-2.8.3.rst +++ b/doc/en/announce/release-2.8.3.rst @@ -16,7 +16,7 @@ As usual, you can upgrade from pypi via:: Thanks to all who contributed to this release, among them: Bruno Oliveira - Florian Bruhin + Freya Bruhin Gabe Hollombe Gabriel Reis Hartmut Goebel diff --git a/doc/en/announce/release-2.8.4.rst b/doc/en/announce/release-2.8.4.rst index adbdecc87ea..0605c986928 100644 --- a/doc/en/announce/release-2.8.4.rst +++ b/doc/en/announce/release-2.8.4.rst @@ -16,7 +16,7 @@ As usual, you can upgrade from pypi via:: Thanks to all who contributed to this release, among them: Bruno Oliveira - Florian Bruhin + Freya Bruhin Jeff Widman Mehdy Khoshnoody Nicholas Chammas @@ -43,10 +43,10 @@ The py.test Development Team non-ascii characters. Thanks Bruno Oliveira for the PR. - fix #1204: another error when collecting with a nasty __getattr__(). - Thanks Florian Bruhin for the PR. + Thanks Freya Bruhin for the PR. - fix the summary printed when no tests did run. - Thanks Florian Bruhin for the PR. + Thanks Freya Bruhin for the PR. - a number of documentation modernizations wrt good practices. Thanks Bruno Oliveira for the PR. diff --git a/doc/en/announce/release-2.8.6.rst b/doc/en/announce/release-2.8.6.rst index 5d6565b16a3..a63c7f1e38d 100644 --- a/doc/en/announce/release-2.8.6.rst +++ b/doc/en/announce/release-2.8.6.rst @@ -18,7 +18,7 @@ Thanks to all who contributed to this release, among them: AMiT Kumar Bruno Oliveira Erik M. Bray - Florian Bruhin + Freya Bruhin Georgy Dyuldin Jeff Widman Kartik Singhal diff --git a/doc/en/announce/release-2.9.0.rst b/doc/en/announce/release-2.9.0.rst index 753bb7bf6f0..9477f0a9ba3 100644 --- a/doc/en/announce/release-2.9.0.rst +++ b/doc/en/announce/release-2.9.0.rst @@ -18,7 +18,7 @@ Thanks to all who contributed to this release, among them: Bruno Oliveira Buck Golemon David Vierra - Florian Bruhin + Freya Bruhin Galaczi Endre Georgy Dyuldin Lukas Bednar diff --git a/doc/en/announce/release-2.9.1.rst b/doc/en/announce/release-2.9.1.rst index 7a46d2ae690..3880218d233 100644 --- a/doc/en/announce/release-2.9.1.rst +++ b/doc/en/announce/release-2.9.1.rst @@ -17,7 +17,7 @@ Thanks to all who contributed to this release, among them: Bruno Oliveira Daniel Hahler Dmitry Malinovsky - Florian Bruhin + Freya Bruhin Floris Bruynooghe Matt Bachmann Ronny Pfannschmidt diff --git a/doc/en/announce/release-2.9.2.rst b/doc/en/announce/release-2.9.2.rst index 3e75af7fe69..3dc00b46729 100644 --- a/doc/en/announce/release-2.9.2.rst +++ b/doc/en/announce/release-2.9.2.rst @@ -17,7 +17,7 @@ Thanks to all who contributed to this release, among them: Adam Chainz Benjamin Dopplinger Bruno Oliveira - Florian Bruhin + Freya Bruhin John Towler Martin Prusse Meng Jue diff --git a/doc/en/announce/release-3.0.0.rst b/doc/en/announce/release-3.0.0.rst index 5de38911482..b201b901eb7 100644 --- a/doc/en/announce/release-3.0.0.rst +++ b/doc/en/announce/release-3.0.0.rst @@ -39,7 +39,7 @@ Thanks to all who contributed to this release, among them: Dmitry Dygalo Edoardo Batini Eli Boyarski - Florian Bruhin + Freya Bruhin Floris Bruynooghe Greg Price Guyzmo diff --git a/doc/en/announce/release-3.0.1.rst b/doc/en/announce/release-3.0.1.rst index 8f5cfe411aa..b36587f983a 100644 --- a/doc/en/announce/release-3.0.1.rst +++ b/doc/en/announce/release-3.0.1.rst @@ -17,7 +17,7 @@ Thanks to all who contributed to this release, among them: Bruno Oliveira Daniel Hahler Dmitry Dygalo - Florian Bruhin + Freya Bruhin Marcin Bachry Ronny Pfannschmidt matthiasha diff --git a/doc/en/announce/release-3.0.2.rst b/doc/en/announce/release-3.0.2.rst index 86ba82ca6e6..9b1f2acd60d 100644 --- a/doc/en/announce/release-3.0.2.rst +++ b/doc/en/announce/release-3.0.2.rst @@ -14,7 +14,7 @@ Thanks to all who contributed to this release, among them: * Ahn Ki-Wook * Bruno Oliveira -* Florian Bruhin +* Freya Bruhin * Jordan Guymon * Raphael Pierzina * Ronny Pfannschmidt diff --git a/doc/en/announce/release-3.0.3.rst b/doc/en/announce/release-3.0.3.rst index 89a2e0c744e..05bdf4dcd16 100644 --- a/doc/en/announce/release-3.0.3.rst +++ b/doc/en/announce/release-3.0.3.rst @@ -13,7 +13,7 @@ The changelog is available at http://doc.pytest.org/en/stable/changelog.html. Thanks to all who contributed to this release, among them: * Bruno Oliveira -* Florian Bruhin +* Freya Bruhin * Floris Bruynooghe * Huayi Zhang * Lev Maximov diff --git a/doc/en/announce/release-3.0.4.rst b/doc/en/announce/release-3.0.4.rst index 72c2d29464d..ba37bba2111 100644 --- a/doc/en/announce/release-3.0.4.rst +++ b/doc/en/announce/release-3.0.4.rst @@ -14,7 +14,7 @@ Thanks to all who contributed to this release, among them: * Bruno Oliveira * Dan Wandschneider -* Florian Bruhin +* Freya Bruhin * Georgy Dyuldin * Grigorii Eremeev * Jason R. Coombs diff --git a/doc/en/announce/release-3.0.7.rst b/doc/en/announce/release-3.0.7.rst index 4b7e075e76a..782910ae6a4 100644 --- a/doc/en/announce/release-3.0.7.rst +++ b/doc/en/announce/release-3.0.7.rst @@ -14,7 +14,7 @@ Thanks to all who contributed to this release, among them: * Anthony Sottile * Barney Gale * Bruno Oliveira -* Florian Bruhin +* Freya Bruhin * Floris Bruynooghe * Ionel Cristian Mărieș * Katerina Koukiou diff --git a/doc/en/announce/release-3.1.0.rst b/doc/en/announce/release-3.1.0.rst index 55277067948..454c04c6430 100644 --- a/doc/en/announce/release-3.1.0.rst +++ b/doc/en/announce/release-3.1.0.rst @@ -27,7 +27,7 @@ Thanks to all who contributed to this release, among them: * David Giese * David Szotten * Dmitri Pribysh -* Florian Bruhin +* Freya Bruhin * Florian Schulze * Floris Bruynooghe * John Towler diff --git a/doc/en/announce/release-3.1.1.rst b/doc/en/announce/release-3.1.1.rst index 135b2fe8443..99fb0d0f801 100644 --- a/doc/en/announce/release-3.1.1.rst +++ b/doc/en/announce/release-3.1.1.rst @@ -12,7 +12,7 @@ The full changelog is available at http://doc.pytest.org/en/stable/changelog.htm Thanks to all who contributed to this release, among them: * Bruno Oliveira -* Florian Bruhin +* Freya Bruhin * Floris Bruynooghe * Jason R. Coombs * Ronny Pfannschmidt diff --git a/doc/en/announce/release-3.1.2.rst b/doc/en/announce/release-3.1.2.rst index a9b85c4715c..3e988b17e84 100644 --- a/doc/en/announce/release-3.1.2.rst +++ b/doc/en/announce/release-3.1.2.rst @@ -14,7 +14,7 @@ Thanks to all who contributed to this release, among them: * Andreas Pelme * ApaDoctor * Bruno Oliveira -* Florian Bruhin +* Freya Bruhin * Ronny Pfannschmidt * Segev Finer diff --git a/doc/en/announce/release-3.2.0.rst b/doc/en/announce/release-3.2.0.rst index edc66a28e78..68694493907 100644 --- a/doc/en/announce/release-3.2.0.rst +++ b/doc/en/announce/release-3.2.0.rst @@ -25,7 +25,7 @@ Thanks to all who contributed to this release, among them: * Andras Tim * Bruno Oliveira * Daniel Hahler -* Florian Bruhin +* Freya Bruhin * Floris Bruynooghe * John Still * Jordan Moldow diff --git a/doc/en/announce/release-3.2.1.rst b/doc/en/announce/release-3.2.1.rst index c40217d311d..a492390fa58 100644 --- a/doc/en/announce/release-3.2.1.rst +++ b/doc/en/announce/release-3.2.1.rst @@ -13,7 +13,7 @@ Thanks to all who contributed to this release, among them: * Alex Gaynor * Bruno Oliveira -* Florian Bruhin +* Freya Bruhin * Ronny Pfannschmidt * Srinivas Reddy Thatiparthy diff --git a/doc/en/announce/release-3.2.4.rst b/doc/en/announce/release-3.2.4.rst index ff0b35781b1..9bde3afab3b 100644 --- a/doc/en/announce/release-3.2.4.rst +++ b/doc/en/announce/release-3.2.4.rst @@ -15,7 +15,7 @@ Thanks to all who contributed to this release, among them: * Christian Boelsen * Christoph Buchner * Daw-Ran Liou -* Florian Bruhin +* Freya Bruhin * Franck Michea * Leonard Lausen * Matty G diff --git a/doc/en/announce/release-3.3.0.rst b/doc/en/announce/release-3.3.0.rst index 1cbf2c448c8..d54910bea4c 100644 --- a/doc/en/announce/release-3.3.0.rst +++ b/doc/en/announce/release-3.3.0.rst @@ -27,7 +27,7 @@ Thanks to all who contributed to this release, among them: * Daniel Hahler * Dirk Thomas * Dmitry Malinovsky -* Florian Bruhin +* Freya Bruhin * George Y. Kussumoto * Hugo * Jesús Espino diff --git a/doc/en/announce/release-3.3.1.rst b/doc/en/announce/release-3.3.1.rst index 98b6fa6c1ba..a1a0a6d6f45 100644 --- a/doc/en/announce/release-3.3.1.rst +++ b/doc/en/announce/release-3.3.1.rst @@ -14,7 +14,7 @@ Thanks to all who contributed to this release, among them: * Bruno Oliveira * Daniel Hahler * Eugene Prikazchikov -* Florian Bruhin +* Freya Bruhin * Roland Puntaier * Ronny Pfannschmidt * Sebastian Rahlf diff --git a/doc/en/announce/release-3.3.2.rst b/doc/en/announce/release-3.3.2.rst index 7a2577d1ff8..8c4110cc350 100644 --- a/doc/en/announce/release-3.3.2.rst +++ b/doc/en/announce/release-3.3.2.rst @@ -15,7 +15,7 @@ Thanks to all who contributed to this release, among them: * Antony Lee * Austin * Bruno Oliveira -* Florian Bruhin +* Freya Bruhin * Floris Bruynooghe * Henk-Jaap Wagenaar * Jurko Gospodnetić diff --git a/doc/en/announce/release-3.4.0.rst b/doc/en/announce/release-3.4.0.rst index 6ab5b124a25..8a8582f7a00 100644 --- a/doc/en/announce/release-3.4.0.rst +++ b/doc/en/announce/release-3.4.0.rst @@ -30,7 +30,7 @@ Thanks to all who contributed to this release, among them: * Brian Maissy * Bruno Oliveira * Cyrus Maden -* Florian Bruhin +* Freya Bruhin * Henk-Jaap Wagenaar * Ian Lesperance * Jon Dufresne diff --git a/doc/en/announce/release-3.4.1.rst b/doc/en/announce/release-3.4.1.rst index d83949453a2..bef05752698 100644 --- a/doc/en/announce/release-3.4.1.rst +++ b/doc/en/announce/release-3.4.1.rst @@ -16,7 +16,7 @@ Thanks to all who contributed to this release, among them: * Andy Freeland * Brian Maissy * Bruno Oliveira -* Florian Bruhin +* Freya Bruhin * Jason R. Coombs * Marcin Bachry * Pedro Algarvio diff --git a/doc/en/announce/release-3.4.2.rst b/doc/en/announce/release-3.4.2.rst index 07cd9d3a8ba..5ab73986617 100644 --- a/doc/en/announce/release-3.4.2.rst +++ b/doc/en/announce/release-3.4.2.rst @@ -13,7 +13,7 @@ Thanks to all who contributed to this release, among them: * Allan Feldman * Bruno Oliveira -* Florian Bruhin +* Freya Bruhin * Jason R. Coombs * Kyle Altendorf * Maik Figura diff --git a/doc/en/announce/release-3.5.0.rst b/doc/en/announce/release-3.5.0.rst index 6bc2f3cd0cb..7ce2fe3dfe0 100644 --- a/doc/en/announce/release-3.5.0.rst +++ b/doc/en/announce/release-3.5.0.rst @@ -26,7 +26,7 @@ Thanks to all who contributed to this release, among them: * Bruno Oliveira * Carlos Jenkins * Daniel Hahler -* Florian Bruhin +* Freya Bruhin * Jason R. Coombs * Jeffrey Rackauckas * Jordan Speicher diff --git a/doc/en/announce/release-5.0.0.rst b/doc/en/announce/release-5.0.0.rst index f5e593e9d88..166d4e565c3 100644 --- a/doc/en/announce/release-5.0.0.rst +++ b/doc/en/announce/release-5.0.0.rst @@ -26,7 +26,7 @@ Thanks to all who contributed to this release, among them: * Daniel Hahler * Dirk Thomas * Evan Kepner -* Florian Bruhin +* Freya Bruhin * Hugo * Kevin J. Foley * Pulkit Goyal diff --git a/doc/en/announce/release-5.0.1.rst b/doc/en/announce/release-5.0.1.rst index e16a8f716f1..f0ffb791545 100644 --- a/doc/en/announce/release-5.0.1.rst +++ b/doc/en/announce/release-5.0.1.rst @@ -15,7 +15,7 @@ Thanks to all who contributed to this release, among them: * Andreu Vallbona Plazas * Anthony Sottile * Bruno Oliveira -* Florian Bruhin +* Freya Bruhin * Michael Moore * Niklas Meinzer * Thomas Grainger diff --git a/doc/en/announce/release-5.1.0.rst b/doc/en/announce/release-5.1.0.rst index 9ab54ff9730..6170023604a 100644 --- a/doc/en/announce/release-5.1.0.rst +++ b/doc/en/announce/release-5.1.0.rst @@ -27,7 +27,7 @@ Thanks to all who contributed to this release, among them: * Bruno Oliveira * Daniel Hahler * David Röthlisberger -* Florian Bruhin +* Freya Bruhin * Ilya Stepin * Jon Dufresne * Kaiqi diff --git a/doc/en/announce/release-5.1.1.rst b/doc/en/announce/release-5.1.1.rst index bb8de48014a..1262e94fd00 100644 --- a/doc/en/announce/release-5.1.1.rst +++ b/doc/en/announce/release-5.1.1.rst @@ -14,7 +14,7 @@ Thanks to all who contributed to this release, among them: * Anthony Sottile * Bruno Oliveira * Daniel Hahler -* Florian Bruhin +* Freya Bruhin * Hugo van Kemenade * Ran Benita * Ronny Pfannschmidt diff --git a/doc/en/announce/release-5.2.1.rst b/doc/en/announce/release-5.2.1.rst index fe42b9bf15f..904e1b59893 100644 --- a/doc/en/announce/release-5.2.1.rst +++ b/doc/en/announce/release-5.2.1.rst @@ -13,7 +13,7 @@ Thanks to all who contributed to this release, among them: * Anthony Sottile * Bruno Oliveira -* Florian Bruhin +* Freya Bruhin * Hynek Schlawack * Kevin J. Foley * tadashigaki diff --git a/doc/en/announce/release-5.2.2.rst b/doc/en/announce/release-5.2.2.rst index 89fd6a534d4..015baba52e7 100644 --- a/doc/en/announce/release-5.2.2.rst +++ b/doc/en/announce/release-5.2.2.rst @@ -16,7 +16,7 @@ Thanks to all who contributed to this release, among them: * Anthony Sottile * Bruno Oliveira * Daniel Hahler -* Florian Bruhin +* Freya Bruhin * Nattaphoom Chaipreecha * Oliver Bestwalter * Philipp Loose diff --git a/doc/en/announce/release-5.2.3.rst b/doc/en/announce/release-5.2.3.rst index bab174495d9..8c89e04540a 100644 --- a/doc/en/announce/release-5.2.3.rst +++ b/doc/en/announce/release-5.2.3.rst @@ -17,7 +17,7 @@ Thanks to all who contributed to this release, among them: * Daniel Hahler * Daniil Galiev * David Szotten -* Florian Bruhin +* Freya Bruhin * Patrick Harmon * Ran Benita * Zac Hatfield-Dodds diff --git a/doc/en/announce/release-5.3.1.rst b/doc/en/announce/release-5.3.1.rst index d575bb70e3f..5dc82ab7d88 100644 --- a/doc/en/announce/release-5.3.1.rst +++ b/doc/en/announce/release-5.3.1.rst @@ -15,7 +15,7 @@ Thanks to all who contributed to this release, among them: * Bruno Oliveira * Daniel Hahler * Felix Yan -* Florian Bruhin +* Freya Bruhin * Mark Dickinson * Nikolay Kondratyev * Steffen Schroeder diff --git a/doc/en/announce/release-6.0.0rc1.rst b/doc/en/announce/release-6.0.0rc1.rst index 5690b514baf..6f0a745cd00 100644 --- a/doc/en/announce/release-6.0.0rc1.rst +++ b/doc/en/announce/release-6.0.0rc1.rst @@ -25,7 +25,7 @@ Thanks to all who contributed to this release, among them: * David Diaz Barquero * Fabio Zadrozny * Felix Nieuwenhuizen -* Florian Bruhin +* Freya Bruhin * Florian Dahlitz * Gleb Nikonorov * Hugo van Kemenade diff --git a/doc/en/announce/release-6.1.0.rst b/doc/en/announce/release-6.1.0.rst index f4b571ae846..0c787d0bd15 100644 --- a/doc/en/announce/release-6.1.0.rst +++ b/doc/en/announce/release-6.1.0.rst @@ -23,7 +23,7 @@ Thanks to all of the contributors to this release: * C. Titus Brown * Drew Devereux * Faris A Chugthai -* Florian Bruhin +* Freya Bruhin * Hugo van Kemenade * Hynek Schlawack * Joseph Lucas diff --git a/doc/en/announce/release-6.2.0.rst b/doc/en/announce/release-6.2.0.rst index af16b830ddd..8e99d8fcda5 100644 --- a/doc/en/announce/release-6.2.0.rst +++ b/doc/en/announce/release-6.2.0.rst @@ -30,7 +30,7 @@ Thanks to all of the contributors to this release: * Cserna Zsolt * Dominic Mortlock * Emiel van de Laar -* Florian Bruhin +* Freya Bruhin * Garvit Shubham * Gustavo Camargo * Hugo Martins diff --git a/doc/en/announce/release-6.2.4.rst b/doc/en/announce/release-6.2.4.rst index fa2e3e78132..129368e73cd 100644 --- a/doc/en/announce/release-6.2.4.rst +++ b/doc/en/announce/release-6.2.4.rst @@ -14,7 +14,7 @@ Thanks to all of the contributors to this release: * Anthony Sottile * Bruno Oliveira * Christian Maurer -* Florian Bruhin +* Freya Bruhin * Ran Benita diff --git a/doc/en/announce/release-6.2.5.rst b/doc/en/announce/release-6.2.5.rst index bc6b4cf4222..daf9731c800 100644 --- a/doc/en/announce/release-6.2.5.rst +++ b/doc/en/announce/release-6.2.5.rst @@ -15,7 +15,7 @@ Thanks to all of the contributors to this release: * Bruno Oliveira * Brylie Christopher Oxley * Daniel Asztalos -* Florian Bruhin +* Freya Bruhin * Jason Haugen * MapleCCC * Michał Górny diff --git a/doc/en/announce/release-7.0.0.rst b/doc/en/announce/release-7.0.0.rst index 3ce4335564f..934064df745 100644 --- a/doc/en/announce/release-7.0.0.rst +++ b/doc/en/announce/release-7.0.0.rst @@ -34,7 +34,7 @@ Thanks to all of the contributors to this release: * Emmanuel Arias * Emmanuel Meric de Bellefon * Eric Liu -* Florian Bruhin +* Freya Bruhin * GergelyKalmar * Graeme Smecher * Harshna diff --git a/doc/en/announce/release-7.0.0rc1.rst b/doc/en/announce/release-7.0.0rc1.rst index a5bf0ed3c44..dd6ecdd131b 100644 --- a/doc/en/announce/release-7.0.0rc1.rst +++ b/doc/en/announce/release-7.0.0rc1.rst @@ -38,7 +38,7 @@ Thanks to all the contributors to this release: * Emmanuel Arias * Emmanuel Meric de Bellefon * Eric Liu -* Florian Bruhin +* Freya Bruhin * GergelyKalmar * Graeme Smecher * Harshna diff --git a/doc/en/announce/release-7.1.0.rst b/doc/en/announce/release-7.1.0.rst index 3361e1c8a32..f138524c564 100644 --- a/doc/en/announce/release-7.1.0.rst +++ b/doc/en/announce/release-7.1.0.rst @@ -28,7 +28,7 @@ Thanks to all of the contributors to this release: * Elijah DeLee * Emmanuel Arias * Fabian Egli -* Florian Bruhin +* Freya Bruhin * Gabor Szabo * Hasan Ramezani * Hugo van Kemenade diff --git a/doc/en/announce/release-7.2.0.rst b/doc/en/announce/release-7.2.0.rst index eca84aeb669..44cd553ec0f 100644 --- a/doc/en/announce/release-7.2.0.rst +++ b/doc/en/announce/release-7.2.0.rst @@ -33,7 +33,7 @@ Thanks to all of the contributors to this release: * EmptyRabbit * Ezio Melotti * Florian Best -* Florian Bruhin +* Freya Bruhin * Fredrik Berndtsson * Gabriel Landau * Gergely Kalmár diff --git a/doc/en/announce/release-7.3.0.rst b/doc/en/announce/release-7.3.0.rst index 33258dabade..b6d8379d5b5 100644 --- a/doc/en/announce/release-7.3.0.rst +++ b/doc/en/announce/release-7.3.0.rst @@ -42,7 +42,7 @@ Thanks to all of the contributors to this release: * Ezio Melotti * Felix Hofstätter * Florian Best -* Florian Bruhin +* Freya Bruhin * Fredrik Berndtsson * Gabriel Landau * Garvit Shubham diff --git a/doc/en/announce/release-7.4.0.rst b/doc/en/announce/release-7.4.0.rst index 5a0d18267d3..fef2ad6cb3d 100644 --- a/doc/en/announce/release-7.4.0.rst +++ b/doc/en/announce/release-7.4.0.rst @@ -27,7 +27,7 @@ Thanks to all of the contributors to this release: * Bryan Ricker * Chris Mahoney * Facundo Batista -* Florian Bruhin +* Freya Bruhin * Jarrett Keifer * Kenny Y * Miro Hrončok diff --git a/doc/en/announce/release-7.4.1.rst b/doc/en/announce/release-7.4.1.rst index efadcf919e8..4e22d3ead66 100644 --- a/doc/en/announce/release-7.4.1.rst +++ b/doc/en/announce/release-7.4.1.rst @@ -12,7 +12,7 @@ The full changelog is available at https://docs.pytest.org/en/stable/changelog.h Thanks to all of the contributors to this release: * Bruno Oliveira -* Florian Bruhin +* Freya Bruhin * Ran Benita diff --git a/doc/en/announce/release-8.0.0rc1.rst b/doc/en/announce/release-8.0.0rc1.rst index 547c8cbc53b..0cbfc3dad59 100644 --- a/doc/en/announce/release-8.0.0rc1.rst +++ b/doc/en/announce/release-8.0.0rc1.rst @@ -31,7 +31,7 @@ Thanks to all of the contributors to this release: * Christoph Anton Mitterer * DetachHead * Erik Hasse -* Florian Bruhin +* Freya Bruhin * Fraser Stark * Ha Pam * Hugo van Kemenade diff --git a/doc/en/announce/release-8.1.0.rst b/doc/en/announce/release-8.1.0.rst index 62cafdd78bb..6762bd412fe 100644 --- a/doc/en/announce/release-8.1.0.rst +++ b/doc/en/announce/release-8.1.0.rst @@ -28,7 +28,7 @@ Thanks to all of the contributors to this release: * Eric Larson * Fabian Sturm * Faisal Fawad -* Florian Bruhin +* Freya Bruhin * Franck Charras * Joachim B Haga * John Litborn diff --git a/doc/en/announce/release-8.2.0.rst b/doc/en/announce/release-8.2.0.rst index 2a63c8d8722..7aba492d7da 100644 --- a/doc/en/announce/release-8.2.0.rst +++ b/doc/en/announce/release-8.2.0.rst @@ -20,7 +20,7 @@ Thanks to all of the contributors to this release: * Bruno Oliveira * Daniel Miller -* Florian Bruhin +* Freya Bruhin * HolyMagician03-UMich * John Litborn * Levon Saldamli diff --git a/doc/en/announce/release-8.3.0.rst b/doc/en/announce/release-8.3.0.rst index ec5cd3d0db9..0589aedfa89 100644 --- a/doc/en/announce/release-8.3.0.rst +++ b/doc/en/announce/release-8.3.0.rst @@ -24,7 +24,7 @@ Thanks to all of the contributors to this release: * Bruno Oliveira * Cornelius Riemenschneider * Farbod Ahmadian -* Florian Bruhin +* Freya Bruhin * Hynek Schlawack * James Frost * Jason R. Coombs diff --git a/doc/en/announce/release-8.3.3.rst b/doc/en/announce/release-8.3.3.rst index 5e3eb36b921..6e73714d4f9 100644 --- a/doc/en/announce/release-8.3.3.rst +++ b/doc/en/announce/release-8.3.3.rst @@ -16,7 +16,7 @@ Thanks to all of the contributors to this release: * Bruno Oliveira * Christian Clauss * Eugene Mwangi -* Florian Bruhin +* Freya Bruhin * GTowers1 * Nauman Ahmed * Pierre Sassoulas diff --git a/doc/en/announce/release-8.3.4.rst b/doc/en/announce/release-8.3.4.rst index f76d60396dc..3ec21d73f5e 100644 --- a/doc/en/announce/release-8.3.4.rst +++ b/doc/en/announce/release-8.3.4.rst @@ -12,7 +12,7 @@ The full changelog is available at https://docs.pytest.org/en/stable/changelog.h Thanks to all of the contributors to this release: * Bruno Oliveira -* Florian Bruhin +* Freya Bruhin * Frank Hoffmann * Jakob van Santen * Leonardus Chen diff --git a/doc/en/announce/release-8.3.5.rst b/doc/en/announce/release-8.3.5.rst index 3de02c1d7a4..21bae869180 100644 --- a/doc/en/announce/release-8.3.5.rst +++ b/doc/en/announce/release-8.3.5.rst @@ -10,7 +10,7 @@ The full changelog is available at https://docs.pytest.org/en/stable/changelog.h Thanks to all of the contributors to this release: * Bruno Oliveira -* Florian Bruhin +* Freya Bruhin * John Litborn * Kenny Y * Ran Benita diff --git a/doc/en/announce/release-8.4.0.rst b/doc/en/announce/release-8.4.0.rst index 65e80a55919..f492d45070a 100644 --- a/doc/en/announce/release-8.4.0.rst +++ b/doc/en/announce/release-8.4.0.rst @@ -38,7 +38,7 @@ Thanks to all of the contributors to this release: * Deysha Rivera * Emil Hjelm * Eugene Mwangi -* Florian Bruhin +* Freya Bruhin * Frank Hoffmann * GTowers1 * Guillaume Gauvrit diff --git a/doc/en/announce/release-8.4.2.rst b/doc/en/announce/release-8.4.2.rst index 58a842c4d4b..3111e85bd0f 100644 --- a/doc/en/announce/release-8.4.2.rst +++ b/doc/en/announce/release-8.4.2.rst @@ -12,7 +12,7 @@ Thanks to all of the contributors to this release: * AD * Aditi De * Bruno Oliveira -* Florian Bruhin +* Freya Bruhin * John Litborn * Liam DeVoe * Marc Mueller diff --git a/doc/en/announce/release-9.0.0.rst b/doc/en/announce/release-9.0.0.rst index 86dd828f045..67d4f95a56d 100644 --- a/doc/en/announce/release-9.0.0.rst +++ b/doc/en/announce/release-9.0.0.rst @@ -27,7 +27,7 @@ Thanks to all of the contributors to this release: * CoretexShadow * Cornelius Roemer * Eero Vaher -* Florian Bruhin +* Freya Bruhin * Harsha Sai * Hossein * Israël Hallé diff --git a/doc/en/announce/release-9.0.2.rst b/doc/en/announce/release-9.0.2.rst index f15a2dc8e13..f184e1aa4b2 100644 --- a/doc/en/announce/release-9.0.2.rst +++ b/doc/en/announce/release-9.0.2.rst @@ -12,7 +12,7 @@ Thanks to all of the contributors to this release: * Alex Waygood * Bruno Oliveira * Fazeel Usmani -* Florian Bruhin +* Freya Bruhin * Ran Benita * Tom Most * 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 2133c1b33e3..bcae26aa09b 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -9374,10 +9374,10 @@ time or change existing behaviors in order to make them less surprising/more use non-ascii characters. Thanks Bruno Oliveira for the PR. - fix #1204: another error when collecting with a nasty __getattr__(). - Thanks Florian Bruhin for the PR. + Thanks Freya Bruhin for the PR. - fix the summary printed when no tests did run. - Thanks Florian Bruhin for the PR. + Thanks Freya Bruhin for the PR. - fix #1185 - ensure MANIFEST.in exactly matches what should go to a sdist - a number of documentation modernizations wrt good practices. @@ -9499,7 +9499,7 @@ time or change existing behaviors in order to make them less surprising/more use - fix issue934: when string comparison fails and a diff is too large to display without passing -vv, still show a few lines of the diff. - Thanks Florian Bruhin for the report and Bruno Oliveira for the PR. + Thanks Freya Bruhin for the report and Bruno Oliveira for the PR. - fix issue736: Fix a bug where fixture params would be discarded when combined with parametrization markers. @@ -9512,7 +9512,7 @@ time or change existing behaviors in order to make them less surprising/more use - parametrize now also generates meaningful test IDs for enum, regex and class objects (as opposed to class instances). - Thanks to Florian Bruhin for the PR. + Thanks to Freya Bruhin for the PR. - Add 'warns' to assert that warnings are thrown (like 'raises'). Thanks to Eric Hunsberger for the PR. @@ -9639,7 +9639,7 @@ time or change existing behaviors in order to make them less surprising/more use one will also have a "reprec" attribute with the recorded events/reports. - fix monkeypatch.setattr("x.y", raising=False) to actually not raise - if "y" is not a preexisting attribute. Thanks Florian Bruhin. + if "y" is not a preexisting attribute. Thanks Freya Bruhin. - fix issue741: make running output from testdir.run copy/pasteable Thanks Bruno Oliveira. @@ -9699,7 +9699,7 @@ time or change existing behaviors in order to make them less surprising/more use - fix issue833: --fixtures now shows all fixtures of collected test files, instead of just the fixtures declared on the first one. - Thanks Florian Bruhin for reporting and Bruno Oliveira for the PR. + Thanks Freya Bruhin for reporting and Bruno Oliveira for the PR. - fix issue863: skipped tests now report the correct reason when a skip/xfail condition is met when using multiple markers. diff --git a/doc/en/contact.rst b/doc/en/contact.rst index b2a1368eaba..311224eeef0 100644 --- a/doc/en/contact.rst +++ b/doc/en/contact.rst @@ -40,7 +40,7 @@ Mail in the pytest core team, who can also be contacted individually: * Bruno Oliveira (:user:`nicoddemus`, `bruno@pytest.org `_) - * Florian Bruhin (:user:`The-Compiler`, `florian@pytest.org `_) + * Freya Bruhin (:user:`The-Compiler`, `freya@pytest.org `_) * Pierre Sassoulas (:user:`Pierre-Sassoulas`, `pierre@pytest.org `_) * Ran Benita (:user:`bluetech`, `ran@pytest.org `_) * Ronny Pfannschmidt (:user:`RonnyPfannschmidt`, `ronny@pytest.org `_) @@ -51,7 +51,7 @@ Other - The :doc:`contribution guide ` for help on submitting pull requests to GitHub. -- Florian Bruhin (:user:`The-Compiler`) offers pytest professional teaching and +- Freya Bruhin (:user:`The-Compiler`) offers pytest professional teaching and consulting via `Bruhin Software `_. .. _`pytest issue tracker`: https://github.com/pytest-dev/pytest/issues diff --git a/doc/en/talks.rst b/doc/en/talks.rst index b9b153a792e..a45c05c6f2f 100644 --- a/doc/en/talks.rst +++ b/doc/en/talks.rst @@ -17,19 +17,19 @@ Books Talks and blog postings --------------------------------------------- -- Training: `pytest - simple, rapid and fun testing with Python `_, Florian Bruhin, PyConDE 2022 +- Training: `pytest - simple, rapid and fun testing with Python `_, Freya Bruhin, PyConDE 2022 -- `pytest: Simple, rapid and fun testing with Python, `_ (@ 4:22:32), Florian Bruhin, WeAreDevelopers World Congress 2021 +- `pytest: Simple, rapid and fun testing with Python, `_ (@ 4:22:32), Freya Bruhin, WeAreDevelopers World Congress 2021 -- Webinar: `pytest: Test Driven Development für Python (German) `_, Florian Bruhin, via mylearning.ch, 2020 +- Webinar: `pytest: Test Driven Development für Python (German) `_, Freya Bruhin, via mylearning.ch, 2020 - Webinar: `Simplify Your Tests with Fixtures `_, Oliver Bestwalter, via JetBrains, 2020 -- Training: `Introduction to pytest - simple, rapid and fun testing with Python `_, Florian Bruhin, PyConDE 2019 +- Training: `Introduction to pytest - simple, rapid and fun testing with Python `_, Freya Bruhin, PyConDE 2019 - Abridged metaprogramming classics - this episode: pytest, Oliver Bestwalter, PyConDE 2019 (`repository `__, `recording `__) -- Testing PySide/PyQt code easily using the pytest framework, Florian Bruhin, Qt World Summit 2019 (`slides `__, `recording `__) +- Testing PySide/PyQt code easily using the pytest framework, Freya Bruhin, Qt World Summit 2019 (`slides `__, `recording `__) - `pytest: recommendations, basic packages for testing in Python and Django, Andreu Vallbona, PyBCN June 2019 `_. @@ -41,7 +41,7 @@ Talks and blog postings - `Pythonic testing, Igor Starikov (Russian, PyNsk, November 2016) `_. -- `pytest - Rapid Simple Testing, Florian Bruhin, Swiss Python Summit 2016 +- `pytest - Rapid Simple Testing, Freya Bruhin, Swiss Python Summit 2016 `_. - `Improve your testing with Pytest and Mock, Gabe Hollombe, PyCon SG 2015 diff --git a/pyproject.toml b/pyproject.toml index f57d7e8e85b..31b8a029ec5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ authors = [ { name = "Ronny Pfannschmidt" }, { name = "Floris Bruynooghe" }, { name = "Brianna Laugher" }, - { name = "Florian Bruhin" }, + { name = "Freya Bruhin" }, { name = "Others (See AUTHORS)" }, ] requires-python = ">=3.10" From 9482ccb0d55f4e9cc43c8c3587225dbb2a19d74c Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 15:53:11 +0000 Subject: [PATCH 43/74] doc: Adjust training info (#14174) (#14178) The training will be remote-only due to lack of on-site signups (cherry picked from commit e77b9a403f94b4a70d588b62ca4dfb66060b84b4) Co-authored-by: Freya --- doc/en/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/index.rst b/doc/en/index.rst index b98c886d981..77b502e3e41 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -2,7 +2,7 @@ .. sidebar:: **Next Open Trainings and Events** - - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training), **March 3th -- 5th 2026**, Leipzig (DE) / Remote + - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training), **March 3th -- 5th 2026**, Remote Also see :doc:`previous talks and blogposts ` From 4c11ce61740721029ceee2eba4052fc9e1d50f1a Mon Sep 17 00:00:00 2001 From: Alejandro Villate <145073504+aleguy02@users.noreply.github.com> Date: Wed, 11 Feb 2026 11:28:01 -0500 Subject: [PATCH 44/74] Upload junit reports codecov (#13778) Automate uploading JUnit reports to codecov in the test pipeline. An example pipeline run with the changes can be found here (https://github.com/aleguy02/fork-pytest/actions/runs/18184970357). An example of what the codecov UI looks like with these changes can be found here (https://app.codecov.io/gh/aleguy02/fork-pytest/tests). Closes #12689 (cherry picked from commit bda18de6ab84023bd08baf620bc2430f41eb4b5c) --- .github/workflows/test.yml | 12 ++++++++++++ AUTHORS | 1 + changelog/12689.contrib.rst | 5 +++++ tox.ini | 4 ++-- 4 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 changelog/12689.contrib.rst diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 394ea9b33d7..b7f0634d08d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -277,11 +277,15 @@ jobs: - name: Test without coverage if: "! matrix.use_coverage" shell: bash + env: + _PYTEST_TOX_POSARGS_JUNIT: --junitxml=junit.xml run: tox run -e ${{ matrix.tox_env }} --installpkg `find dist/*.tar.gz` - name: Test with coverage if: "matrix.use_coverage" shell: bash + env: + _PYTEST_TOX_POSARGS_JUNIT: --junitxml=junit.xml run: tox run -e ${{ matrix.tox_env }}-coverage --installpkg `find dist/*.tar.gz` - name: Generate coverage report @@ -296,6 +300,14 @@ jobs: files: ./coverage.xml verbose: true + - name: Upload JUnit report to Codecov + uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 + with: + fail_ci_if_error: false + files: junit.xml + report_type: test_results + verbose: true + check: # This job does nothing and is only used for the branch protection if: always() diff --git a/AUTHORS b/AUTHORS index 8b307cd5626..fa6bc58c52f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -14,6 +14,7 @@ Ahn Ki-Wook Akhilesh Ramakrishnan Akiomi Kamakura Alan Velasco +Alejandro Villate Alessio Izzo Alex Jones Alex Lambson diff --git a/changelog/12689.contrib.rst b/changelog/12689.contrib.rst new file mode 100644 index 00000000000..81bb5577d97 --- /dev/null +++ b/changelog/12689.contrib.rst @@ -0,0 +1,5 @@ +The test reports are now published to Codecov from GitHub Actions. +The test statistics is visible `on the web interface +`__. + +-- by :user:`aleguy02` diff --git a/tox.ini b/tox.ini index 70b439f7573..e2e09fa8b7f 100644 --- a/tox.ini +++ b/tox.ini @@ -62,7 +62,7 @@ description = doctesting: including doctests commands = {env:_PYTEST_TOX_COVERAGE_RUN:} pytest {posargs:{env:_PYTEST_TOX_DEFAULT_POSARGS:}} - doctesting: {env:_PYTEST_TOX_COVERAGE_RUN:} pytest --doctest-modules --pyargs _pytest + doctesting: {env:_PYTEST_TOX_COVERAGE_RUN:} pytest --doctest-modules {env:_PYTEST_TOX_POSARGS_JUNIT:} --pyargs _pytest coverage: coverage combine coverage: coverage report -m passenv = @@ -71,7 +71,7 @@ passenv = TERM CI setenv = - _PYTEST_TOX_DEFAULT_POSARGS={env:_PYTEST_TOX_POSARGS_DOCTESTING:} {env:_PYTEST_TOX_POSARGS_LSOF:} {env:_PYTEST_TOX_POSARGS_XDIST:} {env:_PYTEST_FILES:} + _PYTEST_TOX_DEFAULT_POSARGS={env:_PYTEST_TOX_POSARGS_DOCTESTING:} {env:_PYTEST_TOX_POSARGS_JUNIT:} {env:_PYTEST_TOX_POSARGS_LSOF:} {env:_PYTEST_TOX_POSARGS_XDIST:} {env:_PYTEST_FILES:} # See https://docs.python.org/3/library/io.html#io-encoding-warning # If we don't enable this, neither can any of our downstream users! From ca5deb45f10ce672975b9d03a095297f96078b38 Mon Sep 17 00:00:00 2001 From: Ronald Eddy Jr Date: Wed, 11 Feb 2026 13:14:51 -0500 Subject: [PATCH 45/74] doc: fix ~75 typos and grammar issues across documentation (#14179) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix typos, grammar errors, and broken RST directives found across 37 documentation files including how-to guides, reference docs, examples, explanations, and project root files. Notable fixes: - Broken RST directives (``.. note:`` → ``.. note::``) - Subject-verb agreement errors - Missing/incorrect articles and prepositions - Incorrect verb forms ("teared down" → "torn down") - Duplicate words and extra spaces - Wrong URL in changelog (pytest → pytest-xdist) - Ordinal typo ("3th" → "3rd") (cherry picked from commit b2310f28314249e4bfa1e0b9817dbef5cb968f4d) --- CONTRIBUTING.rst | 18 +++++++++--------- RELEASING.rst | 2 +- changelog/12444.bugfix.rst | 2 +- changelog/README.rst | 4 ++-- doc/en/backwards-compatibility.rst | 4 ++-- doc/en/deprecations.rst | 8 ++++---- doc/en/example/attic.rst | 2 +- doc/en/example/customdirectory.rst | 2 +- doc/en/example/markers.rst | 2 +- doc/en/example/parametrize.rst | 4 ++-- doc/en/example/pythoncollection.rst | 2 +- doc/en/example/simple.rst | 6 +++--- doc/en/explanation/ci.rst | 8 ++++---- doc/en/explanation/flaky.rst | 2 +- doc/en/explanation/goodpractices.rst | 4 ++-- doc/en/funcarg_compare.rst | 8 ++++---- doc/en/historical-notes.rst | 2 +- doc/en/how-to/assert.rst | 2 +- doc/en/how-to/cache.rst | 2 +- doc/en/how-to/capture-stdout-stderr.rst | 4 ++-- doc/en/how-to/capture-warnings.rst | 2 +- doc/en/how-to/doctest.rst | 2 +- doc/en/how-to/fixtures.rst | 14 +++++++------- doc/en/how-to/logging.rst | 8 ++++---- doc/en/how-to/monkeypatch.rst | 2 +- doc/en/how-to/output.rst | 2 +- doc/en/how-to/skipping.rst | 2 +- doc/en/how-to/subtests.rst | 2 +- doc/en/how-to/writing_hook_functions.rst | 2 +- doc/en/how-to/writing_plugins.rst | 2 +- doc/en/index.rst | 2 +- doc/en/reference/customize.rst | 6 +++--- doc/en/reference/exit-codes.rst | 2 +- doc/en/reference/fixtures.rst | 10 +++++----- doc/en/reference/reference.rst | 9 ++++----- doc/en/sponsor.rst | 4 ++-- 36 files changed, 79 insertions(+), 80 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index f31c14aec49..fb9f7f4d53d 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -146,7 +146,7 @@ the following: - PyPI presence with packaging metadata that contains a ``pytest-`` prefixed name, version number, authors, short and long description. -- a `tox configuration `_ +- a `tox configuration `_ for running tests using `tox `_. - a ``README`` describing how to use the plugin and on which @@ -280,7 +280,7 @@ Here is a simple overview, with pytest-specific bits: #. You can now edit your local working copy and run the tests again as necessary. Please follow `PEP-8 `_ for naming. You can pass different options to ``tox``. For example, to run tests on Python 3.13 and pass options to pytest - (e.g. enter pdb on failure) to pytest you can do:: + (e.g. enter pdb on failure) you can do:: $ tox -e py313 -- --pdb @@ -346,7 +346,7 @@ For example, to ensure a simple test passes you can write: result.assert_outcomes(failed=0, passed=1) -Alternatively, it is possible to make checks based on the actual output of the termal using +Alternatively, it is possible to make checks based on the actual output of the terminal using *glob-like* expressions: .. code-block:: python @@ -479,10 +479,10 @@ above? to do the backport. 2. However, often the merge is done by another maintainer, in which case it is nice of them to do the backport procedure if they have the time. -3. For bugs submitted by non-maintainers, it is expected that a core developer will to do +3. For bugs submitted by non-maintainers, it is expected that a core developer will do the backport, normally the one that merged the PR on ``main``. -4. If a non-maintainers notices a bug which is fixed on ``main`` but has not been backported - (due to maintainers forgetting to apply the *needs backport* label, or just plain missing it), +4. If a non-maintainer notices a bug which is fixed on ``main`` but has not been backported + (due to maintainers forgetting to apply the *needs backport* or *backport x.x.x* labels, or just plain missing it), they are also welcome to open a PR with the backport. The procedure is simple and really helps with the maintenance of the project. @@ -512,7 +512,7 @@ can always reopen the issue/pull request in their own time later if it makes sen When to close ~~~~~~~~~~~~~ -Here are a few general rules the maintainers use deciding when to close issues/PRs because +Here are a few general rules the maintainers use to decide when to close issues/PRs because of lack of inactivity: * Issues labeled ``question`` or ``needs information``: closed after 14 days inactive. @@ -524,7 +524,7 @@ The above are **not hard rules**, but merely **guidelines**, and can be (and oft Closing pull requests ~~~~~~~~~~~~~~~~~~~~~ -When closing a Pull Request, it needs to be acknowledging the time, effort, and interest demonstrated by the person which submitted it. As mentioned previously, it is not the intent of the team to dismiss a stalled pull request entirely but to merely to clear up our queue, so a message like the one below is warranted when closing a pull request that went stale: +When closing a Pull Request, we should acknowledge the time, effort, and interest demonstrated by the person who submitted it. As mentioned previously, it is not the intent of the team to dismiss a stalled pull request entirely but to merely to clear up our queue, so a message like the one below is warranted when closing a pull request that went stale: Hi , @@ -532,7 +532,7 @@ When closing a Pull Request, it needs to be acknowledging the time, effort, and We noticed it has been awhile since you have updated this PR, however. pytest is a high activity project, with many issues/PRs being opened daily, so it is hard for us maintainers to track which PRs are ready for merging, for review, or need more attention. - So for those reasons we, think it is best to close the PR for now, but with the only intention to clean up our queue, it is by no means a rejection of your changes. We still encourage you to re-open this PR (it is just a click of a button away) when you are ready to get back to it. + So for those reasons, we think it is best to close the PR for now, but with the only intention to clean up our queue, it is by no means a rejection of your changes. We still encourage you to re-open this PR (it is just a click of a button away) when you are ready to get back to it. Again we appreciate your time for working on this, and hope you might get back to this at a later time! diff --git a/RELEASING.rst b/RELEASING.rst index 79b4e2f764d..2b00e658e7a 100644 --- a/RELEASING.rst +++ b/RELEASING.rst @@ -117,7 +117,7 @@ To release a version ``MAJOR.MINOR.PATCH``, follow these steps: #. Create a branch ``release-MAJOR.MINOR.PATCH`` from the ``MAJOR.MINOR.x`` branch. - Ensure your are updated and in a clean working tree. + Ensure your local checkout is up to date and in a clean working tree. #. Using ``tox``, generate docs, changelog, announcements:: diff --git a/changelog/12444.bugfix.rst b/changelog/12444.bugfix.rst index 146cfc7ab24..d4e804ac613 100644 --- a/changelog/12444.bugfix.rst +++ b/changelog/12444.bugfix.rst @@ -1 +1 @@ -Fixed :func:`pytest.approx` which now correctly takes account Mapping keys order to compare them. +Fixed :func:`pytest.approx` which now correctly takes into account :class:`~collections.abc.Mapping` keys order to compare them. diff --git a/changelog/README.rst b/changelog/README.rst index fdaa573d427..f1ba2cbd0bd 100644 --- a/changelog/README.rst +++ b/changelog/README.rst @@ -16,12 +16,12 @@ Each file should be named like ``..rst``, where * ``feature``: new user facing features, like new command-line options and new behavior. * ``improvement``: improvement of existing functionality, usually without requiring user intervention (for example, new fields being written in ``--junit-xml``, improved colors in terminal, etc). * ``bugfix``: fixes a bug. -* ``doc``: documentation improvement, like rewording an entire session or adding missing docs. +* ``doc``: documentation improvement, like rewording an entire section or adding missing docs. * ``deprecation``: feature deprecation. * ``breaking``: a change which may break existing suites, such as feature removal or behavior change. * ``vendor``: changes in packages vendored in pytest. * ``packaging``: notes for downstreams about unobvious side effects - and tooling. changes in the test invocation considerations and + and tooling. Changes in the test invocation considerations and runtime assumptions. * ``contrib``: stuff that affects the contributor experience. e.g. Running tests, building the docs, setting up the development diff --git a/doc/en/backwards-compatibility.rst b/doc/en/backwards-compatibility.rst index b62046ae2ac..a7ee2253d67 100644 --- a/doc/en/backwards-compatibility.rst +++ b/doc/en/backwards-compatibility.rst @@ -53,8 +53,8 @@ History ========= -Focus primary on smooth transition - stance (pre 6.0) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Focus primarily on smooth transition - stance (pre 6.0) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Keeping backwards compatibility has a very high priority in the pytest project. Although we have deprecated functionality over the years, most of it is still supported. All deprecations in pytest were done because simpler or more efficient ways of accomplishing the same tasks have emerged, making the old way of doing things unnecessary. diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 65a05823517..57c583fd852 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -139,7 +139,7 @@ In ``8.2`` the ``exc_type`` parameter has been added, giving users the ability o to skip tests only if the module cannot really be found, and not because of some other error. Catching only :class:`ModuleNotFoundError` by default (and letting other errors propagate) would be the best solution, -however for backward compatibility, pytest will keep the existing behavior but raise an warning if: +however for backward compatibility, pytest will keep the existing behavior but raise a warning if: 1. The captured exception is of type :class:`ImportError`, and: 2. The user does not pass ``exc_type`` explicitly. @@ -358,7 +358,7 @@ The ``yield_fixture`` function/decorator ``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. +It has been so for a very long time, so it can be searched/replaced safely. Removed Features and Breaking Changes @@ -774,7 +774,7 @@ The ``pytest._fillfuncargs`` function This function was kept for backward compatibility with an older plugin. -It's functionality is not meant to be used directly, but if you must replace +Its functionality is not meant to be used directly, but if you must replace it, use `function._request._fillfixtures()` instead, though note this is not a public API and may break in the future. @@ -805,7 +805,7 @@ The ``--result-log`` option produces a stream of test reports which can be analysed at runtime, but it uses a custom format which requires users to implement their own parser. -The `pytest-reportlog `__ plugin provides a ``--report-log`` option, a more standard and extensible alternative, producing +The :pypi:`pytest-reportlog` plugin provides a ``--report-log`` option, a more standard and extensible alternative, producing one JSON object per-line, and should cover the same use cases. Please try it out and provide feedback. The ``pytest-reportlog`` plugin might even be merged into the core diff --git a/doc/en/example/attic.rst b/doc/en/example/attic.rst index 2b1f2766dce..3a2e228337e 100644 --- a/doc/en/example/attic.rst +++ b/doc/en/example/attic.rst @@ -75,7 +75,7 @@ decorate its result. This mechanism allows us to stay ignorant of how/where the function argument is provided - in our example from a `conftest plugin`_. -sidenote: the temporary directory used here are instances of +Side note: the temporary directories used here are instances of the `py.path.local`_ class which provides many of the os.path methods in a convenient way. diff --git a/doc/en/example/customdirectory.rst b/doc/en/example/customdirectory.rst index 6e326352a7e..705a3373654 100644 --- a/doc/en/example/customdirectory.rst +++ b/doc/en/example/customdirectory.rst @@ -36,7 +36,7 @@ You can create a ``manifest.json`` file and some test files: .. include:: customdirectory/tests/test_third.py :literal: -An you can now execute the test specification: +And you can now execute the test specification: .. code-block:: pytest diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst index 4f6738207e1..c8e4172a696 100644 --- a/doc/en/example/markers.rst +++ b/doc/en/example/markers.rst @@ -411,7 +411,7 @@ A test file using this local plugin: def test_basic_db_operation(): pass -and an example invocations specifying a different environment than what +and an example invocation specifying a different environment than what the test needs: .. code-block:: pytest diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index 7aec1364953..b25b822618a 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -4,7 +4,7 @@ Parametrizing tests ================================================= -``pytest`` allows to easily parametrize test functions. +``pytest`` allows you to easily parametrize test functions. For basic docs, see :ref:`parametrize-basics`. In the following we provide some examples using @@ -642,7 +642,7 @@ As the result: - Four tests were collected - One test was deselected because it doesn't have the ``basic`` mark. -- Three tests with the ``basic`` mark was selected. +- Three tests with the ``basic`` mark were selected. - The test ``test_eval[1+7-8]`` passed, but the name is autogenerated and confusing. - The test ``test_eval[basic_2+4]`` passed. - The test ``test_eval[basic_6*9]`` was expected to fail and did fail. diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 339944c4758..26fdb68b08f 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -161,7 +161,7 @@ You can check for multiple glob patterns by adding a space between the patterns: .. note:: - the ``python_functions`` and ``python_classes`` options has no effect + the ``python_functions`` and ``python_classes`` options have no effect for ``unittest.TestCase`` test discovery because pytest delegates discovery of test case methods to unittest code. diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index 0640160e3bb..a07927280ae 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -416,10 +416,10 @@ running from a test you can do this: if os.environ.get("PYTEST_VERSION") is not None: - # Things you want to to do if your code is called by pytest. + # Things you want to do if your code is called by pytest. ... else: - # Things you want to to do if your code is not called by pytest. + # Things you want to do if your code is not called by pytest. ... @@ -773,7 +773,7 @@ The two test modules in the ``a`` directory see the same ``db`` fixture instance while the one test in the sister-directory ``b`` doesn't see it. We could of course also define a ``db`` fixture in that sister directory's ``conftest.py`` file. Note that each fixture is only instantiated if there is a test actually needing -it (unless you use "autouse" fixture which are always executed ahead of the first test +it (unless you use "autouse" fixtures which are always executed ahead of the first test executing). diff --git a/doc/en/explanation/ci.rst b/doc/en/explanation/ci.rst index 6f6734f395b..16f55be81c0 100644 --- a/doc/en/explanation/ci.rst +++ b/doc/en/explanation/ci.rst @@ -8,7 +8,7 @@ Rationale The goal of testing in a CI pipeline is different from testing locally. Indeed, you can quickly edit some code and run your tests again on your computer, but -it is not possible with CI pipeline. They run on a separate server and are +it is not possible with CI pipelines. They run on a separate server and are triggered by specific actions. From that observation, pytest can detect when it is in a CI environment and @@ -17,10 +17,10 @@ adapt some of its behaviours. How CI is detected ------------------ -Pytest knows it is in a CI environment when either one of these environment variables are set to a non-empty value: +Pytest knows it is in a CI environment when either one of these environment variables is set to a non-empty value: -* `CI`: used by many CI systems. -* `BUILD_NUMBER`: used by Jenkins. +* :envvar:`CI`: used by many CI systems. +* :envvar:`BUILD_NUMBER`: used by Jenkins. Effects on CI ------------- diff --git a/doc/en/explanation/flaky.rst b/doc/en/explanation/flaky.rst index 8369e1d9311..918d6f10b36 100644 --- a/doc/en/explanation/flaky.rst +++ b/doc/en/explanation/flaky.rst @@ -42,7 +42,7 @@ It is of course possible (and common) for tests and fixtures to spawn threads th * Make sure to eventually wait on any spawned threads -- for example at the end of a test, or during the teardown of a fixture. * Avoid using primitives provided by pytest (:func:`pytest.warns`, :func:`pytest.raises`, etc) from multiple threads, as they are not thread-safe. -If your test suite uses threads and your are seeing flaky test results, do not discount the possibility that the test is implicitly using global state in pytest itself. +If your test suite uses threads and you are seeing flaky test results, do not discount the possibility that the test is implicitly using global state in pytest itself. Related features ^^^^^^^^^^^^^^^^ diff --git a/doc/en/explanation/goodpractices.rst b/doc/en/explanation/goodpractices.rst index bbc64ec662d..cb894f82e3c 100644 --- a/doc/en/explanation/goodpractices.rst +++ b/doc/en/explanation/goodpractices.rst @@ -143,7 +143,7 @@ which are better explained in this excellent `blog post`_ by Ionel Cristian Măr .. note:: - If you do not use an editable install and not use the ``src`` layout (``mypkg`` directly in the root + If you do not use an editable install and do not use the ``src`` layout (``mypkg`` directly in the root directory) you can rely on the fact that Python by default puts the current directory in ``sys.path`` to import your package and run ``python -m pytest`` to execute the tests against the local copy directly. @@ -376,7 +376,7 @@ If you don't want to automatically pick up new options, you can enable options i strict_parametrization_ids = true strict_xfail = true -If you want to use strict mode but having trouble with a specific option, you can turn it off individually: +If you want to use strict mode but are having trouble with a specific option, you can turn it off individually: .. tab:: toml diff --git a/doc/en/funcarg_compare.rst b/doc/en/funcarg_compare.rst index bc5e7d3c515..7cd4c0f1676 100644 --- a/doc/en/funcarg_compare.rst +++ b/doc/en/funcarg_compare.rst @@ -18,7 +18,7 @@ The pre pytest-2.3 funcarg mechanism calls a factory each time a funcarg for a test function is required. If a factory wants to reuse a resource across different scopes, it often used the ``request.cached_setup()`` helper to manage caching of -resources. Here is a basic example how we could implement +resources. Here is a basic example of how we could implement a per-session Database object: .. code-block:: python @@ -39,10 +39,10 @@ a per-session Database object: There are several limitations and difficulties with this approach: -1. Scoping funcarg resource creation is not straight forward, instead one must +1. Scoping funcarg resource creation is not straightforward, instead one must understand the intricate cached_setup() method mechanics. -2. parametrizing the "db" resource is not straight forward: +2. parametrizing the "db" resource is not straightforward: you need to apply a "parametrize" decorator or implement a :hook:`pytest_generate_tests` hook calling :py:func:`~pytest.Metafunc.parametrize` which @@ -55,7 +55,7 @@ There are several limitations and difficulties with this approach: at the same time, making it hard for them to affect global state of the application under test. -4. there is no way how you can make use of funcarg factories +4. there is no way you can make use of funcarg factories in xUnit setup methods. 5. A non-parametrized fixture function cannot use a parametrized diff --git a/doc/en/historical-notes.rst b/doc/en/historical-notes.rst index be67036d6ca..600aed4c17b 100644 --- a/doc/en/historical-notes.rst +++ b/doc/en/historical-notes.rst @@ -304,7 +304,7 @@ For more details see :ref:`breakpoints`. -Access of ``Module``, ``Function``, ``Class``, ``Instance``, ``File`` and ``Item`` through ``Node`` instances have long +Access of ``Module``, ``Function``, ``Class``, ``Instance``, ``File`` and ``Item`` through ``Node`` instances has long been documented as deprecated, but started to emit warnings from pytest ``3.9`` and onward. Users should just ``import pytest`` and access those objects using the ``pytest`` module. diff --git a/doc/en/how-to/assert.rst b/doc/en/how-to/assert.rst index 4ef2664b1d5..f8144a08109 100644 --- a/doc/en/how-to/assert.rst +++ b/doc/en/how-to/assert.rst @@ -218,7 +218,7 @@ To specify more details about the contained exception you can use :class:`pytest with pytest.RaisesGroup(pytest.RaisesExc(ValueError, match="foo")): raise ExceptionGroup("", (ValueError("foo"))) -They both supply a method :meth:`pytest.RaisesGroup.matches` :meth:`pytest.RaisesExc.matches` if you want to do matching outside of using it as a contextmanager. This can be helpful when checking ``.__context__`` or ``.__cause__``. +They both supply a method :meth:`pytest.RaisesGroup.matches` :meth:`pytest.RaisesExc.matches` if you want to do matching outside of using it as a :external+python:std:ref:`context manager `. This can be helpful when checking ``.__context__`` or ``.__cause__``. .. code-block:: python diff --git a/doc/en/how-to/cache.rst b/doc/en/how-to/cache.rst index 4271ab469dc..ca345916fc5 100644 --- a/doc/en/how-to/cache.rst +++ b/doc/en/how-to/cache.rst @@ -33,7 +33,7 @@ Other plugins may access the `config.cache`_ object to set/get Rerunning only failures or failures first ----------------------------------------------- -First, let's create 50 test invocation of which only 2 fail: +First, let's create 50 test invocations of which only 2 fail: .. code-block:: python diff --git a/doc/en/how-to/capture-stdout-stderr.rst b/doc/en/how-to/capture-stdout-stderr.rst index 8a6a42d4134..5de89bc0e3f 100644 --- a/doc/en/how-to/capture-stdout-stderr.rst +++ b/doc/en/how-to/capture-stdout-stderr.rst @@ -6,7 +6,7 @@ How to capture stdout/stderr output Pytest intercepts stdout and stderr as configured by the :option:`--capture=` command-line argument or by using fixtures. The ``--capture=`` flag configures -reporting, whereas the fixtures offer more granular control and allows +reporting, whereas the fixtures offer more granular control and allow inspection of output during testing. The reports can be customized with the :option:`-r` flag. @@ -23,7 +23,7 @@ fail on attempts to read from it because it is rarely desired to wait for interactive input when running automated tests. By default capturing is done by intercepting writes to low level -file descriptors. This allows to capture output from simple +file descriptors. This allows capturing output from simple print statements as well as output from a subprocess started by a test. diff --git a/doc/en/how-to/capture-warnings.rst b/doc/en/how-to/capture-warnings.rst index 46f53b3b462..b40d2afff2d 100644 --- a/doc/en/how-to/capture-warnings.rst +++ b/doc/en/how-to/capture-warnings.rst @@ -220,7 +220,7 @@ This plugin is enabled by default but can be disabled entirely in your configura [pytest] addopts = -p no:warnings -Or passing ``-p no:warnings`` in the command-line. This might be useful if your test suites handles warnings +Or passing ``-p no:warnings`` in the command-line. This might be useful if your test suite handles warnings using an external system. diff --git a/doc/en/how-to/doctest.rst b/doc/en/how-to/doctest.rst index 433b35b61ce..59d1033ed4f 100644 --- a/doc/en/how-to/doctest.rst +++ b/doc/en/how-to/doctest.rst @@ -185,7 +185,7 @@ Output format ------------- You can change the diff output format on failure for your doctests -by using one of standard doctest modules format in options +by using one of the standard doctest module's format options (see :data:`python:doctest.REPORT_UDIFF`, :data:`python:doctest.REPORT_CDIFF`, :data:`python:doctest.REPORT_NDIFF`, :data:`python:doctest.REPORT_ONLY_FIRST_FAILURE`): diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index 5c5a239e8d4..b37386525c6 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -471,7 +471,7 @@ marked ``smtp_connection`` fixture function. Running the test looks like this: ============================ 2 failed in 0.12s ============================= You see the two ``assert 0`` failing and more importantly you can also see -that the **exactly same** ``smtp_connection`` object was passed into the +that the **exact same** ``smtp_connection`` object was passed into the two test functions because pytest shows the incoming argument values in the traceback. As a result, the two test functions using ``smtp_connection`` run as quick as a single one because they reuse the same instance. @@ -1645,7 +1645,7 @@ Let's run the tests in verbose mode and with looking at the print-output: ============================ 8 passed in 0.12s ============================= You can see that the parametrized module-scoped ``modarg`` resource caused an -ordering of test execution that lead to the fewest possible "active" resources. +ordering of test execution that led to the fewest possible "active" resources. The finalizer for the ``mod1`` parametrized resource was executed before the ``mod2`` resource was setup. @@ -1654,7 +1654,7 @@ Then test_1 is executed with ``mod1``, then test_2 with ``mod1``, then test_1 with ``mod2`` and finally test_2 with ``mod2``. The ``otherarg`` parametrized resource (having function scope) was set up before -and teared down after every test that used it. +and torn down after every test that used it. .. _`usefixtures`: @@ -1762,8 +1762,8 @@ into a configuration file: Overriding fixtures on various levels ------------------------------------- -In relatively large test suite, you most likely need to ``override`` a ``global`` or ``root`` fixture with a ``locally`` -defined one, keeping the test code readable and maintainable. +In a relatively large test suite, you may want to *override* a fixture, to augment +or change its behavior inside of certain test modules or directories. Override a fixture on a folder (conftest) level ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1800,7 +1800,7 @@ Given the tests file structure is: def test_username(username): assert username == 'overridden-username' -As you can see, a fixture with the same name can be overridden for certain test folder level. +As you can see, a fixture with the same name can be overridden for a certain test directory level. Note that the ``base`` or ``super`` fixture can be accessed from the ``overriding`` fixture easily - used in the example above. @@ -1842,7 +1842,7 @@ Given the tests file structure is: def test_username(username): assert username == 'overridden-else-username' -In the example above, a fixture with the same name can be overridden for certain test module. +In the example above, a fixture with the same name can be overridden for a certain test module. Override a fixture with direct test parametrization diff --git a/doc/en/how-to/logging.rst b/doc/en/how-to/logging.rst index c0762e60928..25b4e9017e2 100644 --- a/doc/en/how-to/logging.rst +++ b/doc/en/how-to/logging.rst @@ -216,8 +216,8 @@ option names are: * :confval:`log_cli_date_format` If you need to record the whole test suite logging calls to a file, you can pass -:option:`--log-file=/path/to/log/file`. This log file is opened in write mode by default which -means that it will be overwritten at each run tests session. +:option:`--log-file=/path/to/log/file`. This log file is opened in write mode by default, which +means that it will be overwritten at each test session. If you'd like the file opened in append mode instead, then you can pass :option:`--log-file-mode=a`. Note that relative paths for the log-file location, whether passed on the CLI or declared in a config file, are always resolved relative to the current working directory. @@ -312,7 +312,7 @@ made in ``3.4`` after community feedback: * :ref:`Live Logs ` are now sent to ``sys.stdout`` and no longer require the :option:`-s` command-line option to work. -If you want to partially restore the logging behavior of version ``3.3``, you can add this options to your configuration +If you want to partially restore the logging behavior of version ``3.3``, you can add these options to your configuration file: .. tab:: toml @@ -331,4 +331,4 @@ file: log_cli = true log_level = NOTSET -More details about the discussion that lead to this changes can be read in :issue:`3013`. +More details about the discussion that led to these changes can be read in :issue:`3013`. diff --git a/doc/en/how-to/monkeypatch.rst b/doc/en/how-to/monkeypatch.rst index ad0c6e0e1c5..7442a85c10e 100644 --- a/doc/en/how-to/monkeypatch.rst +++ b/doc/en/how-to/monkeypatch.rst @@ -382,7 +382,7 @@ You can use the :py:meth:`monkeypatch.delitem ` to remove v def test_missing_user(monkeypatch): - # patch the DEFAULT_CONFIG t be missing the 'user' key + # patch the DEFAULT_CONFIG to be missing the 'user' key monkeypatch.delitem(app.DEFAULT_CONFIG, "user", raising=False) # Key error expected because a config is not passed, and the diff --git a/doc/en/how-to/output.rst b/doc/en/how-to/output.rst index d92b2131701..a594fcb3aab 100644 --- a/doc/en/how-to/output.rst +++ b/doc/en/how-to/output.rst @@ -771,7 +771,7 @@ record_testsuite_property .. versionadded:: 4.5 -If you want to add a properties node at the test-suite level, which may contains properties +If you want to add a properties node at the test-suite level, which may contain properties that are relevant to all tests, you can use the ``record_testsuite_property`` session-scoped fixture: The ``record_testsuite_property`` session-scoped fixture can be used to add properties relevant diff --git a/doc/en/how-to/skipping.rst b/doc/en/how-to/skipping.rst index 3b4d412843d..488f71b09f9 100644 --- a/doc/en/how-to/skipping.rst +++ b/doc/en/how-to/skipping.rst @@ -311,7 +311,7 @@ even executed, use the ``run`` parameter as ``False``: @pytest.mark.xfail(run=False) def test_function(): ... -This is specially useful for xfailing tests that are crashing the interpreter and should be +This is particularly useful for xfailing tests that are crashing the interpreter and should be investigated later. .. _`xfail strict tutorial`: diff --git a/doc/en/how-to/subtests.rst b/doc/en/how-to/subtests.rst index 5a08dbc4769..93b9d052afd 100644 --- a/doc/en/how-to/subtests.rst +++ b/doc/en/how-to/subtests.rst @@ -136,4 +136,4 @@ Subtests This feature was originally implemented as a separate plugin in `pytest-subtests `__, but since ``9.0`` has been merged into the core. - The core implementation should be compatible to the plugin implementation, except it does not contain custom command-line options to control subtest output. + The core implementation should be compatible with the plugin implementation, except it does not contain custom command-line options to control subtest output. diff --git a/doc/en/how-to/writing_hook_functions.rst b/doc/en/how-to/writing_hook_functions.rst index cd18301ce84..d5d6d2ae4f7 100644 --- a/doc/en/how-to/writing_hook_functions.rst +++ b/doc/en/how-to/writing_hook_functions.rst @@ -94,7 +94,7 @@ around the actual hook implementations, in which case it can return the result value of the ``yield``. The simplest (though useless) hook wrapper is ``return (yield)``. -In other cases, the wrapper wants the adjust or adapt the result, in which case +In other cases, the wrapper wants to adjust or adapt the result, in which case it can return a new value. If the result of the underlying hook is a mutable object, the wrapper may modify that result, but it's probably better to avoid it. diff --git a/doc/en/how-to/writing_plugins.rst b/doc/en/how-to/writing_plugins.rst index 6b7e2a7e496..56043a14f97 100644 --- a/doc/en/how-to/writing_plugins.rst +++ b/doc/en/how-to/writing_plugins.rst @@ -48,7 +48,7 @@ Plugin discovery order at tool startup 5. by loading all plugins specified through the :envvar:`PYTEST_PLUGINS` environment variable. -6. by loading all "initial ":file:`conftest.py` files: +6. by loading all "initial" :file:`conftest.py` files: - determine the test paths: specified on the command line, otherwise in :confval:`testpaths` if defined and running from the rootdir, otherwise the diff --git a/doc/en/index.rst b/doc/en/index.rst index 77b502e3e41..fa05b3a0c48 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -2,7 +2,7 @@ .. sidebar:: **Next Open Trainings and Events** - - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training), **March 3th -- 5th 2026**, Remote + - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training), **March 3rd -- 5th 2026**, Remote Also see :doc:`previous talks and blogposts ` diff --git a/doc/en/reference/customize.rst b/doc/en/reference/customize.rst index b2e7d64cc26..db454721dfc 100644 --- a/doc/en/reference/customize.rst +++ b/doc/en/reference/customize.rst @@ -160,7 +160,7 @@ the command line arguments (specified test files, paths) and on the existence of configuration files. The determined ``rootdir`` and ``configfile`` are printed as part of the pytest header during startup. -Here's a summary what ``pytest`` uses ``rootdir`` for: +Here's a summary of what ``pytest`` uses ``rootdir`` for: * Construct *nodeids* during collection; each test is assigned a unique *nodeid* which is rooted at the ``rootdir`` and takes into account @@ -204,7 +204,7 @@ Here is the algorithm which finds the rootdir from ``args``: directory. This allows the use of pytest in structures that are not part of a package and don't have any particular configuration file. -If no ``args`` are given, pytest collects test below the current working +If no ``args`` are given, pytest collects tests below the current working directory and also starts determining the ``rootdir`` from there. Files will only be matched for configuration if: @@ -274,7 +274,7 @@ check for configuration files as follows: ``pytest --log-output ../../test.log args``. Then ``args`` is mandatory, otherwise pytest uses the folder of test.log for rootdir determination (see also :issue:`1435`). - A dot ``.`` for referencing to the current working directory is also + A dot ``.`` for referencing the current working directory is also possible. diff --git a/doc/en/reference/exit-codes.rst b/doc/en/reference/exit-codes.rst index b695ca3702e..49aaca19121 100644 --- a/doc/en/reference/exit-codes.rst +++ b/doc/en/reference/exit-codes.rst @@ -20,7 +20,7 @@ They are represented by the :class:`pytest.ExitCode` enum. The exit codes being .. note:: - If you would like to customize the exit code in some scenarios, specially when + If you would like to customize the exit code in some scenarios, specifically when no tests are collected, consider using the `pytest-custom_exit_code `__ plugin. diff --git a/doc/en/reference/fixtures.rst b/doc/en/reference/fixtures.rst index b0fa8660f9b..c4a8d01ff0e 100644 --- a/doc/en/reference/fixtures.rst +++ b/doc/en/reference/fixtures.rst @@ -277,10 +277,10 @@ the test's search for fixtures would look like: pytest will only search for ``a_fix`` and ``b_fix`` in the plugins after searching for them first in the scopes inside ``tests/``. -.. note: +.. note:: pytest can tell you what fixtures are available for a given test if you call - ``pytests`` along with the test's name (or the scope it's in), and provide + ``pytest`` along with the test's name (or the scope it's in), and provide the :option:`--fixtures` flag, e.g. ``pytest --fixtures test_something.py`` (fixtures with names that start with ``_`` will only be shown if you also provide the :option:`-v` flag). @@ -354,7 +354,7 @@ an order of operations for a given test. If there's any ambiguity, and the order of operations can be interpreted more than one way, you should assume pytest could go with any one of those interpretations at any point. -For example, if ``d`` didn't request ``c``, i.e.the graph would look like this: +For example, if ``d`` didn't request ``c``, i.e. the graph would look like this: .. image:: /example/fixtures/test_fixtures_order_dependencies_unclear.* :align: center @@ -448,10 +448,10 @@ for the tests inside ``TestClassWithoutAutouse``, since they can reference can't see ``c3``. -.. note: +.. note:: pytest can tell you what order the fixtures will execute in for a given test - if you call ``pytests`` along with the test's name (or the scope it's in), + if you call ``pytest`` along with the test's name (or the scope it's in), and provide the :option:`--setup-plan` flag, e.g. ``pytest --setup-plan test_something.py`` (fixtures with names that start with ``_`` will only be shown if you also provide the :option:`-v` flag). diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index b609dc9a810..fdeb266c544 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1179,11 +1179,11 @@ Environment variables that can be used to change pytest's behavior. .. envvar:: CI -When set to a non-empty value, pytest acknowledges that is running in a CI process. See also :ref:`ci-pipelines`. +When set to a non-empty value, pytest acknowledges that it is running in a CI process. See also :ref:`ci-pipelines`. .. envvar:: BUILD_NUMBER -When set to a non-empty value, pytest acknowledges that is running in a CI process. Alternative to :envvar:`CI`. See also :ref:`ci-pipelines`. +When set to a non-empty value, pytest acknowledges that it is running in a CI process. Alternative to :envvar:`CI`. See also :ref:`ci-pipelines`. .. envvar:: PYTEST_ADDOPTS @@ -1315,7 +1315,7 @@ Configuration Options Here is a list of builtin configuration options that may be written in a ``pytest.ini`` (or ``.pytest.ini``), ``pyproject.toml``, ``tox.ini``, or ``setup.cfg`` file, usually located at the root of your repository. -To see each file format in details, see :ref:`config file formats`. +To see each file format in detail, see :ref:`config file formats`. .. warning:: Usage of ``setup.cfg`` is not recommended except for very simple use cases. ``.cfg`` @@ -1586,7 +1586,6 @@ passed multiple times. The expected format is ``name=value``. For example:: faulthandler_timeout = 5 For more information please refer to :ref:`faulthandler`. - For more information please refer to :ref:`faulthandler`. .. confval:: filterwarnings @@ -3175,7 +3174,7 @@ See :ref:`logging` for a guide on using these flags. .. option:: --log-file=PATH - Path to a file when logging will be written to. + Path to a file logging will be written to. .. option:: --log-file-mode diff --git a/doc/en/sponsor.rst b/doc/en/sponsor.rst index 8362a7f0a3a..6ad722be94c 100644 --- a/doc/en/sponsor.rst +++ b/doc/en/sponsor.rst @@ -2,7 +2,7 @@ Sponsor ======= pytest is maintained by a team of volunteers from all around the world in their free time. While -we work on pytest because we love the project and use it daily at our daily jobs, monetary +we work on pytest because we love the project and use it daily in our jobs, monetary compensation when possible is welcome to justify time away from friends, family and personal time. Money is also used to fund local sprints, merchandising (stickers to distribute in conferences for example) @@ -12,7 +12,7 @@ OpenCollective -------------- `Open Collective`_ is an online funding platform for open and transparent communities. -It provide tools to raise money and share your finances in full transparency. +It provides tools to raise money and share your finances in full transparency. It is the platform of choice for individuals and companies that want to make one-time or monthly donations directly to the project. From 1606ded074859710497d93b18c7d40f7832fb712 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Thu, 12 Feb 2026 23:16:06 +0000 Subject: [PATCH 46/74] doc: indent envvar directive bodies in reference.rst (#14183) (#14187) Indent the body text of all 14 ``.. envvar::`` entries with 3 spaces, matching the ``.. confval::`` convention used in the same file. This was the only section with unindented directive bodies. (cherry picked from commit 3740cb962027ed73460c04568b409ef8c52af99e) Co-authored-by: Ronald Eddy Jr --- doc/en/reference/reference.rst | 58 +++++++++++++++++----------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index fdeb266c544..27d3f5e721a 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1179,77 +1179,77 @@ Environment variables that can be used to change pytest's behavior. .. envvar:: CI -When set to a non-empty value, pytest acknowledges that it is running in a CI process. See also :ref:`ci-pipelines`. + When set to a non-empty value, pytest acknowledges that it is running in a CI process. See also :ref:`ci-pipelines`. .. envvar:: BUILD_NUMBER -When set to a non-empty value, pytest acknowledges that it is running in a CI process. Alternative to :envvar:`CI`. See also :ref:`ci-pipelines`. + When set to a non-empty value, pytest acknowledges that it is running in a CI process. Alternative to :envvar:`CI`. See also :ref:`ci-pipelines`. .. envvar:: PYTEST_ADDOPTS -This contains a command-line (parsed by the py:mod:`shlex` module) that will be **prepended** to the command line given -by the user, see :ref:`adding default options` for more information. + This contains a command-line (parsed by the py:mod:`shlex` module) that will be **prepended** to the command line given + by the user, see :ref:`adding default options` for more information. .. envvar:: PYTEST_VERSION -This environment variable is defined at the start of the pytest session and is undefined afterwards. -It contains the value of ``pytest.__version__``, and among other things can be used to easily check if a code is running from within a pytest run. + This environment variable is defined at the start of the pytest session and is undefined afterwards. + It contains the value of ``pytest.__version__``, and among other things can be used to easily check if a code is running from within a pytest run. .. envvar:: PYTEST_CURRENT_TEST -This is not meant to be set by users, but is set by pytest internally with the name of the current test so other -processes can inspect it, see :ref:`pytest current test env` for more information. + This is not meant to be set by users, but is set by pytest internally with the name of the current test so other + processes can inspect it, see :ref:`pytest current test env` for more information. .. envvar:: PYTEST_DEBUG -When set, pytest will print tracing and debug information. + When set, pytest will print tracing and debug information. .. envvar:: PYTEST_DEBUG_TEMPROOT -Root for temporary directories produced by fixtures like :fixture:`tmp_path` -as discussed in :ref:`temporary directory location and retention`. + Root for temporary directories produced by fixtures like :fixture:`tmp_path` + as discussed in :ref:`temporary directory location and retention`. .. envvar:: PYTEST_DISABLE_PLUGIN_AUTOLOAD -When set, disables plugin auto-loading through :std:doc:`entry point packaging -metadata `. Only plugins -explicitly specified in :envvar:`PYTEST_PLUGINS` or with :option:`-p` will be loaded. -See also :ref:`--disable-plugin-autoload `. + When set, disables plugin auto-loading through :std:doc:`entry point packaging + metadata `. Only plugins + explicitly specified in :envvar:`PYTEST_PLUGINS` or with :option:`-p` will be loaded. + See also :ref:`--disable-plugin-autoload `. .. envvar:: PYTEST_PLUGINS -Contains comma-separated list of modules that should be loaded as plugins: + Contains comma-separated list of modules that should be loaded as plugins: -.. code-block:: bash + .. code-block:: bash - export PYTEST_PLUGINS=mymodule.plugin,xdist + export PYTEST_PLUGINS=mymodule.plugin,xdist -See also :option:`-p`. + See also :option:`-p`. .. envvar:: PYTEST_THEME -Sets a `pygment style `_ to use for the code output. + Sets a `pygment style `_ to use for the code output. .. envvar:: PYTEST_THEME_MODE -Sets the :envvar:`PYTEST_THEME` to be either *dark* or *light*. + Sets the :envvar:`PYTEST_THEME` to be either *dark* or *light*. .. envvar:: PY_COLORS -When set to ``1``, pytest will use color in terminal output. -When set to ``0``, pytest will not use color. -``PY_COLORS`` takes precedence over ``NO_COLOR`` and ``FORCE_COLOR``. + When set to ``1``, pytest will use color in terminal output. + When set to ``0``, pytest will not use color. + ``PY_COLORS`` takes precedence over ``NO_COLOR`` and ``FORCE_COLOR``. .. envvar:: NO_COLOR -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``. -See `no-color.org `__ for other libraries supporting this community standard. + 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``. + See `no-color.org `__ for other libraries supporting this community standard. .. envvar:: FORCE_COLOR -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``. + 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``. Exceptions ---------- From c737e3b7e8d679c786a5d0d2b064c6db566eb990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BA=F0=9F=87=A6=20Sviatoslav=20Sydorenko=20=28?= =?UTF-8?q?=D0=A1=D0=B2=D1=8F=D1=82=D0=BE=D1=81=D0=BB=D0=B0=D0=B2=20=D0=A1?= =?UTF-8?q?=D0=B8=D0=B4=D0=BE=D1=80=D0=B5=D0=BD=D0=BA=D0=BE=29?= Date: Fri, 13 Feb 2026 00:25:52 +0100 Subject: [PATCH 47/74] Merge pull request #14184 from him2him2/doc-src-layout-link doc: add seealso link to src-layout vs flat-layout discussion (cherry picked from commit 3c37b551e71c8b18c5323dac8a27d248bb98a5a9) --- doc/en/explanation/goodpractices.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/en/explanation/goodpractices.rst b/doc/en/explanation/goodpractices.rst index cb894f82e3c..52474d148c6 100644 --- a/doc/en/explanation/goodpractices.rst +++ b/doc/en/explanation/goodpractices.rst @@ -150,6 +150,11 @@ which are better explained in this excellent `blog post`_ by Ionel Cristian Măr See :ref:`pytest vs python -m pytest` for more information about the difference between calling ``pytest`` and ``python -m pytest``. +.. seealso:: + + :doc:`packaging:discussions/src-layout-vs-flat-layout` + The Python Packaging User Guide discusses the trade-offs between the ``src`` layout and ``flat`` layout. + Tests as part of application code ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 1cb94d2832254c1d412ab69c9947eb303199d5b9 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sat, 14 Feb 2026 12:45:22 -0300 Subject: [PATCH 48/74] doc: fixed typo in file name format (#14191) (#14192) (cherry picked from commit 2f09ddc84ea6a7ccd56f19b0b998c8d2c51a4652) Co-authored-by: Lily Wu <96460328+lwu1822@users.noreply.github.com> --- doc/en/how-to/usage.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/how-to/usage.rst b/doc/en/how-to/usage.rst index 94e6d94d834..35b07bfe8c1 100644 --- a/doc/en/how-to/usage.rst +++ b/doc/en/how-to/usage.rst @@ -7,7 +7,7 @@ How to invoke pytest .. seealso:: :ref:`Complete pytest command-line flags reference ` In general, pytest is invoked with the command ``pytest`` (see below for :ref:`other ways to invoke pytest -`). This will execute all tests in all files whose names follow the form ``test_*.py`` or ``\*_test.py`` +`). This will execute all tests in all files whose names follow the form ``test_*.py`` or ``*_test.py`` in the current directory and its subdirectories. More generally, pytest follows :ref:`standard test discovery rules `. From 60fb59d341a6373e632849de0a35b90aa85f0d61 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sat, 14 Feb 2026 14:02:08 -0300 Subject: [PATCH 49/74] Fix: assertrepr_compare respects dict insertion order (#14050) (#14193) Fixes #13503 Closes #14066 (cherry picked from commit 966edc9d517cd092104028796b684fb1119a7c73) Co-authored-by: DavidAG --- changelog/14050.bugfix.rst | 1 + src/_pytest/_io/pprint.py | 4 ++-- src/_pytest/_io/saferepr.py | 25 ++++++++++++++++++++ src/_pytest/pytester_assertions.py | 4 ++-- testing/io/test_saferepr.py | 37 ++++++++++++++++++++++++++++++ testing/test_assertion.py | 31 +++++++++++++++++++++++++ 6 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 changelog/14050.bugfix.rst diff --git a/changelog/14050.bugfix.rst b/changelog/14050.bugfix.rst new file mode 100644 index 00000000000..451b248576f --- /dev/null +++ b/changelog/14050.bugfix.rst @@ -0,0 +1 @@ +Display dictionary differences in assertion failures using the original key insertion order instead of sorted order. diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index 28f06909206..ec41b449ddf 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -162,7 +162,7 @@ def _pprint_dict( ) -> None: write = stream.write write("{") - items = sorted(object.items(), key=_safe_tuple) + items = object.items() self._format_dict_items(items, stream, indent, allowance, context, level) write("}") @@ -608,7 +608,7 @@ def _safe_repr( components: list[str] = [] append = components.append level += 1 - for k, v in sorted(object.items(), key=_safe_tuple): + for k, v in object.items(): krepr = self._safe_repr(k, context, maxlevels, level) vrepr = self._safe_repr(v, context, maxlevels, level) append(f"{krepr}: {vrepr}") diff --git a/src/_pytest/_io/saferepr.py b/src/_pytest/_io/saferepr.py index cee70e332f9..3f5c956d9cf 100644 --- a/src/_pytest/_io/saferepr.py +++ b/src/_pytest/_io/saferepr.py @@ -1,5 +1,6 @@ from __future__ import annotations +from itertools import islice import pprint import reprlib @@ -77,8 +78,32 @@ def repr_instance(self, x: object, level: int) -> str: s = _format_repr_exception(exc, x) if self.maxsize is not None: s = _ellipsize(s, self.maxsize) + return s + def repr_dict(self, x: dict[object, object], level: int) -> str: + """Represent a dict while preserving its insertion order. + + Differs from ``reprlib.Repr.repr_dict`` by iterating directly over ``x`` + rather than using the stdlib's sorting helper. + """ + fillvalue = "..." + n = len(x) + if n == 0: + return "{}" + if level <= 0: + return "{" + fillvalue + "}" + newlevel = level - 1 + repr1 = self.repr1 + pieces = [] + for key in islice(x, self.maxdict): + keyrepr = repr1(key, newlevel) + valrepr = repr1(x[key], newlevel) + pieces.append(f"{keyrepr}: {valrepr}") + if n > self.maxdict: + pieces.append(fillvalue) + return "{" + ", ".join(pieces) + "}" + def safeformat(obj: object) -> str: """Return a pretty printed string for the given object. diff --git a/src/_pytest/pytester_assertions.py b/src/_pytest/pytester_assertions.py index 915cc8a10ff..b8d8a195241 100644 --- a/src/_pytest/pytester_assertions.py +++ b/src/_pytest/pytester_assertions.py @@ -26,11 +26,11 @@ def assertoutcome( realpassed, realskipped, realfailed = outcomes obtained = { + "failed": len(realfailed), "passed": len(realpassed), "skipped": len(realskipped), - "failed": len(realfailed), } - expected = {"passed": passed, "skipped": skipped, "failed": failed} + expected = {"failed": failed, "passed": passed, "skipped": skipped} assert obtained == expected, outcomes diff --git a/testing/io/test_saferepr.py b/testing/io/test_saferepr.py index 075d40cdf44..2e3dd55b81f 100644 --- a/testing/io/test_saferepr.py +++ b/testing/io/test_saferepr.py @@ -2,6 +2,7 @@ from __future__ import annotations from _pytest._io.saferepr import DEFAULT_REPR_MAX_SIZE +from _pytest._io.saferepr import SafeRepr from _pytest._io.saferepr import saferepr from _pytest._io.saferepr import saferepr_unlimited import pytest @@ -192,3 +193,39 @@ def __repr__(self): assert saferepr_unlimited(A()).startswith( "<[ValueError(42) raised in repr()] A object at 0x" ) + + +def test_saferepr_dict_preserves_insertion_order() -> None: + d = { + "b": 2, + "a": 1, + "d": 4, + "e": 5, + "c": 3, + } + s = SafeRepr(maxsize=None) + s.maxdict = 10 + assert s.repr(d) == "{'b': 2, 'a': 1, 'd': 4, 'e': 5, 'c': 3}" + + +def test_saferepr_dict_truncation_preserves_insertion_order() -> None: + d = { + "b": 2, + "a": 1, + "d": 4, + "e": 5, + "c": 3, + } + s = SafeRepr(maxsize=None) + s.maxdict = 1 + assert s.repr(d) == "{'b': 2, ...}" + + +def test_saferepr_dict_fillvalue_when_level_is_zero() -> None: + s = SafeRepr(maxsize=None) + assert s.repr_dict({"a": 1}, level=0) == "{...}" + + +def test_saferepr_dict_empty() -> None: + s = SafeRepr(maxsize=None) + assert s.repr_dict({}, level=1) == "{}" diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 5179b13b0e9..12351a48a7f 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -2198,3 +2198,34 @@ def test_vvv(): ] ) result.stdout.no_fnmatch_line(expected_non_vvv_arg_line) + + +def test_dict_extra_items_preserve_insertion_order(pytester: Pytester) -> None: + """Assertion output of dict diff shows keys in insertion order (#13503).""" + pytester.makepyfile( + test_order=""" + def test_order(): + a = { + "b": 2, + "a": 1, + "d": 4, + "e": 5, + "c": 3, + } + assert a == {} + """ + ) + + result = pytester.runpytest("-vv") + result.stdout.fnmatch_lines( + [ + "*Left contains 5 more items:*", + "*Full diff:", + "* + *'b': 2,", + "* + *'a': 1,", + "* + *'d': 4,", + "* + *'e': 5,", + "* + *'c': 3,", + "test_order.py:*: AssertionError", + ] + ) From 3065de713adfb3f38db16056fa2e702824d89978 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Mon, 16 Feb 2026 15:13:03 +0000 Subject: [PATCH 50/74] subtests: fix inconcistent handling of non-string messages (#14196) (#14199) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #14195 --------- (cherry picked from commit 8950ca3bc0988647dfc35b02f854347a1435bd36) Co-authored-by: Randy Döring <30527984+radoering@users.noreply.github.com> Co-authored-by: Bruno Oliveira --- AUTHORS | 1 + changelog/14195.bugfix.rst | 1 + src/_pytest/unittest.py | 6 +++- testing/test_subtests.py | 57 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 changelog/14195.bugfix.rst diff --git a/AUTHORS b/AUTHORS index fa6bc58c52f..e8140292aa4 100644 --- a/AUTHORS +++ b/AUTHORS @@ -382,6 +382,7 @@ Ralf Schmitt Ralph Giles Ram Rachum Ran Benita +Randy Döring Raphael Castaneda Raphael Pierzina Rafal Semik diff --git a/changelog/14195.bugfix.rst b/changelog/14195.bugfix.rst new file mode 100644 index 00000000000..29ae149dd98 --- /dev/null +++ b/changelog/14195.bugfix.rst @@ -0,0 +1 @@ +Fixed an issue where non-string messages passed to `unittest.TestCase.subTest()` were not printed. diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 23b92724f5d..31be8847821 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -409,6 +409,10 @@ def addSubTest( | tuple[type[BaseException], BaseException, TracebackType] | None, ) -> None: + # Importing this private symbol locally in case this symbol is renamed/removed in the future; importing + # it globally would break pytest entirely, importing it locally only will break unittests using `addSubTest`. + from unittest.case import _subtest_msg_sentinel # type: ignore[attr-defined] + exception_info: ExceptionInfo[BaseException] | None match exc_info: case tuple(): @@ -427,7 +431,7 @@ def addSubTest( when="call", _ispytest=True, ) - msg = test._message if isinstance(test._message, str) else None # type: ignore[attr-defined] + msg = None if test._message is _subtest_msg_sentinel else str(test._message) # type: ignore[attr-defined] report = self.ihook.pytest_runtest_makereport(item=self, call=call_info) sub_report = SubtestReport._new( report, diff --git a/testing/test_subtests.py b/testing/test_subtests.py index 6849df53622..06de9f009d8 100644 --- a/testing/test_subtests.py +++ b/testing/test_subtests.py @@ -370,6 +370,36 @@ def test_foo(subtests): ) +def test_msg_not_a_string( + pytester: pytest.Pytester, monkeypatch: pytest.MonkeyPatch +) -> None: + """ + Using a non-string in subtests.test() should still show it in the terminal (#14195). + + Note: this was not a problem originally with the subtests fixture, only with TestCase.subTest; this test + was added for symmetry. + """ + monkeypatch.setenv("COLUMNS", "120") + pytester.makepyfile( + """ + def test_int_msg(subtests): + with subtests.test(42): + assert False, "subtest failure" + + def test_no_msg(subtests): + with subtests.test(): + assert False, "subtest failure" + """ + ) + result = pytester.runpytest() + result.stdout.fnmatch_lines( + [ + "SUBFAILED[[]42[]] test_msg_not_a_string.py::test_int_msg - AssertionError: subtest failure", + "SUBFAILED() test_msg_not_a_string.py::test_no_msg - AssertionError: subtest failure", + ] + ) + + @pytest.mark.parametrize("flag", ["--last-failed", "--stepwise"]) def test_subtests_last_failed_step_wise(pytester: pytest.Pytester, flag: str) -> None: """Check that --last-failed and --step-wise correctly rerun tests with failed subtests.""" @@ -619,6 +649,33 @@ def test_foo(self): "SUBSKIPPED[[]subtest 1[]] [[]1[]] *.py:*: skip subtest 1" ) + def test_msg_not_a_string( + self, pytester: pytest.Pytester, monkeypatch: pytest.MonkeyPatch + ) -> None: + """Using a non-string in TestCase.subTest should still show it in the terminal (#14195).""" + monkeypatch.setenv("COLUMNS", "120") + pytester.makepyfile( + """ + from unittest import TestCase + + class T(TestCase): + def test_int_msg(self): + with self.subTest(42): + assert False, "subtest failure" + + def test_no_msg(self): + with self.subTest(): + assert False, "subtest failure" + """ + ) + result = pytester.runpytest() + result.stdout.fnmatch_lines( + [ + "SUBFAILED[[]42[]] test_msg_not_a_string.py::T::test_int_msg - AssertionError: subtest failure", + "SUBFAILED() test_msg_not_a_string.py::T::test_no_msg - AssertionError: subtest failure", + ] + ) + class TestCapture: def create_file(self, pytester: pytest.Pytester) -> None: From 45e3fbfeb73d242fe876a3164e53ced7b1ee8ae5 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Tue, 24 Feb 2026 10:49:02 +0000 Subject: [PATCH 51/74] doc: fix removed pytest.config reference in historical-notes (#14216) (#14232) pytest.config was removed in pytest 5.0, but the documentation on 'Conditions as strings instead of booleans' still showed it as the modern equivalent of string-based skipif conditions. Replace the broken example with the current recommended approach using request.config (via an autouse fixture), and add a note pointing to the removal notice in the deprecations page. Fixes #12377 (cherry picked from commit 9fd1eebd8af715b58832412bb8398d394ab67666) Co-authored-by: Maxime Grenu <69890511+cluster2600@users.noreply.github.com> --- doc/en/historical-notes.rst | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/doc/en/historical-notes.rst b/doc/en/historical-notes.rst index 600aed4c17b..d93c7b94793 100644 --- a/doc/en/historical-notes.rst +++ b/doc/en/historical-notes.rst @@ -263,20 +263,24 @@ configuration value which you might have added: @pytest.mark.skipif("not config.getvalue('db')") def test_function(): ... -The equivalent with "boolean conditions" is: +The equivalent with "boolean conditions" using ``request.config`` is: .. code-block:: python - @pytest.mark.skipif(not pytest.config.getvalue("db"), reason="--db was not specified") + @pytest.fixture(autouse=True) + def skip_if_no_db(request): + if not request.config.getoption("--db", default=False): + pytest.skip("--db was not specified") + + def test_function(): pass .. note:: - You cannot use ``pytest.config.getvalue()`` in code - imported before pytest's argument parsing takes place. For example, - ``conftest.py`` files are imported before command line parsing and thus - ``config.getvalue()`` will not execute correctly. + ``pytest.config`` was removed in pytest 5.0. Use ``request.config`` + (via the ``request`` fixture) or the ``pytestconfig`` fixture instead. + See :ref:`pytest.config global deprecated` for details. ``pytest.set_trace()`` ---------------------- From 32a95ce020ecef84df1bc17337053b23a539d173 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sun, 1 Mar 2026 09:57:02 -0300 Subject: [PATCH 52/74] Fix CI docs example file names (#14240) (#14244) (cherry picked from commit 3000e22ad966943122efa4b3d2eaff796006f756) Co-authored-by: Aditya Giri <74224708+adityagiri3600@users.noreply.github.com> --- doc/en/explanation/ci.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/explanation/ci.rst b/doc/en/explanation/ci.rst index 16f55be81c0..1c03f840b43 100644 --- a/doc/en/explanation/ci.rst +++ b/doc/en/explanation/ci.rst @@ -50,7 +50,7 @@ Running this locally, without any extra options, will output: $ pytest test_ci.py ... ========================= short test summary info ========================== - FAILED test_backends.py::test_db_initialized[d2] - Failed: deliberately f... + FAILED test_ci.py::test_db_initialized - Failed: deliberately f... *(Note the truncated text)* @@ -63,7 +63,7 @@ While running this on CI will output: $ pytest test_ci.py ... ========================= short test summary info ========================== - FAILED test_backends.py::test_db_initialized[d2] - Failed: deliberately failing + FAILED test_ci.py::test_db_initialized - Failed: deliberately failing for demo purpose, Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras facilisis, massa in suscipit dignissim, mauris lacus molestie nisi, quis varius metus nulla ut ipsum. From c89013ab972d031a5feca0759e80e613d7e683d1 Mon Sep 17 00:00:00 2001 From: Dr Alex Mitre Date: Fri, 6 Mar 2026 07:48:12 -0600 Subject: [PATCH 53/74] Update customize.rst with pytest minversion note (#14258) Add note about maintaining minversion for older pytest versions. Closes #7730 (cherry picked from commit d6fa26c62873ea648272b337f2dc45d095394745) --- doc/en/reference/customize.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/en/reference/customize.rst b/doc/en/reference/customize.rst index db454721dfc..8903ceadf68 100644 --- a/doc/en/reference/customize.rst +++ b/doc/en/reference/customize.rst @@ -103,6 +103,10 @@ pyproject.toml "integration", ] + For projects that still run pytest versions older than 6.0, keep + ``minversion`` in ``pytest.ini`` or ``setup.cfg`` too. Those versions + do not read ``pyproject.toml``. + tox.ini ~~~~~~~ From f1a74fe09e30c5b6ad59b26ab27b9127745e6aa0 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Fri, 6 Mar 2026 13:59:59 +0000 Subject: [PATCH 54/74] TOML integer log levels must be quoted: Updating reference documentation (#14255) (#14264) Fixes #14253 (cherry picked from commit 2755310d51bf6f9a307fcb89b4f1712fbc8f7dc5) Co-authored-by: Samuel Newbold --- changelog/14255.doc.rst | 1 + doc/en/reference/reference.rst | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 changelog/14255.doc.rst diff --git a/changelog/14255.doc.rst b/changelog/14255.doc.rst new file mode 100644 index 00000000000..b96d2c2a1b9 --- /dev/null +++ b/changelog/14255.doc.rst @@ -0,0 +1 @@ +TOML integer log levels must be quoted: Updating reference documentation. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 27d3f5e721a..3760add53cf 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1836,7 +1836,8 @@ passed multiple times. The expected format is ``name=value``. For example:: Sets the minimum log message level that should be captured for live logging. The integer value or - the names of the levels can be used. + the names of the levels can be used. Note in TOML the integer must be quoted, as there is no support + for config parameters of mixed type. .. tab:: toml @@ -1844,6 +1845,7 @@ passed multiple times. The expected format is ``name=value``. For example:: [pytest] log_cli_level = "INFO" + log_cli_level = "10" .. tab:: ini @@ -1851,6 +1853,7 @@ passed multiple times. The expected format is ``name=value``. For example:: [pytest] log_cli_level = INFO + log_cli_level = 10 For more information, see :ref:`live_logs`. @@ -1951,7 +1954,8 @@ passed multiple times. The expected format is ``name=value``. For example:: Sets the minimum log message level that should be captured for the logging file. The integer value or - the names of the levels can be used. + the names of the levels can be used. Note in TOML the integer must be quoted, as there is no support + for config parameters of mixed type. .. tab:: toml @@ -1959,6 +1963,7 @@ passed multiple times. The expected format is ``name=value``. For example:: [pytest] log_file_level = "INFO" + log_cli_level = "10" .. tab:: ini @@ -1966,6 +1971,7 @@ passed multiple times. The expected format is ``name=value``. For example:: [pytest] log_file_level = INFO + log_cli_level = 10 For more information, see :ref:`logging`. @@ -2020,7 +2026,8 @@ passed multiple times. The expected format is ``name=value``. For example:: Sets the minimum log message level that should be captured for logging capture. The integer value or - the names of the levels can be used. + the names of the levels can be used. Note in TOML the integer must be quoted, as there is no support + for config parameters of mixed type. .. tab:: toml @@ -2028,6 +2035,7 @@ passed multiple times. The expected format is ``name=value``. For example:: [pytest] log_level = "INFO" + log_cli_level = "10" .. tab:: ini @@ -2035,6 +2043,7 @@ passed multiple times. The expected format is ``name=value``. For example:: [pytest] log_level = INFO + log_cli_level = 10 For more information, see :ref:`logging`. From 8ed11b2a330444abb2ebefbec103c630058489c7 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:15:16 +0000 Subject: [PATCH 55/74] Update documentation for reportinfo() return values (#14256) (#14265) Clarify the return value of reportinfo() in verbose mode. (cherry picked from commit 8638c7d3f214c0e0e2f8578280cd6f8765a5771c) Co-authored-by: Dr Alex Mitre --- doc/en/example/nonpython.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/en/example/nonpython.rst b/doc/en/example/nonpython.rst index bb879fb51ab..54391d72fd4 100644 --- a/doc/en/example/nonpython.rst +++ b/doc/en/example/nonpython.rst @@ -58,7 +58,12 @@ your own domain specific testing language this way. will be reported as a (red) string. ``reportinfo()`` is used for representing the test location and is also -consulted when reporting in ``verbose`` mode: +consulted when reporting in ``verbose`` mode. It should return a tuple +``(path, lineno, description)``, where: + +* ``path`` is the path shown in reports (usually ``self.path`` or ``self.fspath``). +* ``lineno`` is a zero-based line number, or ``0`` when no specific line applies. +* ``description`` is a short label shown for the collected item: .. code-block:: pytest From c34bfa3b7acb65b594707c714f1d8461b0304eed Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:15:44 +0000 Subject: [PATCH 56/74] Add explanation for string context diffs (#14257) (#14266) Clarify context diff output for string comparisons. (cherry picked from commit 38e9af8b1a59aeab0490e71c2d9fd4c277560ceb) Co-authored-by: Dr Alex Mitre --- doc/en/how-to/assert.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/en/how-to/assert.rst b/doc/en/how-to/assert.rst index f8144a08109..006cf475b02 100644 --- a/doc/en/how-to/assert.rst +++ b/doc/en/how-to/assert.rst @@ -436,6 +436,10 @@ Special comparisons are done for a number of cases: * comparing long sequences: first failing indices * comparing dicts: different entries +In string context diffs, lines prefixed with ``-`` come from the left-hand side +of ``assert left == right``, while lines prefixed with ``+`` come from the +right-hand side. + See the :ref:`reporting demo ` for many more examples. Defining your own explanation for failed assertions From 37da870d37e3a2f5177cae075c7b9ae279432bf8 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Fri, 6 Mar 2026 12:57:12 -0300 Subject: [PATCH 57/74] Merge pull request #14259 from mitre88/patch-4 (#14268) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Docs: clarify multiple arguments in pytest.mark.filterwarnings (cherry picked from commit ced0a8d4a4317f4cb24b4ffb8138deb319dac212) Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) --- doc/en/how-to/capture-warnings.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/en/how-to/capture-warnings.rst b/doc/en/how-to/capture-warnings.rst index b40d2afff2d..b0ff6a74892 100644 --- a/doc/en/how-to/capture-warnings.rst +++ b/doc/en/how-to/capture-warnings.rst @@ -160,6 +160,15 @@ You can specify multiple filters with separate decorators: def test_one(): assert api_v1() == 1 +You can also pass multiple filters to a single mark by providing multiple arguments: + +.. code-block:: python + + # Later arguments take precedence, matching warnings.filterwarnings behavior. + @pytest.mark.filterwarnings("error", "ignore:api v1") + def test_one(): + assert api_v1() == 1 + .. important:: Regarding decorator order and filter precedence: From 7ee58acc8777c31ac6cf388d01addf5a414a7439 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Wed, 11 Mar 2026 05:52:22 +0100 Subject: [PATCH 58/74] Merge pull request #12378 from Pierre-Sassoulas/fix-implicit-str-concat-and-discovered-bug-due-to-it (#14282) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix bug discovered due to the change in ``implicit-str-concat`` (cherry picked from commit 55560d9d4187feecea18b1e637f43f55912d0303) Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) --- src/_pytest/_py/path.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/_py/path.py b/src/_pytest/_py/path.py index b7131b08a20..998a7819972 100644 --- a/src/_pytest/_py/path.py +++ b/src/_pytest/_py/path.py @@ -137,7 +137,7 @@ class NeverRaised(Exception): class Visitor: def __init__(self, fil, rec, ignore, bf, sort): - if isinstance(fil, str): + if isinstance(fil, (str, bytes)): fil = FNMatcher(fil) if isinstance(rec, str): self.rec: Callable[[LocalPath], bool] = FNMatcher(rec) From 74eac6916fee34726cb194f16c516e96fbd29619 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Tue, 17 Mar 2026 14:31:22 +0100 Subject: [PATCH 59/74] doc: Update training info (#14298) (#14301) (cherry picked from commit 5de1f491fe02110686ffdeb68bef3d855687ecab) Co-authored-by: Freya Bruhin --- doc/en/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/index.rst b/doc/en/index.rst index fa05b3a0c48..1140640c80a 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -2,7 +2,7 @@ .. sidebar:: **Next Open Trainings and Events** - - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training), **March 3rd -- 5th 2026**, Remote + - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training), **March 9th -- 11th 2027**, Leipzig (DE) / Remote Also see :doc:`previous talks and blogposts ` From ddee02a578da30dd43aedc39c1c1f1aaadfcee95 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 7 Apr 2026 17:43:09 +0300 Subject: [PATCH 60/74] Merge pull request #14343 from bluetech/cve-2025-71176-simple tmpdir: fix insecure temporary directory vulnerability (CVE-2025-71176) (cherry picked from commit 95d8423bd24992deea5b9df32555fa1741679e2c) --- changelog/14343.bugfix.rst | 1 + src/_pytest/tmpdir.py | 26 ++++++++++++++++++++++++-- testing/test_tmpdir.py | 31 +++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 changelog/14343.bugfix.rst diff --git a/changelog/14343.bugfix.rst b/changelog/14343.bugfix.rst new file mode 100644 index 00000000000..a52028d9f86 --- /dev/null +++ b/changelog/14343.bugfix.rst @@ -0,0 +1 @@ +Fixed use of insecure temporary directory (CVE-2025-71176). diff --git a/src/_pytest/tmpdir.py b/src/_pytest/tmpdir.py index 855ad273ecf..66ca9f190e3 100644 --- a/src/_pytest/tmpdir.py +++ b/src/_pytest/tmpdir.py @@ -9,6 +9,7 @@ from pathlib import Path import re from shutil import rmtree +import stat import tempfile from typing import Any from typing import final @@ -170,16 +171,37 @@ def getbasetemp(self) -> Path: # Also, to keep things private, fixup any world-readable temp # rootdir's permissions. Historically 0o755 was used, so we can't # just error out on this, at least for a while. + # Don't follow symlinks, otherwise we're open to symlink-swapping + # TOCTOU vulnerability. + # This check makes us vulnerable to a DoS - a user can `mkdir + # /tmp/pytest-of-otheruser` and then `otheruser` will fail this + # check. For now we don't consider it a real problem. otheruser can + # change their TMPDIR or --basetemp, and maybe give the prankster a + # good scolding. uid = get_user_id() if uid is not None: - rootdir_stat = rootdir.stat() + stat_follow_symlinks = ( + False if os.stat in os.supports_follow_symlinks else True + ) + rootdir_stat = rootdir.stat(follow_symlinks=stat_follow_symlinks) + if stat.S_ISLNK(rootdir_stat.st_mode): + raise OSError( + f"The temporary directory {rootdir} is a symbolic link. " + "Fix this and try again." + ) if rootdir_stat.st_uid != uid: raise OSError( f"The temporary directory {rootdir} is not owned by the current user. " "Fix this and try again." ) if (rootdir_stat.st_mode & 0o077) != 0: - os.chmod(rootdir, rootdir_stat.st_mode & ~0o077) + chmod_follow_symlinks = ( + False if os.chmod in os.supports_follow_symlinks else True + ) + rootdir.chmod( + rootdir_stat.st_mode & ~0o077, + follow_symlinks=chmod_follow_symlinks, + ) keep = self._retention_count if self._retention_policy == "none": keep = 0 diff --git a/testing/test_tmpdir.py b/testing/test_tmpdir.py index 363172110d3..789e8005184 100644 --- a/testing/test_tmpdir.py +++ b/testing/test_tmpdir.py @@ -5,6 +5,7 @@ import dataclasses import os from pathlib import Path +import shutil import stat import sys from typing import cast @@ -619,3 +620,33 @@ def test_tmp_path_factory_fixes_up_world_readable_permissions( # After - fixed. assert (basetemp.parent.stat().st_mode & 0o077) == 0 + + +@pytest.mark.skipif( + not hasattr(os, "getuid") or os.stat not in os.supports_follow_symlinks, + reason="checks unix permissions and symlinks", +) +def test_tmp_path_factory_doesnt_follow_symlinks( + tmp_path: Path, monkeypatch: MonkeyPatch +) -> None: + """Verify that if a /tmp/pytest-of-foo directory is a symbolic link, + it is rejected (#13669, CVE-2025-71176).""" + attacker_controlled = tmp_path / "attacker_controlled" + attacker_controlled.mkdir() + + # Use the test's tmp_path as the system temproot (/tmp). + monkeypatch.setenv("PYTEST_DEBUG_TEMPROOT", str(tmp_path)) + + # First just get the pytest-of-user path. + tmp_factory = TempPathFactory(None, 3, "all", lambda *args: None, _ispytest=True) + pytest_of_user = tmp_factory.getbasetemp().parent + # Just for safety in the test, before we nuke it. + assert "pytest-of-" in str(pytest_of_user) + shutil.rmtree(pytest_of_user) + + pytest_of_user.symlink_to(attacker_controlled) + + # This now tries to use the directory when it's a symlink. + tmp_factory = TempPathFactory(None, 3, "all", lambda *args: None, _ispytest=True) + with pytest.raises(OSError, match=r"temporary directory .* is a symbolic link"): + tmp_factory.getbasetemp() From 8127eaf4ab7f6b2fdd0dc1b38343ec97aeef05ac Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 7 Apr 2026 19:32:26 +0300 Subject: [PATCH 61/74] Revert "Fix: assertrepr_compare respects dict insertion order (#14050) (#14193)" This reverts commit 60fb59d341a6373e632849de0a35b90aa85f0d61. Revert 9.0.x backport, will wait for 9.1.0 instead. --- changelog/14050.bugfix.rst | 1 - src/_pytest/_io/pprint.py | 4 ++-- src/_pytest/_io/saferepr.py | 25 -------------------- src/_pytest/pytester_assertions.py | 4 ++-- testing/io/test_saferepr.py | 37 ------------------------------ testing/test_assertion.py | 31 ------------------------- 6 files changed, 4 insertions(+), 98 deletions(-) delete mode 100644 changelog/14050.bugfix.rst diff --git a/changelog/14050.bugfix.rst b/changelog/14050.bugfix.rst deleted file mode 100644 index 451b248576f..00000000000 --- a/changelog/14050.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Display dictionary differences in assertion failures using the original key insertion order instead of sorted order. diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index ec41b449ddf..28f06909206 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -162,7 +162,7 @@ def _pprint_dict( ) -> None: write = stream.write write("{") - items = object.items() + items = sorted(object.items(), key=_safe_tuple) self._format_dict_items(items, stream, indent, allowance, context, level) write("}") @@ -608,7 +608,7 @@ def _safe_repr( components: list[str] = [] append = components.append level += 1 - for k, v in object.items(): + for k, v in sorted(object.items(), key=_safe_tuple): krepr = self._safe_repr(k, context, maxlevels, level) vrepr = self._safe_repr(v, context, maxlevels, level) append(f"{krepr}: {vrepr}") diff --git a/src/_pytest/_io/saferepr.py b/src/_pytest/_io/saferepr.py index 3f5c956d9cf..cee70e332f9 100644 --- a/src/_pytest/_io/saferepr.py +++ b/src/_pytest/_io/saferepr.py @@ -1,6 +1,5 @@ from __future__ import annotations -from itertools import islice import pprint import reprlib @@ -78,32 +77,8 @@ def repr_instance(self, x: object, level: int) -> str: s = _format_repr_exception(exc, x) if self.maxsize is not None: s = _ellipsize(s, self.maxsize) - return s - def repr_dict(self, x: dict[object, object], level: int) -> str: - """Represent a dict while preserving its insertion order. - - Differs from ``reprlib.Repr.repr_dict`` by iterating directly over ``x`` - rather than using the stdlib's sorting helper. - """ - fillvalue = "..." - n = len(x) - if n == 0: - return "{}" - if level <= 0: - return "{" + fillvalue + "}" - newlevel = level - 1 - repr1 = self.repr1 - pieces = [] - for key in islice(x, self.maxdict): - keyrepr = repr1(key, newlevel) - valrepr = repr1(x[key], newlevel) - pieces.append(f"{keyrepr}: {valrepr}") - if n > self.maxdict: - pieces.append(fillvalue) - return "{" + ", ".join(pieces) + "}" - def safeformat(obj: object) -> str: """Return a pretty printed string for the given object. diff --git a/src/_pytest/pytester_assertions.py b/src/_pytest/pytester_assertions.py index b8d8a195241..915cc8a10ff 100644 --- a/src/_pytest/pytester_assertions.py +++ b/src/_pytest/pytester_assertions.py @@ -26,11 +26,11 @@ def assertoutcome( realpassed, realskipped, realfailed = outcomes obtained = { - "failed": len(realfailed), "passed": len(realpassed), "skipped": len(realskipped), + "failed": len(realfailed), } - expected = {"failed": failed, "passed": passed, "skipped": skipped} + expected = {"passed": passed, "skipped": skipped, "failed": failed} assert obtained == expected, outcomes diff --git a/testing/io/test_saferepr.py b/testing/io/test_saferepr.py index 2e3dd55b81f..075d40cdf44 100644 --- a/testing/io/test_saferepr.py +++ b/testing/io/test_saferepr.py @@ -2,7 +2,6 @@ from __future__ import annotations from _pytest._io.saferepr import DEFAULT_REPR_MAX_SIZE -from _pytest._io.saferepr import SafeRepr from _pytest._io.saferepr import saferepr from _pytest._io.saferepr import saferepr_unlimited import pytest @@ -193,39 +192,3 @@ def __repr__(self): assert saferepr_unlimited(A()).startswith( "<[ValueError(42) raised in repr()] A object at 0x" ) - - -def test_saferepr_dict_preserves_insertion_order() -> None: - d = { - "b": 2, - "a": 1, - "d": 4, - "e": 5, - "c": 3, - } - s = SafeRepr(maxsize=None) - s.maxdict = 10 - assert s.repr(d) == "{'b': 2, 'a': 1, 'd': 4, 'e': 5, 'c': 3}" - - -def test_saferepr_dict_truncation_preserves_insertion_order() -> None: - d = { - "b": 2, - "a": 1, - "d": 4, - "e": 5, - "c": 3, - } - s = SafeRepr(maxsize=None) - s.maxdict = 1 - assert s.repr(d) == "{'b': 2, ...}" - - -def test_saferepr_dict_fillvalue_when_level_is_zero() -> None: - s = SafeRepr(maxsize=None) - assert s.repr_dict({"a": 1}, level=0) == "{...}" - - -def test_saferepr_dict_empty() -> None: - s = SafeRepr(maxsize=None) - assert s.repr_dict({}, level=1) == "{}" diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 12351a48a7f..5179b13b0e9 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -2198,34 +2198,3 @@ def test_vvv(): ] ) result.stdout.no_fnmatch_line(expected_non_vvv_arg_line) - - -def test_dict_extra_items_preserve_insertion_order(pytester: Pytester) -> None: - """Assertion output of dict diff shows keys in insertion order (#13503).""" - pytester.makepyfile( - test_order=""" - def test_order(): - a = { - "b": 2, - "a": 1, - "d": 4, - "e": 5, - "c": 3, - } - assert a == {} - """ - ) - - result = pytester.runpytest("-vv") - result.stdout.fnmatch_lines( - [ - "*Left contains 5 more items:*", - "*Full diff:", - "* + *'b': 2,", - "* + *'a': 1,", - "* + *'d': 4,", - "* + *'e': 5,", - "* + *'c': 3,", - "test_order.py:*: AssertionError", - ] - ) From a7d58d7a21b78581e636bbbdea13c66ad1657c1e Mon Sep 17 00:00:00 2001 From: pytest bot Date: Tue, 7 Apr 2026 16:52:39 +0000 Subject: [PATCH 62/74] Prepare release version 9.0.3 --- changelog/12444.bugfix.rst | 1 - changelog/12689.contrib.rst | 5 --- changelog/13388.doc.rst | 1 - changelog/13634.bugfix.rst | 5 --- changelog/13731.doc.rst | 1 - changelog/13734.bugfix.rst | 1 - changelog/14088.doc.rst | 1 - changelog/14195.bugfix.rst | 1 - changelog/14255.doc.rst | 1 - changelog/14343.bugfix.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-9.0.3.rst | 38 +++++++++++++++++++++ doc/en/builtin.rst | 4 +-- doc/en/changelog.rst | 52 +++++++++++++++++++++++++++++ doc/en/example/parametrize.rst | 6 ++-- doc/en/example/pythoncollection.rst | 4 +-- doc/en/getting-started.rst | 2 +- doc/en/how-to/fixtures.rst | 2 +- 18 files changed, 100 insertions(+), 27 deletions(-) delete mode 100644 changelog/12444.bugfix.rst delete mode 100644 changelog/12689.contrib.rst delete mode 100644 changelog/13388.doc.rst delete mode 100644 changelog/13634.bugfix.rst delete mode 100644 changelog/13731.doc.rst delete mode 100644 changelog/13734.bugfix.rst delete mode 100644 changelog/14088.doc.rst delete mode 100644 changelog/14195.bugfix.rst delete mode 100644 changelog/14255.doc.rst delete mode 100644 changelog/14343.bugfix.rst create mode 100644 doc/en/announce/release-9.0.3.rst diff --git a/changelog/12444.bugfix.rst b/changelog/12444.bugfix.rst deleted file mode 100644 index d4e804ac613..00000000000 --- a/changelog/12444.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed :func:`pytest.approx` which now correctly takes into account :class:`~collections.abc.Mapping` keys order to compare them. diff --git a/changelog/12689.contrib.rst b/changelog/12689.contrib.rst deleted file mode 100644 index 81bb5577d97..00000000000 --- a/changelog/12689.contrib.rst +++ /dev/null @@ -1,5 +0,0 @@ -The test reports are now published to Codecov from GitHub Actions. -The test statistics is visible `on the web interface -`__. - --- by :user:`aleguy02` diff --git a/changelog/13388.doc.rst b/changelog/13388.doc.rst deleted file mode 100644 index bade402a60d..00000000000 --- a/changelog/13388.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Clarified documentation for ``-p`` vs ``PYTEST_PLUGINS`` plugin loading and fixed an incorrect ``-p`` example. diff --git a/changelog/13634.bugfix.rst b/changelog/13634.bugfix.rst deleted file mode 100644 index ee12aeafc3a..00000000000 --- a/changelog/13634.bugfix.rst +++ /dev/null @@ -1,5 +0,0 @@ -Blocking a ``conftest.py`` file using the ``-p no:`` option is now explicitly disallowed. - -Previously this resulted in an internal assertion failure during plugin loading. - -Pytest now raises a clear ``UsageError`` explaining that conftest files are not plugins and cannot be disabled via ``-p``. diff --git a/changelog/13731.doc.rst b/changelog/13731.doc.rst deleted file mode 100644 index 0cfdbebfc40..00000000000 --- a/changelog/13731.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Clarified that capture fixtures (e.g. ``capsys`` and ``capfd``) take precedence over the ``-s`` / ``--capture=no`` command-line options in :ref:`Accessing captured output from a test function `. diff --git a/changelog/13734.bugfix.rst b/changelog/13734.bugfix.rst deleted file mode 100644 index de1d7368cd4..00000000000 --- a/changelog/13734.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed crash when a test raises an exceptiongroup with ``__tracebackhide__ = True``. diff --git a/changelog/14088.doc.rst b/changelog/14088.doc.rst deleted file mode 100644 index 3f3a0963516..00000000000 --- a/changelog/14088.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Clarified that the default :hook:`pytest_collection` hook sets ``session.items`` before it calls :hook:`pytest_collection_finish`, not after. diff --git a/changelog/14195.bugfix.rst b/changelog/14195.bugfix.rst deleted file mode 100644 index 29ae149dd98..00000000000 --- a/changelog/14195.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed an issue where non-string messages passed to `unittest.TestCase.subTest()` were not printed. diff --git a/changelog/14255.doc.rst b/changelog/14255.doc.rst deleted file mode 100644 index b96d2c2a1b9..00000000000 --- a/changelog/14255.doc.rst +++ /dev/null @@ -1 +0,0 @@ -TOML integer log levels must be quoted: Updating reference documentation. diff --git a/changelog/14343.bugfix.rst b/changelog/14343.bugfix.rst deleted file mode 100644 index a52028d9f86..00000000000 --- a/changelog/14343.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed use of insecure temporary directory (CVE-2025-71176). diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index b92b8d4a56b..4a5e8b86544 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-9.0.3 release-9.0.2 release-9.0.1 release-9.0.0 diff --git a/doc/en/announce/release-9.0.3.rst b/doc/en/announce/release-9.0.3.rst new file mode 100644 index 00000000000..c9540218764 --- /dev/null +++ b/doc/en/announce/release-9.0.3.rst @@ -0,0 +1,38 @@ +pytest-9.0.3 +======================================= + +pytest 9.0.3 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Aditya Giri +* Alejandro Villate +* Bruno Oliveira +* Bubble-Interface +* Charles-Meldhine Madi Mnemoi +* DavidAG +* Denis Cherednichenko +* Dr Alex Mitre +* Freya +* Freya Bruhin +* Hugo van Kemenade +* John Litborn +* Liam DeVoe +* Lily Wu +* Maxime Grenu +* Ran Benita +* Randy Döring +* Ronald Eddy Jr +* Samuel Newbold +* Tejas Verma +* Vladimir +* jxramos +* 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 6a96bb0a304..9d38b329454 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -257,10 +257,10 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a subtests -- .../_pytest/subtests.py:129 Provides subtests functionality. - tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:243 + tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:265 Return a :class:`pytest.TempPathFactory` instance for the test session. - tmp_path -- .../_pytest/tmpdir.py:258 + tmp_path -- .../_pytest/tmpdir.py:280 Return a temporary directory (as :class:`pathlib.Path` object) which is unique to each test function invocation. The temporary directory is created as a subdirectory diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index bcae26aa09b..5bcd44c4226 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -31,6 +31,58 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 9.0.3 (2026-04-07) +========================= + +Bug fixes +--------- + +- `#12444 `_: Fixed :func:`pytest.approx` which now correctly takes into account :class:`~collections.abc.Mapping` keys order to compare them. + + +- `#13634 `_: Blocking a ``conftest.py`` file using the ``-p no:`` option is now explicitly disallowed. + + Previously this resulted in an internal assertion failure during plugin loading. + + Pytest now raises a clear ``UsageError`` explaining that conftest files are not plugins and cannot be disabled via ``-p``. + + +- `#13734 `_: Fixed crash when a test raises an exceptiongroup with ``__tracebackhide__ = True``. + + +- `#14195 `_: Fixed an issue where non-string messages passed to `unittest.TestCase.subTest()` were not printed. + + +- `#14343 `_: Fixed use of insecure temporary directory (CVE-2025-71176). + + + +Improved documentation +---------------------- + +- `#13388 `_: Clarified documentation for ``-p`` vs ``PYTEST_PLUGINS`` plugin loading and fixed an incorrect ``-p`` example. + + +- `#13731 `_: Clarified that capture fixtures (e.g. ``capsys`` and ``capfd``) take precedence over the ``-s`` / ``--capture=no`` command-line options in :ref:`Accessing captured output from a test function `. + + +- `#14088 `_: Clarified that the default :hook:`pytest_collection` hook sets ``session.items`` before it calls :hook:`pytest_collection_finish`, not after. + + +- `#14255 `_: TOML integer log levels must be quoted: Updating reference documentation. + + + +Contributor-facing changes +-------------------------- + +- `#12689 `_: The test reports are now published to Codecov from GitHub Actions. + The test statistics is visible `on the web interface + `__. + + -- by :user:`aleguy02` + + pytest 9.0.2 (2025-12-06) ========================= diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index b25b822618a..ae64a7c62d5 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -162,7 +162,7 @@ objects, they are still using the default pytest representation: rootdir: /home/sweet/project collected 8 items - + @@ -239,7 +239,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia rootdir: /home/sweet/project collected 4 items - + @@ -318,7 +318,7 @@ Let's first see how it looks like at collection time: rootdir: /home/sweet/project collected 2 items - + diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 26fdb68b08f..48ee2c8533f 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -142,7 +142,7 @@ The test collection would look like this: configfile: pytest.toml collected 2 items - + @@ -205,7 +205,7 @@ You can always peek at the collection tree without running tests like this: configfile: pytest.toml collected 3 items - + diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 3ba30a90b34..76a4428c163 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -20,7 +20,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 9.0.2 + pytest 9.0.3 .. _`simpletest`: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index b37386525c6..2f554fb8c60 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1423,7 +1423,7 @@ Running the above tests results in the following test IDs being used: rootdir: /home/sweet/project collected 12 items - + From 68a341f49596fa43c89e052d437723860b98a443 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 12:07:51 +0000 Subject: [PATCH 63/74] Fix `-V` to show version information (#14382) (#14407) This regressed in #13575. Fixes #14381. (cherry picked from commit d72943a57266ef368fb3498a3fd136cbf1c7aee6) Co-authored-by: Bruno Oliveira --- changelog/14381.bugfix.rst | 1 + src/_pytest/config/__init__.py | 7 +++++-- testing/test_helpconfig.py | 7 ++++--- 3 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 changelog/14381.bugfix.rst diff --git a/changelog/14381.bugfix.rst b/changelog/14381.bugfix.rst new file mode 100644 index 00000000000..d3552a6304d --- /dev/null +++ b/changelog/14381.bugfix.rst @@ -0,0 +1 @@ +Fixed ``-V`` (short form of ``--version``) to properly display the current version. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index a027dbc02a4..4cd8d317f6e 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -180,9 +180,12 @@ def main( :returns: An exit code. """ - # Handle a single `--version` argument early to avoid starting up the entire pytest infrastructure. + # Handle a single `--version`/`-V` argument early to avoid starting up the entire pytest infrastructure. new_args = sys.argv[1:] if args is None else args - if isinstance(new_args, Sequence) and new_args.count("--version") == 1: + if ( + isinstance(new_args, Sequence) + and (new_args.count("--version") + new_args.count("-V")) == 1 + ): sys.stdout.write(f"pytest {__version__}\n") return ExitCode.OK diff --git a/testing/test_helpconfig.py b/testing/test_helpconfig.py index b01a6fa1559..7c2cb49d87e 100644 --- a/testing/test_helpconfig.py +++ b/testing/test_helpconfig.py @@ -16,10 +16,11 @@ def test_version_verbose(pytester: Pytester, pytestconfig, monkeypatch) -> None: result.stdout.fnmatch_lines(["*registered third-party plugins:", "*at*"]) -def test_version_less_verbose(pytester: Pytester) -> None: - """Single ``--version`` parameter should display only the pytest version, without loading plugins (#13574).""" +@pytest.mark.parametrize("flag", ["--version", "-V"]) +def test_version_less_verbose(pytester: Pytester, flag: str) -> None: + """Single ``--version`` or ``-V`` should display only the pytest version, without loading plugins (#13574).""" pytester.makeconftest("print('This should not be printed')") - result = pytester.runpytest_subprocess("--version") + result = pytester.runpytest_subprocess(flag) assert result.ret == ExitCode.OK assert result.stdout.str().strip() == f"pytest {pytest.__version__}" From 093184048e36453c5b8c1bb770f22e956a9f310d Mon Sep 17 00:00:00 2001 From: Garion Milazzo <168796509+lavaFreak@users.noreply.github.com> Date: Sun, 26 Apr 2026 00:21:16 -0700 Subject: [PATCH 64/74] raises: suppress exception cause in raises match failures (#14391) (cherry picked from commit cd7592c41c40ebc9663c2984447d72e95c731bda) --- AUTHORS | 1 + changelog/14389.bugfix.rst | 1 + src/_pytest/raises.py | 2 +- testing/python/raises.py | 27 +++++++++++++++++++++++++++ 4 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 changelog/14389.bugfix.rst diff --git a/AUTHORS b/AUTHORS index e8140292aa4..f2f419cf642 100644 --- a/AUTHORS +++ b/AUTHORS @@ -179,6 +179,7 @@ Fraser Stark Freya Bruhin Gabriel Landau Gabriel Reis +Garion Milazzo Garvit Shubham Gene Wood George Kussumoto diff --git a/changelog/14389.bugfix.rst b/changelog/14389.bugfix.rst new file mode 100644 index 00000000000..f0d85169d0b --- /dev/null +++ b/changelog/14389.bugfix.rst @@ -0,0 +1 @@ +Improved :func:`pytest.raises(..., match=...) ` failures to suppress the mismatched exception as a cause of the resulting ``AssertionError``. diff --git a/src/_pytest/raises.py b/src/_pytest/raises.py index 7c246fde280..3ab109c0641 100644 --- a/src/_pytest/raises.py +++ b/src/_pytest/raises.py @@ -716,7 +716,7 @@ def __exit__( if not self.matches(exc_val): if self._just_propagate: return False - raise AssertionError(self._fail_reason) + raise AssertionError(self._fail_reason) from None # Cast to narrow the exception type now that it's verified.... # even though the TypeGuard in self.matches should be narrowing diff --git a/testing/python/raises.py b/testing/python/raises.py index c9d57918a83..9fd43ecbdaf 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -177,6 +177,33 @@ def test_invalid_regex(): result.stdout.no_fnmatch_line("*File*") result.stdout.no_fnmatch_line("*line*") + def test_raises_match_failure_suppresses_exception_context( + self, pytester: Pytester + ) -> None: + pytester.makepyfile( + """ + import pytest + + def test_raises_match_failure(): + with pytest.raises(ValueError, match="expected"): + raise ValueError("actual") + """ + ) + result = pytester.runpytest("--tb=short") + assert result.ret == 1 + result.stdout.fnmatch_lines( + [ + "*E*AssertionError: Regex pattern did not match.*", + ] + ) + result.stdout.no_fnmatch_line("*ValueError: actual") + result.stdout.no_fnmatch_line( + "*The above exception was the direct cause of the following exception:*" + ) + result.stdout.no_fnmatch_line( + "*During handling of the above exception, another exception occurred:*" + ) + def test_noclass(self) -> None: with pytest.raises(TypeError): pytest.raises("wrong", lambda: None) # type: ignore[call-overload] From 6e8f51481a2f7891da6301528620c8cff22a06d4 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Fri, 1 May 2026 11:44:49 +0000 Subject: [PATCH 65/74] docs: guard pytestconfig.cache example when cacheprovider is disabled (#14254) (#14433) Update the `config.cache` example in `doc/en/how-to/cache.rst` to safely handle cases where the `cacheprovider` plugin is disabled. Closes #14148 (cherry picked from commit 2aa07343b6ebcb426f4cc595e3bf1912b0a442de) Co-authored-by: Dr Alex Mitre --- changelog/14148.doc.rst | 2 ++ doc/en/how-to/cache.rst | 11 +++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 changelog/14148.doc.rst diff --git a/changelog/14148.doc.rst b/changelog/14148.doc.rst new file mode 100644 index 00000000000..b54ae2cd8e3 --- /dev/null +++ b/changelog/14148.doc.rst @@ -0,0 +1,2 @@ +Documented a safe ``pytestconfig.cache`` access pattern when the +``cacheprovider`` plugin is disabled. diff --git a/doc/en/how-to/cache.rst b/doc/en/how-to/cache.rst index ca345916fc5..c030e487563 100644 --- a/doc/en/how-to/cache.rst +++ b/doc/en/how-to/cache.rst @@ -214,11 +214,18 @@ across pytest invocations: @pytest.fixture def mydata(pytestconfig): - val = pytestconfig.cache.get("example/value", None) + cache = getattr(pytestconfig, "cache", None) + if cache is None: + # pytestconfig not having the cache attribute means the + # cache plugin is disabled. + expensive_computation() + return 42 + + val = cache.get("example/value", None) if val is None: expensive_computation() val = 42 - pytestconfig.cache.set("example/value", val) + cache.set("example/value", val) return val From e4f1cf3e4de43baf642b92a8da0884c2f4de1fe8 Mon Sep 17 00:00:00 2001 From: Praneeth Kodumagulla <64239307+praneethhere@users.noreply.github.com> Date: Fri, 8 May 2026 15:40:31 -0500 Subject: [PATCH 66/74] Fix strict options from addopts Closes #14442 (cherry picked from commit a481f264d70ac3d053d5f7408f4ac1ec439d0c2f) --- AUTHORS | 1 + changelog/14442.bugfix.rst | 3 +++ src/_pytest/config/__init__.py | 7 +++++++ testing/test_config.py | 15 ++++++++++----- testing/test_mark.py | 21 +++++++++++++-------- 5 files changed, 34 insertions(+), 13 deletions(-) create mode 100644 changelog/14442.bugfix.rst diff --git a/AUTHORS b/AUTHORS index f2f419cf642..620ed218886 100644 --- a/AUTHORS +++ b/AUTHORS @@ -373,6 +373,7 @@ Piotr Banaszkiewicz Piotr Helm Poulami Sau Prakhar Gurunani +Praneeth Kodumagulla Prashant Anand Prashant Sharma Pulkit Goyal diff --git a/changelog/14442.bugfix.rst b/changelog/14442.bugfix.rst new file mode 100644 index 00000000000..90999cc9572 --- /dev/null +++ b/changelog/14442.bugfix.rst @@ -0,0 +1,3 @@ +Fixed a regression in pytest 9.0 where :option:`--strict-markers` and :option:`--strict-config` specified through :confval:`addopts` were silently ignored. + +Note that when targeting pytest >= 9.0, it's nicer to use :confval:`strict_markers` and :confval:`strict_config`, or :ref:`strict mode `. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 4cd8d317f6e..67d9a0aa111 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -50,6 +50,7 @@ from .exceptions import UsageError as UsageError from .findpaths import ConfigValue from .findpaths import determine_setup +from .findpaths import parse_override_ini from _pytest import __version__ import _pytest._code from _pytest._code import ExceptionInfo @@ -1535,6 +1536,12 @@ def parse(self, args: list[str], addopts: bool = True) -> None: self.known_args_namespace = self._parser.parse_known_args( args, namespace=copy.copy(self.option) ) + if addopts: + # addopts may have added overrides (especially via OverrideIniAction). + # The thing can be endlessly circular but we only do one level (#14442). + if overrides := parse_override_ini(self.known_args_namespace.override_ini): + self._inicfg.update(overrides) + self._inicache.clear() self._checkversion() self._consider_importhook() self._configure_python_path() diff --git a/testing/test_config.py b/testing/test_config.py index f086778ad1e..4496e94d0f4 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -459,16 +459,21 @@ def test_silence_unknown_key_warning(self, pytester: Pytester) -> None: result = pytester.runpytest() result.stdout.no_fnmatch_line("*PytestConfigWarning*") - @pytest.mark.parametrize("option_name", ["strict_config", "strict"]) - def test_strict_config_ini_option( - self, pytester: Pytester, option_name: str - ) -> None: + @pytest.mark.parametrize( + "option", + [ + "strict_config = true", + "strict = true", + "addopts = --strict-config", + ], + ) + def test_strict_config_ini_option(self, pytester: Pytester, option: str) -> None: """Test that strict_config and strict ini options enable strict config checking.""" pytester.makeini( f""" [pytest] unknown_option = 1 - {option_name} = True + {option} """ ) result = pytester.runpytest() diff --git a/testing/test_mark.py b/testing/test_mark.py index 8d76ea310eb..70df03be2fd 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -184,11 +184,16 @@ def test_hello(): @pytest.mark.parametrize( - "option_name", ["--strict-markers", "--strict", "strict_markers", "strict"] + "option", + [ + "--strict-markers", + "--strict", + "strict_markers = true", + "strict = true", + "addopts = --strict-markers", + ], ) -def test_strict_prohibits_unregistered_markers( - pytester: Pytester, option_name: str -) -> None: +def test_strict_prohibits_unregistered_markers(pytester: Pytester, option: str) -> None: pytester.makepyfile( """ import pytest @@ -197,16 +202,16 @@ def test_hello(): pass """ ) - if option_name in ("strict_markers", "strict"): + if option.startswith("-"): + result = pytester.runpytest(option) + else: pytester.makeini( f""" [pytest] - {option_name} = true + {option} """ ) result = pytester.runpytest() - else: - result = pytester.runpytest(option_name) assert result.ret != 0 result.stdout.fnmatch_lines( ["'unregisteredmark' not found in `markers` configuration option"] From 439f3efb7e0049d7c4cc1d58a592d837988f72b8 Mon Sep 17 00:00:00 2001 From: EternalRights <162705204+EternalRights@users.noreply.github.com> Date: Wed, 13 May 2026 23:42:37 +0800 Subject: [PATCH 67/74] mark/expression: fix scanner - search for backslash in string value, not entire input (#14475) The backslash check in the string literal lexer was searching the entire input expression (input.find("\")) instead of only the current string value (value.find("\")). This caused false rejections when an identifier containing a backslash appeared in the same expression as a string literal. For example, `pytest -k 'test\nfoo\n and mark(x="y")'` would fail with "escaping not supported" even though the backslash is in the identifier, not the string. Closes #14474 (cherry picked from commit 984cabfaccf8aa69fe49097ed3d07bd60d05f240) --- changelog/14474.bugfix.rst | 1 + src/_pytest/mark/expression.py | 4 ++-- testing/test_mark_expression.py | 14 ++++++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 changelog/14474.bugfix.rst diff --git a/changelog/14474.bugfix.rst b/changelog/14474.bugfix.rst new file mode 100644 index 00000000000..333d4d34d9a --- /dev/null +++ b/changelog/14474.bugfix.rst @@ -0,0 +1 @@ +Fixed a regression where ``-k`` and ``-m`` expressions containing both backslash characters in identifiers and string literal arguments would incorrectly raise a ``SyntaxError`` about escaping. diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index 3bdbd03c2b5..4b4a68d8a74 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -102,10 +102,10 @@ def lex(self, input: str) -> Iterator[Token]: (FILE_NAME, 1, pos + 1, input), ) value = input[pos : end_quote_pos + 1] - if (backslash_pos := input.find("\\")) != -1: + if (backslash_pos := value.find("\\")) != -1: raise SyntaxError( r'escaping with "\" not supported in marker expression', - (FILE_NAME, 1, backslash_pos + 1, input), + (FILE_NAME, 1, pos + backslash_pos + 1, input), ) yield Token(TokenType.STRING, value, pos) pos += len(value) diff --git a/testing/test_mark_expression.py b/testing/test_mark_expression.py index 1e3c769347c..3a606bac17c 100644 --- a/testing/test_mark_expression.py +++ b/testing/test_mark_expression.py @@ -86,6 +86,20 @@ def matcher(name: str, /, **kwargs: str | int | bool | None) -> bool: evaluate("\nfoo\n", matcher) +def test_backslash_in_identifier_with_string_literal() -> None: + r"""Backslashes in identifiers should not cause false rejections when the + expression also contains string literals. Regression test for a bug where + the scanner searched the entire input for backslashes instead of only the + current string literal value.""" + + def matcher(name: str, /, **kwargs: str | int | bool | None) -> bool: + return {r"\nfoo\n", r"test\case", "mark"}.__contains__(name) + + assert evaluate(r'\nfoo\n and mark(x="y")', matcher) + assert evaluate(r'mark(x="y") and \nfoo\n', matcher) + assert evaluate(r'test\case and mark(x="y")', matcher) + + @pytest.mark.parametrize( ("expr", "column", "message"), ( From a86f3c3eebf98398c5ea431375a1cd972a3e2edc Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sat, 23 May 2026 14:02:58 +0000 Subject: [PATCH 68/74] docs: clarify subtests progress output (#14467) (#14468) (cherry picked from commit 7df5d80ff3a98714a1d3cdbe82941229e511f4b3) Co-authored-by: 1Utkarsh1 <121078149+1Utkarsh1@users.noreply.github.com> Co-authored-by: OpenAI Codex --- changelog/13902.doc.rst | 1 + doc/en/how-to/subtests.rst | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 changelog/13902.doc.rst diff --git a/changelog/13902.doc.rst b/changelog/13902.doc.rst new file mode 100644 index 00000000000..f11a1936051 --- /dev/null +++ b/changelog/13902.doc.rst @@ -0,0 +1 @@ +Clarified how subtest progress markers are shown in the documentation. diff --git a/doc/en/how-to/subtests.rst b/doc/en/how-to/subtests.rst index 93b9d052afd..c71f1bbe1ad 100644 --- a/doc/en/how-to/subtests.rst +++ b/doc/en/how-to/subtests.rst @@ -26,7 +26,7 @@ Subtests are an alternative to parametrization, particularly useful when the exa Each assertion failure or error is caught by the context manager and reported individually: -.. code-block:: pytest +.. code-block:: text $ pytest -q test_subtest.py uuuuuF [100%] @@ -63,6 +63,8 @@ Each assertion failure or error is caught by the context manager and reported in In the output above: +* The compact progress output uses ``u`` for both passed and failed subtests; + see the short test summary for each failed subtest. * Subtest failures are reported as ``SUBFAILED``. * Subtests are reported first and the "top-level" test is reported at the end on its own. From 02c9610f38b82a803fc61214d9a14d58263a0eaf Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Tue, 26 May 2026 17:50:14 +0200 Subject: [PATCH 69/74] Merge pull request #14511 from The-Compiler/doc-sprint (#14525) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit doc: Add pytest sprint (cherry picked from commit 8927e35166ab410afe5002dcfa93481dc020c096) Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) --- doc/en/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/en/index.rst b/doc/en/index.rst index 1140640c80a..29d270084e9 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -2,6 +2,7 @@ .. sidebar:: **Next Open Trainings and Events** + - `pytest development sprint `_, **July 20th -- 24th**, Klaus (AT), sign-up open until June 15th - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training), **March 9th -- 11th 2027**, Leipzig (DE) / Remote Also see :doc:`previous talks and blogposts ` From 7fc5c7908bd90b273305de192ca2bd9ae38ed36a Mon Sep 17 00:00:00 2001 From: EternalRights <162705204+EternalRights@users.noreply.github.com> Date: Thu, 28 May 2026 22:00:24 +0800 Subject: [PATCH 70/74] junitxml: fix supplementary plane characters incorrectly escaped (#14484) Closes #14483 (cherry picked from commit 4748bb15b9053a791c04783d4d84eba512c7cf79) --- changelog/14483.bugfix.rst | 1 + src/_pytest/junitxml.py | 4 +--- testing/test_junitxml.py | 8 ++------ 3 files changed, 4 insertions(+), 9 deletions(-) create mode 100644 changelog/14483.bugfix.rst diff --git a/changelog/14483.bugfix.rst b/changelog/14483.bugfix.rst new file mode 100644 index 00000000000..cdc5d0f5af7 --- /dev/null +++ b/changelog/14483.bugfix.rst @@ -0,0 +1 @@ +Fixed JUnit XML report incorrectly escaping high Unicode codepoints (supplementary plane characters like emoji) in test failure messages. -- by :user:`EternalRights` diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index ae8d2b94d36..30c93c88c07 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -55,9 +55,7 @@ def repl(matchobj: re.Match[str]) -> str: # The spec range of valid chars is: # Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] # For an unknown(?) reason, we disallow #x7F (DEL) as well. - illegal_xml_re = ( - "[^\u0009\u000a\u000d\u0020-\u007e\u0080-\ud7ff\ue000-\ufffd\u10000-\u10ffff]" - ) + illegal_xml_re = "[^\u0009\u000a\u000d\u0020-\u007e\u0080-\ud7ff\ue000-\ufffd\U00010000-\U0010ffff]" return re.sub(illegal_xml_re, repl, str(arg)) diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index 5a603c05bc8..2ddae7e0a39 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -1104,9 +1104,6 @@ def test_invalid_xml_escape() -> None: # Test some more invalid xml chars, the full range should be # tested really but let's just test the edges of the ranges # instead. - # XXX This only tests low unicode character points for now as - # there are some issues with the testing infrastructure for - # the higher ones. # XXX Testing 0xD (\r) is tricky as it overwrites the just written # line in the output, so we skip it too. invalid = ( @@ -1121,9 +1118,8 @@ def test_invalid_xml_escape() -> None: 0xDFFF, 0xFFFE, 0x0FFFF, - ) # , 0x110000) - valid = (0x9, 0xA, 0x20) - # 0xD, 0xD7FF, 0xE000, 0xFFFD, 0x10000, 0x10FFFF) + ) + valid = (0x9, 0xA, 0x20, 0xD, 0xD7FF, 0xE000, 0xFFFD, 0x10000, 0x10FFFF) for i in invalid: got = bin_xml_escape(chr(i)) From 76fefd0e57df8e49768e0b7673044125c28727f4 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sat, 30 May 2026 09:06:38 -0300 Subject: [PATCH 71/74] Fix Code.getargs() treating co_flags bitmask values as counts (#14493) (#14535) CO_VARARGS (4) and CO_VARKEYWORDS (8) are bitmask flags, but they were used directly as increment values for the argument count via `&`. This caused co_varnames[:argcount] to slice beyond the actual arguments when the function body contained enough local variables. Fix by wrapping the bitmask results in bool(), so they contribute at most 1 to the argcount. Closes #14492 (cherry picked from commit f976bb67b293cf358e2fbd0352638e2f5a9da8e0) Co-authored-by: EternalRights <162705204+EternalRights@users.noreply.github.com> --- changelog/14492.bugfix.rst | 1 + src/_pytest/_code/code.py | 5 +++-- testing/code/test_code.py | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 changelog/14492.bugfix.rst diff --git a/changelog/14492.bugfix.rst b/changelog/14492.bugfix.rst new file mode 100644 index 00000000000..1e5c6b778d3 --- /dev/null +++ b/changelog/14492.bugfix.rst @@ -0,0 +1 @@ +Fixed ``Code.getargs()`` incorrectly including local variable names in the returned argument tuple for functions with ``*args`` and/or ``**kwargs``. The method was using ``co_flags`` bitmask values (``4`` and ``8``) directly as counts instead of converting them to ``1`` via ``bool()``, and was not accounting for ``co_kwonlyargcount`` when ``var=True``. diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 4cf99a77340..4fcce0427ef 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -121,8 +121,9 @@ def getargs(self, var: bool = False) -> tuple[str, ...]: raw = self.raw argcount = raw.co_argcount if var: - argcount += raw.co_flags & CO_VARARGS - argcount += raw.co_flags & CO_VARKEYWORDS + argcount += raw.co_kwonlyargcount + argcount += bool(raw.co_flags & CO_VARARGS) + argcount += bool(raw.co_flags & CO_VARKEYWORDS) return raw.co_varnames[:argcount] diff --git a/testing/code/test_code.py b/testing/code/test_code.py index ae5e0e949cf..d21330429ca 100644 --- a/testing/code/test_code.py +++ b/testing/code/test_code.py @@ -117,6 +117,20 @@ def f4(x, *y, **z): c4 = Code.from_function(f4) assert c4.getargs(var=True) == ("x", "y", "z") + def f5(x, *y, **z): + a1 = a2 = a3 = a4 = a5 = a6 = 1 # noqa: F841 + + c5 = Code.from_function(f5) + f5(1, 2, 3, z=4) # cover function body + assert c5.getargs(var=True) == ("x", "y", "z") + + def f6(x, *y, kw=1, **z): + a1 = a2 = a3 = a4 = a5 = a6 = 1 # noqa: F841 + + c6 = Code.from_function(f6) + f6(1, 2, kw=3, z=4) # cover function body + assert c6.getargs(var=True) == ("x", "kw", "y", "z") + def test_frame_getargs() -> None: def f1(x) -> FrameType: From 1e5f8d07534a16969240181a48ba7b202f3025d6 Mon Sep 17 00:00:00 2001 From: arya rizky Date: Thu, 14 May 2026 16:40:33 +0700 Subject: [PATCH 72/74] approx: fix buggy `__array_interface__` check Fix #14456 (cherry picked from commit 21be7a259424e509e3d667082a138bcc8fc45c00) --- AUTHORS | 1 + changelog/14456.bugfix.rst | 1 + src/_pytest/python_api.py | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 changelog/14456.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 620ed218886..af895ed1855 100644 --- a/AUTHORS +++ b/AUTHORS @@ -21,6 +21,7 @@ Alex Lambson Alexander Johnson Alexander King Alexei Kozlenok +algojogacor Alice Purcell Allan Feldman Aly Sivji diff --git a/changelog/14456.bugfix.rst b/changelog/14456.bugfix.rst new file mode 100644 index 00000000000..ccd9ca20a8f --- /dev/null +++ b/changelog/14456.bugfix.rst @@ -0,0 +1 @@ +Fixed :func:`pytest.approx` not recognizing types with ``__array_interface__`` as numpy-like arrays. diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index bab70aa4a8c..1ff35e94fcf 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -814,6 +814,6 @@ def _as_numpy_array(obj: object) -> ndarray | None: return None elif isinstance(obj, np.ndarray): return obj - elif hasattr(obj, "__array__") or hasattr("obj", "__array_interface__"): + elif hasattr(obj, "__array__") or hasattr(obj, "__array_interface__"): return np.asarray(obj) return None From 612f39c38bc4cb0c0e8c52f5f889e612c39b7658 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Thu, 4 Jun 2026 10:25:11 +0300 Subject: [PATCH 73/74] Merge pull request #14550 from trendels/docs-fix docs: fix target of "assertraises" anchor. (cherry picked from commit aa01adceb7d52294d7a78f68939bf6862e0ce846) --- doc/en/how-to/assert.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/how-to/assert.rst b/doc/en/how-to/assert.rst index 006cf475b02..377b2a5a3c0 100644 --- a/doc/en/how-to/assert.rst +++ b/doc/en/how-to/assert.rst @@ -64,8 +64,6 @@ it is printed alongside the assertion introspection in the traceback. See :ref:`assert-details` for more information on assertion introspection. -.. _`assertraises`: - Assertions about approximate equality ------------------------------------- @@ -93,6 +91,8 @@ It also supports comparisons involving NaNs. See :func:`pytest.approx` for details. +.. _`assertraises`: + Assertions about expected exceptions ------------------------------------------ From 9577bd9d076669bd7443b396004bc17ed868b66f Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Thu, 4 Jun 2026 09:52:29 -0300 Subject: [PATCH 74/74] Clarify request fixture in indirect parametrization docs (#14539) (#14555) Closes #13155 --------- (cherry picked from commit 3422c67a3a46ccb4b5549c88821d5d768843418e) Co-authored-by: morning-verlu Co-authored-by: Bruno Oliveira --- changelog/13155.doc.rst | 1 + doc/en/example/parametrize.rst | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 changelog/13155.doc.rst diff --git a/changelog/13155.doc.rst b/changelog/13155.doc.rst new file mode 100644 index 00000000000..a4faf22fa4a --- /dev/null +++ b/changelog/13155.doc.rst @@ -0,0 +1 @@ +Clarified how the ``request`` fixture provides indirect parametrization values via ``request.param``. diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index ae64a7c62d5..de668def863 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -370,9 +370,19 @@ test: def test_indirect(fixt): assert len(fixt) == 3 + This can be used, for example, to do more expensive setup at test run time in the fixture, rather than having to run those setup steps at collection time. +.. note:: + + The ``request`` argument used by the fixture is pytest's built-in + :py:class:`FixtureRequest ` fixture. For indirect + parametrization, the value supplied to the test parameter is passed to the + fixture and made available as ``request.param``. + + For more information, see :ref:`fixture-parametrize`. + .. regendoc:wipe Apply indirect on particular arguments