diff --git a/.coveragerc b/.coveragerc
index d39d3d5f02b..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/
@@ -25,6 +28,7 @@ exclude_lines =
^\s*raise NotImplementedError\b
^\s*return NotImplemented\b
^\s*assert False(,|$)
+ ^\s*case unreachable:
^\s*assert_never\(
^\s*if TYPE_CHECKING:
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 9e63bc68cfd..c44ef2d8210 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -25,41 +25,85 @@ jobs:
attestations: write
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
with:
fetch-depth: 0
persist-credentials: false
- name: Build and Check Package
- uses: hynek/build-and-inspect-python-package@b5076c307dc91924a82ad150cdd1533b444d3310
+ uses: hynek/build-and-inspect-python-package@efb823f52190ad02594531168b7a2d5790e66516
with:
attest-build-provenance-github: 'true'
- deploy:
- if: github.repository == 'pytest-dev/pytest'
+ generate-gh-release-notes:
needs: [package]
runs-on: ubuntu-latest
- environment: deploy
timeout-minutes: 30
permissions:
- id-token: write
- contents: write
+ contents: read
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
with:
- persist-credentials: true
+ fetch-depth: 0
+ persist-credentials: false
+
+ - name: Set up Python
+ uses: actions/setup-python@v6
+ with:
+ python-version: "3.13"
+
+ - name: Install tox
+ run: |
+ python -m pip install --upgrade pip
+ pip install --upgrade tox
+
+ - name: Generate release notes
+ env:
+ VERSION: ${{ github.event.inputs.version }}
+ run: |
+ tox -e generate-gh-release-notes -- "$VERSION" gh-release-notes.md
+
+ - name: Upload release notes
+ uses: actions/upload-artifact@v4
+ with:
+ name: release-notes
+ path: gh-release-notes.md
+ retention-days: 1
+ publish-to-pypi:
+ if: github.repository == 'pytest-dev/pytest'
+ # Need generate-gh-release-notes only for ordering.
+ # Don't want to release to PyPI if generating GitHub release notes fails.
+ needs: [package, generate-gh-release-notes]
+ runs-on: ubuntu-latest
+ environment: deploy
+ timeout-minutes: 30
+ permissions:
+ id-token: write
+ steps:
- name: Download Package
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@v6
with:
name: Packages
path: dist
- name: Publish package to PyPI
- uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc
+ uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e
with:
attestations: true
+ push-tag:
+ needs: [publish-to-pypi]
+ runs-on: ubuntu-latest
+ timeout-minutes: 10
+ permissions:
+ contents: write
+ steps:
+ - uses: actions/checkout@v5
+ with:
+ fetch-depth: 0
+ persist-credentials: true
+
- name: Push tag
env:
VERSION: ${{ github.event.inputs.version }}
@@ -69,48 +113,29 @@ jobs:
git tag --annotate --message=v"$VERSION" "$VERSION" ${{ github.sha }}
git push origin "$VERSION"
- release-notes:
-
- # todo: generate the content in the build job
- # the goal being of using a github action script to push the release data
- # after success instead of creating a complete python/tox env
- needs: [deploy]
+ create-github-release:
+ needs: [push-tag, generate-gh-release-notes]
runs-on: ubuntu-latest
- timeout-minutes: 30
+ timeout-minutes: 10
permissions:
contents: write
steps:
- - uses: actions/checkout@v4
- with:
- fetch-depth: 0
- persist-credentials: false
-
- name: Download Package
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@v6
with:
name: Packages
path: dist
- - name: Set up Python
- uses: actions/setup-python@v5
+ - name: Download release notes
+ uses: actions/download-artifact@v6
with:
- python-version: "3.11"
-
- - name: Install tox
- run: |
- python -m pip install --upgrade pip
- pip install --upgrade tox
+ name: release-notes
+ path: .
- - name: Generate release notes
+ - name: Publish GitHub Release
env:
VERSION: ${{ github.event.inputs.version }}
+ GH_REPO: ${{ github.repository }}
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
- sudo apt-get install pandoc
- tox -e generate-gh-release-notes -- "$VERSION" scripts/latest-release-notes.md
-
- - name: Publish GitHub Release
- uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
- with:
- body_path: scripts/latest-release-notes.md
- files: dist/*
- tag_name: ${{ github.event.inputs.version }}
+ gh release create --notes-file gh-release-notes.md --verify-tag "$VERSION" dist/*
diff --git a/.github/workflows/doc-check-links.yml b/.github/workflows/doc-check-links.yml
new file mode 100644
index 00000000000..497ec73500a
--- /dev/null
+++ b/.github/workflows/doc-check-links.yml
@@ -0,0 +1,37 @@
+name: Doc Check Links
+
+on:
+ schedule:
+ # At 00:00 on Sunday.
+ # https://crontab.guru
+ - cron: '0 0 * * 0'
+ workflow_dispatch:
+
+# Set permissions at the job level.
+permissions: {}
+
+jobs:
+ doc-check-links:
+ if: github.repository_owner == 'pytest-dev'
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v5
+ with:
+ fetch-depth: 0
+ persist-credentials: false
+
+ - name: Setup Python
+ uses: actions/setup-python@v6
+ with:
+ python-version: "3.13"
+ cache: pip
+
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install tox
+
+ - name: Run sphinx linkcheck via tox
+ run: tox -e docs-checklinks
diff --git a/.github/workflows/prepare-release-pr.yml b/.github/workflows/prepare-release-pr.yml
index b21ca70cb46..9dcfea7bae5 100644
--- a/.github/workflows/prepare-release-pr.yml
+++ b/.github/workflows/prepare-release-pr.yml
@@ -27,16 +27,16 @@ jobs:
pull-requests: write
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
with:
fetch-depth: 0
# persist-credentials is needed in order for us to push the release branch.
persist-credentials: true
- name: Set up Python
- uses: actions/setup-python@v5
+ uses: actions/setup-python@v6
with:
- python-version: "3.x"
+ python-version: "3.13"
- name: Install dependencies
run: |
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
index 82f9a1f2579..aeac36cea60 100644
--- a/.github/workflows/stale.yml
+++ b/.github/workflows/stale.yml
@@ -10,7 +10,7 @@ jobs:
permissions:
issues: write
steps:
- - uses: actions/stale@v9
+ - uses: actions/stale@v10
with:
debug-only: false
days-before-issue-stale: 14
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 3ecc133878f..4914725f778 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -20,6 +20,8 @@ on:
- reopened # default
- ready_for_review # used in PRs created from the release workflow
+ workflow_dispatch: # allows manual triggering of the workflow
+
env:
PYTEST_ADDOPTS: "--color=yes"
@@ -35,12 +37,12 @@ jobs:
package:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
with:
fetch-depth: 0
persist-credentials: false
- name: Build and Check Package
- uses: hynek/build-and-inspect-python-package@b5076c307dc91924a82ad150cdd1533b444d3310
+ uses: hynek/build-and-inspect-python-package@efb823f52190ad02594531168b7a2d5790e66516
build:
needs: [package]
@@ -54,19 +56,22 @@ jobs:
fail-fast: false
matrix:
name: [
- "windows-py39-unittestextras",
- "windows-py39-pluggy",
- "windows-py39-xdist",
- "windows-py310",
+ "windows-py310-unittest-asynctest",
+ "windows-py310-unittest-twisted24",
+ "windows-py310-unittest-twisted25",
+ "windows-py310-pluggy",
+ "windows-py310-xdist",
"windows-py311",
"windows-py312",
"windows-py313",
"windows-py314",
- "ubuntu-py39-lsof-numpy-pexpect",
- "ubuntu-py39-pluggy",
- "ubuntu-py39-freeze",
- "ubuntu-py39-xdist",
+ "ubuntu-py310-unittest-asynctest",
+ "ubuntu-py310-unittest-twisted24",
+ "ubuntu-py310-unittest-twisted25",
+ "ubuntu-py310-lsof-numpy-pexpect",
+ "ubuntu-py310-pluggy",
+ "ubuntu-py310-freeze",
"ubuntu-py310-xdist",
"ubuntu-py311",
"ubuntu-py312",
@@ -74,7 +79,6 @@ jobs:
"ubuntu-py314",
"ubuntu-pypy3-xdist",
- "macos-py39",
"macos-py310",
"macos-py312",
"macos-py313",
@@ -85,23 +89,32 @@ jobs:
]
include:
- - name: "windows-py39-unittestextras"
- python: "3.9"
+ # Use separate jobs for different unittest flavors (twisted, asynctest) to ensure proper coverage.
+ - name: "windows-py310-unittest-asynctest"
+ python: "3.10"
os: windows-latest
- tox_env: "py39-unittestextras"
+ tox_env: "py310-asynctest"
use_coverage: true
- - name: "windows-py39-pluggy"
- python: "3.9"
+ - name: "windows-py310-unittest-twisted24"
+ python: "3.10"
+ os: windows-latest
+ tox_env: "py310-twisted24"
+ use_coverage: true
+
+ - name: "windows-py310-unittest-twisted25"
+ python: "3.10"
os: windows-latest
- tox_env: "py39-pluggymain-pylib-xdist"
+ tox_env: "py310-twisted25"
+ use_coverage: true
- - name: "windows-py39-xdist"
- python: "3.9"
+ - name: "windows-py310-pluggy"
+ python: "3.10"
os: windows-latest
- tox_env: "py39-xdist"
+ tox_env: "py310-pluggymain-pylib-xdist"
+ xfail: true
- - name: "windows-py310"
+ - name: "windows-py310-xdist"
python: "3.10"
os: windows-latest
tox_env: "py310-xdist"
@@ -120,32 +133,50 @@ jobs:
python: "3.13"
os: windows-latest
tox_env: "py313"
+ xfail: true
- name: "windows-py314"
python: "3.14"
os: windows-latest
tox_env: "py314"
+ use_coverage: true
- - name: "ubuntu-py39-lsof-numpy-pexpect"
- python: "3.9"
+ # Use separate jobs for different unittest flavors (twisted, asynctest) to ensure proper coverage.
+ - name: "ubuntu-py310-unittest-asynctest"
+ python: "3.10"
os: ubuntu-latest
- tox_env: "py39-lsof-numpy-pexpect"
+ tox_env: "py310-asynctest"
use_coverage: true
- - name: "ubuntu-py39-pluggy"
- python: "3.9"
+ - name: "ubuntu-py310-unittest-twisted24"
+ python: "3.10"
os: ubuntu-latest
- tox_env: "py39-pluggymain-pylib-xdist"
+ tox_env: "py310-twisted24"
+ use_coverage: true
- - name: "ubuntu-py39-freeze"
- python: "3.9"
+ - name: "ubuntu-py310-unittest-twisted25"
+ python: "3.10"
os: ubuntu-latest
- tox_env: "py39-freeze"
+ tox_env: "py310-twisted25"
+ use_coverage: true
- - name: "ubuntu-py39-xdist"
- python: "3.9"
+ - name: "ubuntu-py310-lsof-numpy-pexpect"
+ python: "3.10"
os: ubuntu-latest
- tox_env: "py39-xdist"
+ tox_env: "py310-lsof-numpy-pexpect"
+ use_coverage: true
+
+ - name: "ubuntu-py310-pluggy"
+ python: "3.10"
+ os: ubuntu-latest
+ tox_env: "py310-pluggymain-pylib-xdist"
+ xfail: true
+
+ - name: "ubuntu-py310-freeze"
+ python: "3.10"
+ os: ubuntu-latest
+ tox_env: "py310-freeze"
+ xfail: true
- name: "ubuntu-py310-xdist"
python: "3.10"
@@ -169,6 +200,7 @@ jobs:
os: ubuntu-latest
tox_env: "py313-pexpect"
use_coverage: true
+ xfail: true
- name: "ubuntu-py314"
python: "3.14"
@@ -177,21 +209,16 @@ jobs:
use_coverage: true
- name: "ubuntu-pypy3-xdist"
- python: "pypy-3.9"
+ python: "pypy-3.10"
os: ubuntu-latest
tox_env: "pypy3-xdist"
- - name: "macos-py39"
- python: "3.9"
- os: macos-latest
- tox_env: "py39-xdist"
- use_coverage: true
-
- name: "macos-py310"
python: "3.10"
os: macos-latest
tox_env: "py310-xdist"
+ xfail: true
- name: "macos-py312"
python: "3.12"
@@ -202,6 +229,7 @@ jobs:
python: "3.13"
os: macos-latest
tox_env: "py313-xdist"
+ xfail: true
- name: "macos-py314"
python: "3.14"
@@ -215,45 +243,27 @@ jobs:
- name: "doctesting"
- python: "3.9"
+ python: "3.10"
os: ubuntu-latest
tox_env: "doctesting"
use_coverage: true
- continue-on-error: >-
- ${{
- contains(
- fromJSON(
- '[
- "windows-py39-pluggy",
- "windows-py313",
- "ubuntu-py39-pluggy",
- "ubuntu-py39-freeze",
- "ubuntu-py313",
- "macos-py39",
- "macos-py313"
- ]'
- ),
- matrix.name
- )
- && true
- || false
- }}
+ continue-on-error: ${{ matrix.xfail && true || false }}
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
with:
fetch-depth: 0
persist-credentials: false
- name: Download Package
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@v6
with:
name: Packages
path: dist
- name: Set up Python ${{ matrix.python }}
- uses: actions/setup-python@v5
+ uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python }}
check-latest: true
@@ -280,7 +290,7 @@ jobs:
- name: Upload coverage to Codecov
if: "matrix.use_coverage"
- uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24
+ uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7
with:
fail_ci_if_error: false
files: ./coverage.xml
@@ -296,6 +306,6 @@ jobs:
steps:
- name: Decide whether the needed jobs succeeded or failed
- uses: re-actors/alls-green@223e4bb7a751b91f43eda76992bcfbf23b8b0302
+ uses: re-actors/alls-green@2765efec08f0fd63e83ad900f5fd75646be69ff6
with:
jobs: ${{ toJSON(needs) }}
diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml
index c10aefa3a55..b396d6e19d4 100644
--- a/.github/workflows/update-plugin-list.yml
+++ b/.github/workflows/update-plugin-list.yml
@@ -20,16 +20,15 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
with:
fetch-depth: 0
persist-credentials: false
- name: Setup Python
- uses: actions/setup-python@v5
+ uses: actions/setup-python@v6
with:
- python-version: "3.11"
- cache: pip
+ python-version: "3.13"
- name: requests-cache
uses: actions/cache@v4
@@ -38,13 +37,13 @@ jobs:
key: plugins-http-cache-${{ github.run_id }} # Can use time based key as well
restore-keys: plugins-http-cache-
- - name: Install dependencies
+ - name: Install tox
run: |
python -m pip install --upgrade pip
- pip install packaging requests tabulate[widechars] tqdm requests-cache platformdirs
+ pip install --upgrade tox
- name: Update Plugin List
- run: python scripts/update-plugin-list.py
+ run: tox -e update-plugin-list
- name: Create Pull Request
id: pr
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 149f7e6af59..2f9f56256b6 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,22 +1,23 @@
+minimum_pre_commit_version: "4.4.0"
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
- rev: "v0.11.11"
+ rev: "v0.14.3"
hooks:
- - id: ruff
+ - id: ruff-check
args: ["--fix"]
- id: ruff-format
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v5.0.0
+ rev: v6.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- repo: https://github.com/woodruffw/zizmor-pre-commit
- rev: v1.8.0
+ rev: v1.16.2
hooks:
- id: zizmor
- repo: https://github.com/adamchainz/blacken-docs
- rev: 1.19.1
+ rev: 1.20.0
hooks:
- id: blacken-docs
additional_dependencies: [black==24.1.1]
@@ -32,7 +33,7 @@ repos:
hooks:
- id: python-use-type-annotations
- repo: https://github.com/pre-commit/mirrors-mypy
- rev: v1.15.0
+ rev: v1.18.2
hooks:
- id: mypy
files: ^(src/|testing/|scripts/)
@@ -48,7 +49,7 @@ repos:
# on <3.11
- exceptiongroup>=1.0.0rc8
- repo: https://github.com/RobertCraigie/pyright-python
- rev: v1.1.401
+ rev: v1.1.407
hooks:
- id: pyright
files: ^(src/|scripts/)
@@ -66,17 +67,17 @@ repos:
# Manual because passing pyright is a work in progress.
stages: [manual]
- repo: https://github.com/tox-dev/pyproject-fmt
- rev: "v2.6.0"
+ rev: "v2.11.0"
hooks:
- id: pyproject-fmt
# https://pyproject-fmt.readthedocs.io/en/latest/#calculating-max-supported-python-version
additional_dependencies: ["tox>=4.9"]
- repo: https://github.com/asottile/pyupgrade
- rev: v3.20.0
+ rev: v3.21.0
hooks:
- id: pyupgrade
args:
- - "--py39-plus"
+ - "--py310-plus"
# Manual because ruff does what pyupgrade does and the two are not out of sync
# often enough to make launching pyupgrade everytime worth it
stages: [manual]
@@ -92,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
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/AUTHORS b/AUTHORS
index e5b863e71f1..a089ca678f7 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -39,6 +39,7 @@ Andrzej Klajnert
Andrzej Ostrowski
Andy Freeland
Anita Hammer
+Anna Tasiopoulou
Anthon van der Neut
Anthony Shaw
Anthony Sottile
@@ -82,6 +83,7 @@ Carlos Jenkins
Ceridwen
Charles Cloud
Charles Machalow
+Charles-Meldhine Madi Mnemoi (cmnemoi)
Charnjit SiNGH (CCSJ)
Cheuk Ting Ho
Chris Mahoney
@@ -134,6 +136,7 @@ Deysha Rivera
Dheeraj C K
Dhiren Serai
Diego Russo
+Dima Gerasimov
Dmitry Dygalo
Dmitry Pribysh
Dominic Mortlock
@@ -200,6 +203,7 @@ Ilya Konstantinov
Ionuț Turturică
Isaac Virshup
Israel Fruchter
+Israël Hallé
Itxaso Aizpurua
Iwan Briquemont
Jaap Broekhuizen
@@ -225,6 +229,7 @@ Jon Parise
Jon Sonesen
Jonas Obrist
Jordan Guymon
+Jordan Macdonald
Jordan Moldow
Jordan Speicher
Joseph Hunkeler
@@ -250,6 +255,7 @@ Kevin Hierro Carrasco
Kevin J. Foley
Kian Eliasi
Kian-Meng Ang
+Kim Soo
Kodi B. Arfer
Kojo Idrissa
Kostis Anagnostopoulos
@@ -261,6 +267,7 @@ Leonardus Chen
Lev Maximov
Levon Saldamli
Lewis Cowles
+Liam DeVoe
Llandy Riveron Del Risco
Loic Esteve
lovetheguitar
@@ -279,6 +286,7 @@ Marcin Augustynów
Marcin Bachry
Marc Bresson
Marco Gorelli
+Marcos Boger
Mark Abramowitz
Mark Dickinson
Mark Vong
@@ -313,6 +321,7 @@ Mike Hoyle (hoylemd)
Mike Lundy
Milan Lesnek
Miro Hrončok
+Mulat Mekonen
mrbean-bremen
Nathan Goldbaum
Nathan Rousseau
@@ -335,8 +344,10 @@ Oleg Sushchenko
Oleksandr Zavertniev
Olga Matoula
Oliver Bestwalter
+Olivier Grisel
Omar Kohl
Omer Hadari
+Omri Golan
Ondřej Súkup
Oscar Benjamin
Parth Patel
@@ -375,6 +386,7 @@ Reza Mousavi
Raquel Alegre
Ravi Chandra
Reagan Lee
+Reilly Brogan
Rob Arrow
Robert Holt
Roberto Aldera
@@ -393,6 +405,7 @@ Sadra Barikbin
Saiprasad Kale
Samuel Colvin
Samuel Dion-Girardeau
+Samuel Gaist
Samuel Jirovec
Samuel Searles-Bryant
Samuel Therrien (Avasam)
@@ -446,6 +459,7 @@ TJ Bruno
Tobias Diez
Tobias Petersen
Tom Dalton
+Tom Most
Tom Viner
Tomáš Gavenčiak
Tomer Keren
@@ -488,6 +502,7 @@ Yusuke Kadowaki
Yutian Li
Yuval Shimon
Zac Hatfield-Dodds
+Zac Palmer Laporte
Zach Snicker
Zachary Kneupper
Zachary OBrien
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index b79955e1c01..f31c14aec49 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -197,13 +197,13 @@ Short version
#. Follow `PEP-8 `_ for naming.
#. Tests are run using ``tox``::
- tox -e linting,py39
+ tox -e linting,py313
The test environments above are usually enough to cover most cases locally.
#. Write a ``changelog`` entry: ``changelog/2574.bugfix.rst``, use issue id number
and one of ``feature``, ``improvement``, ``bugfix``, ``doc``, ``deprecation``,
- ``breaking``, ``vendor`` or ``trivial`` for the issue type.
+ ``breaking``, ``vendor``, ``packaging``, ``contrib``, or ``misc`` for the issue type.
#. Unless your change is a trivial or a documentation fix (e.g., a typo or reword of a small section) please
@@ -269,24 +269,24 @@ Here is a simple overview, with pytest-specific bits:
#. Run all the tests
- You need to have Python 3.9 or later available in your system. Now
+ You need to have a supported Python version available in your system. Now
running tests is as simple as issuing this command::
- $ tox -e linting,py39
+ $ tox -e linting,py
- This command will run tests via the "tox" tool against Python 3.9
- and also perform "lint" coding-style checks.
+ This command will run tests via the "tox" tool against your default Python
+ version and also perform "lint" coding-style checks.
#. You can now edit your local working copy and run the tests again as necessary. Please follow `PEP-8 `_ for naming.
- You can pass different options to ``tox``. For example, to run tests on Python 3.9 and pass options to pytest
+ 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::
- $ tox -e py39 -- --pdb
+ $ tox -e py313 -- --pdb
- Or to only run tests in a particular test module on Python 3.9::
+ Or to only run tests in a particular test module on Python 3.12::
- $ tox -e py39 -- testing/test_config.py
+ $ tox -e py312 -- testing/test_config.py
When committing, ``pre-commit`` will re-format the files if necessary.
@@ -305,8 +305,9 @@ Here is a simple overview, with pytest-specific bits:
#. Create a new changelog entry in ``changelog``. The file should be named ``..rst``,
where *issueid* is the number of the issue related to the change and *type* is one of
- ``feature``, ``improvement``, ``bugfix``, ``doc``, ``deprecation``, ``breaking``, ``vendor``
- or ``trivial``. You may skip creating the changelog entry if the change doesn't affect the
+ ``feature``, ``improvement``, ``bugfix``, ``doc``, ``deprecation``, ``breaking``, ``vendor``,
+ ``packaging``, ``contrib``, or ``misc``.
+ You may skip creating the changelog entry if the change doesn't affect the
documented behaviour of pytest.
#. Add yourself to ``AUTHORS`` file if not there yet, in alphabetical order.
diff --git a/README.rst b/README.rst
index 091afc363da..3bc5f06fc81 100644
--- a/README.rst
+++ b/README.rst
@@ -79,7 +79,7 @@ To execute it::
========================== 1 failed in 0.04 seconds ===========================
-Due to ``pytest``'s detailed assertion introspection, only plain ``assert`` statements are used. See `getting-started `_ for more examples.
+Thanks to ``pytest``'s detailed assertion introspection, you can simply use plain ``assert`` statements. See `getting-started `_ for more examples.
Features
@@ -97,7 +97,7 @@ Features
- Can run `unittest `_ (or trial)
test suites out of the box
-- Python 3.9+ or PyPy3
+- Python 3.10+ or PyPy3
- Rich plugin architecture, with over 1300+ `external plugins `_ and thriving community
diff --git a/RELEASING.rst b/RELEASING.rst
index 0ca63ee4fbf..79b4e2f764d 100644
--- a/RELEASING.rst
+++ b/RELEASING.rst
@@ -133,7 +133,7 @@ Releasing
Both automatic and manual processes described above follow the same steps from this point onward.
-#. After all tests pass and the PR has been approved, trigger the ``deploy`` job
+#. After all tests pass and the PR has been approved, trigger the ``deploy`` workflow
in https://github.com/pytest-dev/pytest/actions/workflows/deploy.yml, using the ``release-MAJOR.MINOR.PATCH`` branch
as source.
@@ -168,9 +168,7 @@ Both automatic and manual processes described above follow the same steps from t
To the following mailing lists:
- * pytest-dev@python.org (all releases)
- * python-announce-list@python.org (all releases)
- * testing-in-python@lists.idyll.org (only major/minor releases)
+ * python-announce-list@python.org
And announce it with the ``#pytest`` hashtag on:
diff --git a/changelog/10224.improvement.rst b/changelog/10224.improvement.rst
deleted file mode 100644
index 93afe9e2c1e..00000000000
--- a/changelog/10224.improvement.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-pytest's ``short`` and ``long`` traceback styles (:ref:`how-to-modifying-python-tb-printing`)
-now have partial :pep:`657` support and will show specific code segments in the
-traceback.
-
-.. code-block:: pytest
-
- ================================= FAILURES =================================
- _______________________ test_gets_correct_tracebacks _______________________
-
- test_tracebacks.py:12: in test_gets_correct_tracebacks
- assert manhattan_distance(p1, p2) == 1
- ^^^^^^^^^^^^^^^^^^^^^^^^^^
- test_tracebacks.py:6: in manhattan_distance
- return abs(point_1.x - point_2.x) + abs(point_1.y - point_2.y)
- ^^^^^^^^^
- E AttributeError: 'NoneType' object has no attribute 'x'
-
--- by :user:`ammaraskar`
diff --git a/changelog/10404.bugfix.rst b/changelog/10404.bugfix.rst
deleted file mode 100644
index 4c98ea03d64..00000000000
--- a/changelog/10404.bugfix.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-Apply filterwarnings from config/cli as soon as possible, and revert them as late as possible
-so that warnings as errors are collected throughout the pytest run and before the
-unraisable and threadexcept hooks are removed.
-
-This allows very late warnings and unraisable/threadexcept exceptions to fail the test suite.
-
-This also changes the warning that the lsof plugin issues from PytestWarning to the new warning PytestFDWarning so it can be more easily filtered.
diff --git a/changelog/10839.deprecation.rst b/changelog/10839.deprecation.rst
deleted file mode 100644
index a3e2cbf51d0..00000000000
--- a/changelog/10839.deprecation.rst
+++ /dev/null
@@ -1 +0,0 @@
-Requesting an asynchronous fixture without a `pytest_fixture_setup` hook that resolves it will now give a DeprecationWarning. This most commonly happens if a sync test requests an async fixture. This should have no effect on a majority of users with async tests or fixtures using async pytest plugins, but may affect non-standard hook setups or ``autouse=True``. For guidance on how to work around this warning see :ref:`sync-test-async-fixture`.
diff --git a/changelog/11067.bugfix.rst b/changelog/11067.bugfix.rst
deleted file mode 100644
index 4e3cb8e7dd7..00000000000
--- a/changelog/11067.bugfix.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-The test report is now consistent regardless if the test xfailed via :ref:`pytest.mark.xfail ` or :func:`pytest.fail`.
-
-Previously, *xfailed* tests via the marker would have the string ``"reason: "`` prefixed to the message, while those *xfailed* via the function did not. The prefix has been removed.
diff --git a/changelog/11118.improvement.rst b/changelog/11118.improvement.rst
deleted file mode 100644
index 4760dbe9d64..00000000000
--- a/changelog/11118.improvement.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-Now :confval:`pythonpath` configures `$PYTHONPATH` earlier than before during the initialization process, which now also affects plugins loaded via the `-p` command-line option.
-
--- by :user:`millerdev`
diff --git a/changelog/11372.breaking.rst b/changelog/11372.breaking.rst
deleted file mode 100644
index f4b5c3c6f6b..00000000000
--- a/changelog/11372.breaking.rst
+++ /dev/null
@@ -1 +0,0 @@
-Async tests will now fail, instead of warning+skipping, if you don't have any suitable plugin installed.
diff --git a/changelog/11381.improvement.rst b/changelog/11381.improvement.rst
deleted file mode 100644
index 74c080cc188..00000000000
--- a/changelog/11381.improvement.rst
+++ /dev/null
@@ -1,17 +0,0 @@
-The ``type`` parameter of the ``parser.addini`` method now accepts `"int"` and ``"float"`` parameters, facilitating the parsing of configuration values in the configuration file.
-
-Example:
-
-.. code-block:: python
-
- def pytest_addoption(parser):
- parser.addini("int_value", type="int", default=2, help="my int value")
- parser.addini("float_value", type="float", default=4.2, help="my float value")
-
-The `pytest.ini` file:
-
-.. code-block:: ini
-
- [pytest]
- int_value = 3
- float_value = 5.4
diff --git a/changelog/11525.improvement.rst b/changelog/11525.improvement.rst
deleted file mode 100644
index 1935ce59343..00000000000
--- a/changelog/11525.improvement.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-Fixtures are now clearly represented in the output as a "fixture object", not as a normal function as before, making it easy for beginners to catch mistakes such as referencing a fixture declared in the same module but not requested in the test function.
-
--- by :user:`the-compiler` and :user:`glyphack`
diff --git a/changelog/11538.feature.rst b/changelog/11538.feature.rst
deleted file mode 100644
index d6473b8fe73..00000000000
--- a/changelog/11538.feature.rst
+++ /dev/null
@@ -1 +0,0 @@
-Added :class:`pytest.RaisesGroup` as an equivalent to :func:`pytest.raises` for expecting :exc:`ExceptionGroup`. Also adds :class:`pytest.RaisesExc` which is now the logic behind :func:`pytest.raises` and used as parameter to :class:`pytest.RaisesGroup`. ``RaisesGroup`` includes the ability to specify multiple different expected exceptions, the structure of nested exception groups, and flags for emulating :ref:`except* `. See :ref:`assert-matching-exception-groups` and docstrings for more information.
diff --git a/changelog/12008.bugfix.rst b/changelog/12008.bugfix.rst
deleted file mode 100644
index b9680b89236..00000000000
--- a/changelog/12008.bugfix.rst
+++ /dev/null
@@ -1 +0,0 @@
-In :pr:`11220`, an unintended change in reordering was introduced by changing the way indices were assigned to direct params. More specifically, before that change, the indices of direct params to metafunc's callspecs were assigned after all parametrizations took place. Now, that change is reverted.
diff --git a/changelog/12017.contrib.rst b/changelog/12017.contrib.rst
deleted file mode 100644
index ec1861893b3..00000000000
--- a/changelog/12017.contrib.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-Mixed internal improvements:
-
-* Migrate formatting to f-strings in some tests.
-* Use type-safe constructs in JUnitXML tests.
-* Moved`` MockTiming`` into ``_pytest.timing``.
-
--- by :user:`RonnyPfannschmidt`
diff --git a/changelog/12081.feature.rst b/changelog/12081.feature.rst
deleted file mode 100644
index 6538fbf30f8..00000000000
--- a/changelog/12081.feature.rst
+++ /dev/null
@@ -1 +0,0 @@
-Added :fixture:`capteesys` to capture AND pass output to next handler set by ``--capture=``.
diff --git a/changelog/12346.breaking.rst b/changelog/12346.breaking.rst
deleted file mode 100644
index 7013cf734c8..00000000000
--- a/changelog/12346.breaking.rst
+++ /dev/null
@@ -1 +0,0 @@
-Tests will now fail, instead of raising a warning, if they return any value other than None.
diff --git a/changelog/12426.improvement.rst b/changelog/12426.improvement.rst
deleted file mode 100644
index 0da1f838aea..00000000000
--- a/changelog/12426.improvement.rst
+++ /dev/null
@@ -1 +0,0 @@
-A warning is now issued when :ref:`pytest.mark.usefixtures ref` is used without specifying any fixtures. Previously, empty usefixtures markers were silently ignored.
diff --git a/changelog/12504.feature.rst b/changelog/12504.feature.rst
deleted file mode 100644
index d72b97958c2..00000000000
--- a/changelog/12504.feature.rst
+++ /dev/null
@@ -1 +0,0 @@
-:func:`pytest.mark.xfail` now accepts :class:`pytest.RaisesGroup` for the ``raises`` parameter when you expect an exception group. You can also pass a :class:`pytest.RaisesExc` if you e.g. want to make use of the ``check`` parameter.
diff --git a/changelog/12535.doc.rst b/changelog/12535.doc.rst
deleted file mode 100644
index d43c1c822ea..00000000000
--- a/changelog/12535.doc.rst
+++ /dev/null
@@ -1,4 +0,0 @@
-`This
-example`
-showed ``print`` statements that do not exactly reflect what the
-different branches actually do. The fix makes the example more precise.
diff --git a/changelog/12647.contrib.rst b/changelog/12647.contrib.rst
deleted file mode 100644
index 1d7a3181778..00000000000
--- a/changelog/12647.contrib.rst
+++ /dev/null
@@ -1 +0,0 @@
-Fixed running the test suite with the ``hypothesis`` pytest plugin.
diff --git a/changelog/12707.improvement.rst b/changelog/12707.improvement.rst
deleted file mode 100644
index 4684b6561c8..00000000000
--- a/changelog/12707.improvement.rst
+++ /dev/null
@@ -1 +0,0 @@
-Exception chains can be navigated when dropped into Pdb in Python 3.13+.
diff --git a/changelog/12713.feature.rst b/changelog/12713.feature.rst
deleted file mode 100644
index 90867b87eae..00000000000
--- a/changelog/12713.feature.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-New `--force-short-summary` option to force condensed summary output regardless of verbosity level.
-
-This lets users still see condensed summary output of failures for quick reference in log files from job outputs, being especially useful if non-condensed output is very verbose.
diff --git a/changelog/12736.improvement.rst b/changelog/12736.improvement.rst
deleted file mode 100644
index 5fdb14e2ef5..00000000000
--- a/changelog/12736.improvement.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-Added a new attribute `name` with the fixed value `"pytest tests"` to the root tag `testsuites` of the junit-xml generated by pytest.
-
-This attribute is part of many junit-xml specifications and is even part of the `junit-10.xsd` specification that pytest's implementation is based on.
diff --git a/changelog/12749.feature.rst b/changelog/12749.feature.rst
deleted file mode 100644
index c3b7ca5d321..00000000000
--- a/changelog/12749.feature.rst
+++ /dev/null
@@ -1,21 +0,0 @@
-pytest traditionally collects classes/functions in the test module namespace even if they are imported from another file.
-
-For example:
-
-.. code-block:: python
-
- # contents of src/domain.py
- class Testament: ...
-
-
- # contents of tests/test_testament.py
- from domain import Testament
-
-
- def test_testament(): ...
-
-In this scenario with the default options, pytest will collect the class `Testament` from `tests/test_testament.py` because it starts with `Test`, even though in this case it is a production class being imported in the test module namespace.
-
-This behavior can now be prevented by setting the new :confval:`collect_imported_tests` configuration option to ``false``, which will make pytest collect classes/functions from test files **only** if they are defined in that file.
-
--- by :user:`FreerGit`
diff --git a/changelog/12765.feature.rst b/changelog/12765.feature.rst
deleted file mode 100644
index 193c75621f7..00000000000
--- a/changelog/12765.feature.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-Thresholds to trigger snippet truncation can now be set with :confval:`truncation_limit_lines` and :confval:`truncation_limit_chars`.
-
-See :ref:`truncation-params` for more information.
diff --git a/changelog/12863.bugfix.rst b/changelog/12863.bugfix.rst
deleted file mode 100644
index 0b1c397a08e..00000000000
--- a/changelog/12863.bugfix.rst
+++ /dev/null
@@ -1 +0,0 @@
-Fix applying markers, including :ref:`pytest.mark.parametrize ` when placed above `@staticmethod` or `@classmethod`.
diff --git a/changelog/12874.breaking.rst b/changelog/12874.breaking.rst
deleted file mode 100644
index a442586eeb5..00000000000
--- a/changelog/12874.breaking.rst
+++ /dev/null
@@ -1 +0,0 @@
-We dropped support for Python 3.8 following its end of life (2024-10-07).
diff --git a/changelog/12929.bugfix.rst b/changelog/12929.bugfix.rst
deleted file mode 100644
index fcf490d83e2..00000000000
--- a/changelog/12929.bugfix.rst
+++ /dev/null
@@ -1 +0,0 @@
-Handle StopIteration from test cases, setup and teardown correctly.
diff --git a/changelog/12938.bugfix.rst b/changelog/12938.bugfix.rst
deleted file mode 100644
index d54d73bdbf5..00000000000
--- a/changelog/12938.bugfix.rst
+++ /dev/null
@@ -1 +0,0 @@
-Fixed ``--durations-min`` argument not respected if ``-vv`` is used.
diff --git a/changelog/12943.improvement.rst b/changelog/12943.improvement.rst
deleted file mode 100644
index eb8ac63650a..00000000000
--- a/changelog/12943.improvement.rst
+++ /dev/null
@@ -1 +0,0 @@
-If a test fails with an exceptiongroup with a single exception, the contained exception will now be displayed in the short test summary info.
diff --git a/changelog/12946.bugfix.rst b/changelog/12946.bugfix.rst
deleted file mode 100644
index b11da09e7ae..00000000000
--- a/changelog/12946.bugfix.rst
+++ /dev/null
@@ -1 +0,0 @@
-Fixed missing help for :mod:`pdb` commands wrapped by pytest -- by :user:`adamchainz`.
diff --git a/changelog/12958.improvement.rst b/changelog/12958.improvement.rst
deleted file mode 100644
index ee8dc8c0710..00000000000
--- a/changelog/12958.improvement.rst
+++ /dev/null
@@ -1,9 +0,0 @@
-A number of :ref:`unraisable ` enhancements:
-
-* Set the unraisable hook as early as possible and unset it as late as possible, to collect the most possible number of unraisable exceptions.
-* Call the garbage collector just before unsetting the unraisable hook, to collect any straggling exceptions.
-* Collect multiple unraisable exceptions per test phase.
-* Report the :mod:`tracemalloc` allocation traceback (if available).
-* Avoid using a generator based hook to allow handling :class:`StopIteration` in test failures.
-* Report the unraisable exception as the cause of the :class:`pytest.PytestUnraisableExceptionWarning` exception if raised.
-* Compute the ``repr`` of the unraisable object in the unraisable hook so you get the latest information if available, and should help with resurrection of the object.
diff --git a/changelog/12960.breaking.rst b/changelog/12960.breaking.rst
deleted file mode 100644
index 3ab87e6fe23..00000000000
--- a/changelog/12960.breaking.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-Test functions containing a yield now cause an explicit error. They have not been run since pytest 4.0, and were previously marked as an expected failure and deprecation warning.
-
-See :ref:`the docs ` for more information.
diff --git a/changelog/12981.bugfix.rst b/changelog/12981.bugfix.rst
deleted file mode 100644
index 5fc8e29656f..00000000000
--- a/changelog/12981.bugfix.rst
+++ /dev/null
@@ -1 +0,0 @@
-Prevent exceptions in :func:`pytest.Config.add_cleanup` callbacks preventing further cleanups.
diff --git a/changelog/13010.improvement.rst b/changelog/13010.improvement.rst
deleted file mode 100644
index d6b814f090e..00000000000
--- a/changelog/13010.improvement.rst
+++ /dev/null
@@ -1 +0,0 @@
-:func:`pytest.approx` now can compare collections that contain numbers and non-numbers mixed.
diff --git a/changelog/13016.improvement.rst b/changelog/13016.improvement.rst
deleted file mode 100644
index 634672ab69b..00000000000
--- a/changelog/13016.improvement.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-A number of :ref:`threadexception ` enhancements:
-
-* Set the excepthook as early as possible and unset it as late as possible, to collect the most possible number of unhandled exceptions from threads.
-* Collect multiple thread exceptions per test phase.
-* Report the :mod:`tracemalloc` allocation traceback (if available).
-* Avoid using a generator based hook to allow handling :class:`StopIteration` in test failures.
-* Report the thread exception as the cause of the :class:`pytest.PytestUnhandledThreadExceptionWarning` exception if raised.
-* Extract the ``name`` of the thread object in the excepthook which should help with resurrection of the thread.
diff --git a/changelog/13031.improvement.rst b/changelog/13031.improvement.rst
deleted file mode 100644
index c6c64c4673a..00000000000
--- a/changelog/13031.improvement.rst
+++ /dev/null
@@ -1 +0,0 @@
-An empty parameter set as in ``pytest.mark.parametrize([], ids=idfunc)`` will no longer trigger a call to ``idfunc`` with internal objects.
diff --git a/changelog/13047.bugfix.rst b/changelog/13047.bugfix.rst
deleted file mode 100644
index 399e860505c..00000000000
--- a/changelog/13047.bugfix.rst
+++ /dev/null
@@ -1,17 +0,0 @@
-Restore :func:`pytest.approx` handling of equality checks between `bool` and `numpy.bool_` types.
-
-Comparing `bool` and `numpy.bool_` using :func:`pytest.approx` accidentally changed in version `8.3.4` and `8.3.5` to no longer match:
-
-.. code-block:: pycon
-
- >>> import numpy as np
- >>> from pytest import approx
- >>> [np.True_, np.True_] == pytest.approx([True, True])
- False
-
-This has now been fixed:
-
-.. code-block:: pycon
-
- >>> [np.True_, np.True_] == pytest.approx([True, True])
- True
diff --git a/changelog/13115.improvement.rst b/changelog/13115.improvement.rst
deleted file mode 100644
index 9ac45820917..00000000000
--- a/changelog/13115.improvement.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-Allows supplying ``ExceptionGroup[Exception]`` and ``BaseExceptionGroup[BaseException]`` to ``pytest.raises`` to keep full typing on :class:`ExceptionInfo `:
-
-.. code-block:: python
-
- with pytest.raises(ExceptionGroup[Exception]) as exc_info:
- some_function()
-
-Parametrizing with other exception types remains an error - we do not check the types of child exceptions and thus do not permit code that might look like we do.
diff --git a/changelog/13119.bugfix.rst b/changelog/13119.bugfix.rst
deleted file mode 100644
index b7e56af9bb8..00000000000
--- a/changelog/13119.bugfix.rst
+++ /dev/null
@@ -1 +0,0 @@
-Improved handling of invalid regex patterns for filter warnings by providing a clear error message.
diff --git a/changelog/13122.improvement.rst b/changelog/13122.improvement.rst
deleted file mode 100644
index c302713b320..00000000000
--- a/changelog/13122.improvement.rst
+++ /dev/null
@@ -1,15 +0,0 @@
-The ``--stepwise`` mode received a number of improvements:
-
-* It no longer forgets the last failed test in case pytest is executed later without the flag.
-
- This enables the following workflow:
-
- 1. Execute pytest with ``--stepwise``, pytest then stops at the first failing test;
- 2. Iteratively update the code and run the test in isolation, without the ``--stepwise`` flag (for example in an IDE), until it is fixed.
- 3. Execute pytest with ``--stepwise`` again and pytest will continue from the previously failed test, and if it passes, continue on to the next tests.
-
- Previously, at step 3, pytest would start from the beginning, forgetting the previously failed test.
-
- This change however might cause issues if the ``--stepwise`` mode is used far apart in time, as the state might get stale, so the internal state will be reset automatically in case the test suite changes (for now only the number of tests are considered for this, we might change/improve this on the future).
-
-* New ``--stepwise-reset``/``--sw-reset`` flag, allowing the user to explicitly reset the stepwise state and restart the workflow from the beginning.
diff --git a/changelog/13125.feature.rst b/changelog/13125.feature.rst
deleted file mode 100644
index 0c7d66c1169..00000000000
--- a/changelog/13125.feature.rst
+++ /dev/null
@@ -1 +0,0 @@
-:confval:`console_output_style` now supports ``times`` to show execution time of each test.
diff --git a/changelog/13175.bugfix.rst b/changelog/13175.bugfix.rst
deleted file mode 100644
index bdbb72b41e1..00000000000
--- a/changelog/13175.bugfix.rst
+++ /dev/null
@@ -1 +0,0 @@
-The diff is now also highlighted correctly when comparing two strings.
diff --git a/changelog/13192.feature.1.rst b/changelog/13192.feature.1.rst
deleted file mode 100644
index 71fb06f7d70..00000000000
--- a/changelog/13192.feature.1.rst
+++ /dev/null
@@ -1 +0,0 @@
-:func:`pytest.raises` will now print a helpful string diff if matching fails and the match parameter has ``^`` and ``$`` and is otherwise escaped.
diff --git a/changelog/13192.feature.2.rst b/changelog/13192.feature.2.rst
deleted file mode 100644
index 0ffa0e1496a..00000000000
--- a/changelog/13192.feature.2.rst
+++ /dev/null
@@ -1 +0,0 @@
-You can now pass :func:`with pytest.raises(check=fn): `, where ``fn`` is a function which takes a raised exception and returns a boolean. The ``raises`` fails if no exception was raised (as usual), passes if an exception is raised and ``fn`` returns ``True`` (as well as ``match`` and the type matching, if specified, which are checked before), and propagates the exception if ``fn`` returns ``False`` (which likely also fails the test).
diff --git a/changelog/13192.feature.rst b/changelog/13192.feature.rst
deleted file mode 100644
index 97f31ce233c..00000000000
--- a/changelog/13192.feature.rst
+++ /dev/null
@@ -1 +0,0 @@
-:func:`pytest.raises` will now raise a warning when passing an empty string to ``match``, as this will match against any value. Use ``match="^$"`` if you want to check that an exception has no message.
diff --git a/changelog/13218.doc.rst b/changelog/13218.doc.rst
deleted file mode 100644
index 907a817e895..00000000000
--- a/changelog/13218.doc.rst
+++ /dev/null
@@ -1 +0,0 @@
-Pointed out in the :func:`pytest.approx` documentation that it considers booleans unequal to numeric zero or one.
diff --git a/changelog/13221.doc.rst b/changelog/13221.doc.rst
deleted file mode 100644
index cfd35f821b4..00000000000
--- a/changelog/13221.doc.rst
+++ /dev/null
@@ -1 +0,0 @@
-Improved grouping of CLI options in the ``--help`` output.
diff --git a/changelog/13228.feature.rst b/changelog/13228.feature.rst
deleted file mode 100644
index c5d84182313..00000000000
--- a/changelog/13228.feature.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-:ref:`hidden-param` can now be used in ``id`` of :func:`pytest.param` or in
-``ids`` of :py:func:`Metafunc.parametrize `.
-It hides the parameter set from the test name.
diff --git a/changelog/13248.bugfix.rst b/changelog/13248.bugfix.rst
deleted file mode 100644
index 2ebb102fd07..00000000000
--- a/changelog/13248.bugfix.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Fixed an issue where passing a ``scope`` in :py:func:`Metafunc.parametrize ` with ``indirect=True``
-could result in other fixtures being unable to depend on the parametrized fixture.
diff --git a/changelog/13253.feature.rst b/changelog/13253.feature.rst
deleted file mode 100644
index e497c207223..00000000000
--- a/changelog/13253.feature.rst
+++ /dev/null
@@ -1 +0,0 @@
-New flag: :ref:`--disable-plugin-autoload ` which works as an alternative to :envvar:`PYTEST_DISABLE_PLUGIN_AUTOLOAD` when setting environment variables is inconvenient; and allows setting it in config files with :confval:`addopts`.
diff --git a/changelog/13291.bugfix.rst b/changelog/13291.bugfix.rst
deleted file mode 100644
index 03ce06b697a..00000000000
--- a/changelog/13291.bugfix.rst
+++ /dev/null
@@ -1 +0,0 @@
-Fixed ``repr`` of ``attrs`` objects in assertion failure messages when using ``attrs>=25.2``.
diff --git a/changelog/13308.improvement.rst b/changelog/13308.improvement.rst
deleted file mode 100644
index 70018c66d59..00000000000
--- a/changelog/13308.improvement.rst
+++ /dev/null
@@ -1 +0,0 @@
-Added official support for Python 3.14.
diff --git a/changelog/13312.bugfix.rst b/changelog/13312.bugfix.rst
deleted file mode 100644
index 62ad36879f5..00000000000
--- a/changelog/13312.bugfix.rst
+++ /dev/null
@@ -1 +0,0 @@
-Fixed a possible ``KeyError`` crash on PyPy during collection of tests involving higher-scoped parameters.
diff --git a/changelog/13317.packaging.rst b/changelog/13317.packaging.rst
deleted file mode 100644
index 94171cb1ef3..00000000000
--- a/changelog/13317.packaging.rst
+++ /dev/null
@@ -1,4 +0,0 @@
-Specified minimum allowed versions of ``colorama``, ``iniconfig``,
-and ``packaging``; and bumped the minimum allowed version
-of ``exceptiongroup`` for ``python_version<'3.11'`` from a release
-candidate to a full release.
diff --git a/changelog/13345.bugfix.rst b/changelog/13345.bugfix.rst
deleted file mode 100644
index 5010888aa08..00000000000
--- a/changelog/13345.bugfix.rst
+++ /dev/null
@@ -1 +0,0 @@
-Fix type hints for :attr:`pytest.TestReport.when` and :attr:`pytest.TestReport.location`.
diff --git a/changelog/13377.bugfix.rst b/changelog/13377.bugfix.rst
deleted file mode 100644
index 15755481f7f..00000000000
--- a/changelog/13377.bugfix.rst
+++ /dev/null
@@ -1,12 +0,0 @@
-Fixed handling of test methods with positional-only parameter syntax.
-
-Now, methods are supported that formally define ``self`` as positional-only
-and/or fixture parameters as keyword-only, e.g.:
-
-.. code-block:: python
-
- class TestClass:
-
- def test_method(self, /, *, fixture): ...
-
-Before, this caused an internal error in pytest.
diff --git a/changelog/13380.improvement.rst b/changelog/13380.improvement.rst
deleted file mode 100644
index 51f374fbf01..00000000000
--- a/changelog/13380.improvement.rst
+++ /dev/null
@@ -1 +0,0 @@
-Fix :class:`ExceptionGroup` traceback filtering to exclude pytest internals.
diff --git a/changelog/13384.bugfix.rst b/changelog/13384.bugfix.rst
deleted file mode 100644
index e93d01dcab0..00000000000
--- a/changelog/13384.bugfix.rst
+++ /dev/null
@@ -1 +0,0 @@
-Fixed an issue where pytest could report negative durations.
diff --git a/changelog/13415.improvement.rst b/changelog/13415.improvement.rst
deleted file mode 100644
index 61667f15c7b..00000000000
--- a/changelog/13415.improvement.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-The author metadata of the BibTex example is now correctly formatted with last names following first names.
-An example of BibLaTex has been added.
-BibTex and BibLaTex examples now clearly indicate that what is cited is software.
-
--- by :user:`willynilly`
diff --git a/changelog/13420.bugfix.rst b/changelog/13420.bugfix.rst
deleted file mode 100644
index 02f7372a759..00000000000
--- a/changelog/13420.bugfix.rst
+++ /dev/null
@@ -1 +0,0 @@
-Added ``lru_cache`` to ``nodes._check_initialpaths_for_relpath``.
diff --git a/changelog/13420.improvement.rst b/changelog/13420.improvement.rst
deleted file mode 100644
index 54fe50a72b0..00000000000
--- a/changelog/13420.improvement.rst
+++ /dev/null
@@ -1 +0,0 @@
-Improved test collection performance by optimizing path resolution used in ``FSCollector``.
diff --git a/changelog/13457.improvement.rst b/changelog/13457.improvement.rst
deleted file mode 100644
index 3937384b322..00000000000
--- a/changelog/13457.improvement.rst
+++ /dev/null
@@ -1 +0,0 @@
-The error message about duplicate parametrization no longer displays an internal stack trace.
diff --git a/changelog/4112.improvement.rst b/changelog/4112.improvement.rst
deleted file mode 100644
index 426b87ffa19..00000000000
--- a/changelog/4112.improvement.rst
+++ /dev/null
@@ -1 +0,0 @@
-Using :ref:`pytest.mark.usefixtures ` on :func:`pytest.param` now produces an error instead of silently doing nothing.
diff --git a/changelog/5473.improvement.rst b/changelog/5473.improvement.rst
deleted file mode 100644
index 1b9ab006d49..00000000000
--- a/changelog/5473.improvement.rst
+++ /dev/null
@@ -1 +0,0 @@
-Replace `:` with `;` in the assertion rewrite warning message so it can be filtered using standard Python warning filters before calling :func:`pytest.main`.
diff --git a/changelog/6649.doc.rst b/changelog/6649.doc.rst
deleted file mode 100644
index cf5bb781b87..00000000000
--- a/changelog/6649.doc.rst
+++ /dev/null
@@ -1 +0,0 @@
-Added :class:`~pytest.TerminalReporter` to the :ref:`api-reference` documentation page.
diff --git a/changelog/6649.misc.rst b/changelog/6649.misc.rst
deleted file mode 100644
index cec8c3f4506..00000000000
--- a/changelog/6649.misc.rst
+++ /dev/null
@@ -1 +0,0 @@
-Added :class:`~pytest.TerminalReporter` to the public pytest API, as it is part of the signature of the :hook:`pytest_terminal_summary` hook.
diff --git a/changelog/6985.improvement.rst b/changelog/6985.improvement.rst
deleted file mode 100644
index 34ee8edc77d..00000000000
--- a/changelog/6985.improvement.rst
+++ /dev/null
@@ -1,21 +0,0 @@
-Improved :func:`pytest.approx` to enhance the readability of value ranges and tolerances between 0.001 and 1000.
- * The `repr` method now provides clearer output for values within those ranges, making it easier to interpret the results.
- * Previously, the output for those ranges of values and tolerances was displayed in scientific notation (e.g., `42 ± 1.0e+00`). The updated method now presents the tolerance as a decimal for better readability (e.g., `42 ± 1`).
-
- Example:
-
- **Previous Output:**
-
- .. code-block:: console
-
- >>> pytest.approx(42, abs=1)
- 42 ± 1.0e+00
-
- **Current Output:**
-
- .. code-block:: console
-
- >>> pytest.approx(42, abs=1)
- 42 ± 1
-
- -- by :user:`fazeelghafoor`
diff --git a/changelog/7683.improvement.rst b/changelog/7683.improvement.rst
deleted file mode 100644
index 311abe4df93..00000000000
--- a/changelog/7683.improvement.rst
+++ /dev/null
@@ -1 +0,0 @@
-The formerly optional ``pygments`` dependency is now required, causing output always to be source-highlighted (unless disabled via the ``--code-highlight=no`` CLI option).
diff --git a/changelog/8612.doc.rst b/changelog/8612.doc.rst
deleted file mode 100644
index 6ab4102ace4..00000000000
--- a/changelog/8612.doc.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-Add a recipe for handling abstract test classes in the documentation.
-
-A new example has been added to the documentation to demonstrate how to use a mixin class to handle abstract
-test classes without manually setting the ``__test__`` attribute for subclasses.
-This ensures that subclasses of abstract test classes are automatically collected by pytest.
diff --git a/changelog/9037.bugfix.rst b/changelog/9037.bugfix.rst
deleted file mode 100644
index 5367452337e..00000000000
--- a/changelog/9037.bugfix.rst
+++ /dev/null
@@ -1 +0,0 @@
-Honor :confval:`disable_test_id_escaping_and_forfeit_all_rights_to_community_support` when escaping ids in parametrized tests.
diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst
index 51edc964a0c..b92b8d4a56b 100644
--- a/doc/en/announce/index.rst
+++ b/doc/en/announce/index.rst
@@ -6,6 +6,12 @@ Release announcements
:maxdepth: 2
+ release-9.0.2
+ release-9.0.1
+ release-9.0.0
+ release-8.4.2
+ release-8.4.1
+ release-8.4.0
release-8.3.5
release-8.3.4
release-8.3.3
diff --git a/doc/en/announce/release-8.4.0.rst b/doc/en/announce/release-8.4.0.rst
new file mode 100644
index 00000000000..65e80a55919
--- /dev/null
+++ b/doc/en/announce/release-8.4.0.rst
@@ -0,0 +1,106 @@
+pytest-8.4.0
+=======================================
+
+The pytest team is proud to announce the 8.4.0 release!
+
+This release contains new features, improvements, and bug fixes,
+the full list of changes is available in the changelog:
+
+ 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:
+
+* Adam Johnson
+* Ammar Askar
+* Andrew Pikul
+* Andy Freeland
+* Anthony Sottile
+* Anton Zhilin
+* Arpit Gupta
+* Ashley Whetter
+* Avasam
+* Bahram Farahmand
+* Brigitta Sipőcz
+* Bruno Oliveira
+* Callum Scott
+* Christian Clauss
+* Christopher Head
+* Daara
+* Daniel Miller
+* Deysha Rivera
+* Emil Hjelm
+* Eugene Mwangi
+* Florian Bruhin
+* Frank Hoffmann
+* GTowers1
+* Guillaume Gauvrit
+* Gupta Arpit
+* Harmin Parra Rueda
+* Jakob van Santen
+* Jason N. White
+* Jiajun Xu
+* John Litborn
+* Julian Valentin
+* JulianJvn
+* Kenny Y
+* Leonardus Chen
+* Marcelo Duarte Trevisani
+* Marcin Augustynów
+* Natalia Mokeeva
+* Nathan Rousseau
+* Nauman Ahmed
+* Nick Murphy
+* Oleksandr Zavertniev
+* Pavel Zhukov
+* Peter Gessler
+* Pierre Sassoulas
+* Pradeep Kumar
+* Ran Benita
+* Reagan Lee
+* Rob Arrow
+* Ronny Pfannschmidt
+* Sadra Barikbin
+* Sam Bull
+* Samuel Bronson
+* Sashko
+* Serge Smertin
+* Shaygan Hooshyari
+* Stefaan Lippens
+* Stefan Zimmermann
+* Stephen McDowell
+* Sviatoslav Sydorenko
+* Sviatoslav Sydorenko (Святослав Сидоренко)
+* Thomas Grainger
+* TobiMcNamobi
+* Tobias Alex-Petersen
+* Tony Narlock
+* Vincent (Wen Yu) Ge
+* Virendra Patil
+* Will Riley
+* Yann Dirson
+* Zac Hatfield-Dodds
+* delta87
+* dongfangtianyu
+* eitanwass
+* fazeelghafoor
+* ikappaki
+* jakkdl
+* maugu
+* moajo
+* mwychung
+* polkapolka
+* suspe
+* sven
+* 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко)
+
+
+Happy testing,
+The pytest Development Team
diff --git a/doc/en/announce/release-8.4.1.rst b/doc/en/announce/release-8.4.1.rst
new file mode 100644
index 00000000000..07ee26187a7
--- /dev/null
+++ b/doc/en/announce/release-8.4.1.rst
@@ -0,0 +1,21 @@
+pytest-8.4.1
+=======================================
+
+pytest 8.4.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
+* Iwithyou2025
+* John Litborn
+* Martin Fischer
+* Ran Benita
+* SarahPythonista
+
+
+Happy testing,
+The pytest Development Team
diff --git a/doc/en/announce/release-8.4.2.rst b/doc/en/announce/release-8.4.2.rst
new file mode 100644
index 00000000000..58a842c4d4b
--- /dev/null
+++ b/doc/en/announce/release-8.4.2.rst
@@ -0,0 +1,27 @@
+pytest-8.4.2
+=======================================
+
+pytest 8.4.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:
+
+* AD
+* Aditi De
+* Bruno Oliveira
+* Florian Bruhin
+* John Litborn
+* Liam DeVoe
+* Marc Mueller
+* NayeemJohn
+* Olivier Grisel
+* Ran Benita
+* bengartner
+* 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко)
+
+
+Happy testing,
+The pytest Development Team
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/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/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/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 8aa6fef681c..6a96bb0a304 100644
--- a/doc/en/builtin.rst
+++ b/doc/en/builtin.rst
@@ -12,17 +12,17 @@ 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
$ 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
- cache -- .../_pytest/cacheprovider.py:556
+ cache -- .../_pytest/cacheprovider.py:566
Return a cache object that can persist state between testing sessions.
cache.get(key, default)
@@ -33,7 +33,48 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
Values can be any object handled by the json stdlib module.
- capsysbinary -- .../_pytest/capture.py:1024
+ capsys -- .../_pytest/capture.py:1000
+ Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``.
+
+ The captured output is made available via ``capsys.readouterr()`` method
+ calls, which return a ``(out, err)`` namedtuple.
+ ``out`` and ``err`` will be ``text`` objects.
+
+ Returns an instance of :class:`CaptureFixture[str] `.
+
+ Example:
+
+ .. code-block:: python
+
+ def test_output(capsys):
+ print("hello")
+ captured = capsys.readouterr()
+ assert captured.out == "hello\n"
+
+ capteesys -- .../_pytest/capture.py:1028
+ Enable simultaneous text capturing and pass-through of writes
+ to ``sys.stdout`` and ``sys.stderr`` as defined by ``--capture=``.
+
+
+ The captured output is made available via ``capteesys.readouterr()`` method
+ calls, which return a ``(out, err)`` namedtuple.
+ ``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=``.
+
+ Returns an instance of :class:`CaptureFixture[str] `.
+
+ Example:
+
+ .. code-block:: python
+
+ def test_output(capteesys):
+ print("hello")
+ captured = capteesys.readouterr()
+ assert captured.out == "hello\n"
+
+ capsysbinary -- .../_pytest/capture.py:1063
Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``.
The captured output is made available via ``capsysbinary.readouterr()``
@@ -51,7 +92,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
captured = capsysbinary.readouterr()
assert captured.out == b"hello\n"
- capfd -- .../_pytest/capture.py:1052
+ capfd -- .../_pytest/capture.py:1091
Enable text capturing of writes to file descriptors ``1`` and ``2``.
The captured output is made available via ``capfd.readouterr()`` method
@@ -69,7 +110,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
captured = capfd.readouterr()
assert captured.out == "hello\n"
- capfdbinary -- .../_pytest/capture.py:1080
+ capfdbinary -- .../_pytest/capture.py:1119
Enable bytes capturing of writes to file descriptors ``1`` and ``2``.
The captured output is made available via ``capfd.readouterr()`` method
@@ -87,25 +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"
- capsys -- .../_pytest/capture.py:996
- Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``.
-
- The captured output is made available via ``capsys.readouterr()`` method
- calls, which return a ``(out, err)`` namedtuple.
- ``out`` and ``err`` will be ``text`` objects.
-
- Returns an instance of :class:`CaptureFixture[str] `.
-
- Example:
-
- .. code-block:: python
-
- def test_output(capsys):
- print("hello")
- captured = capsys.readouterr()
- assert captured.out == "hello\n"
-
- doctest_namespace [session scope] -- .../_pytest/doctest.py:741
+ doctest_namespace [session scope] -- .../_pytest/doctest.py:722
Fixture that returns a :py:class:`dict` that will be injected into the
namespace of doctests.
@@ -119,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:1345
+ pytestconfig [session scope] -- .../_pytest/fixtures.py:1431
Session-scoped fixture that returns the session's :class:`pytest.Config`
object.
@@ -129,7 +152,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
if pytestconfig.get_verbosity() > 0:
...
- record_property -- .../_pytest/junitxml.py:280
+ record_property -- .../_pytest/junitxml.py:277
Add extra properties to the calling test.
User properties become part of the test report and are available to the
@@ -143,13 +166,13 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
def test_function(record_property):
record_property("example_key", 1)
- record_xml_attribute -- .../_pytest/junitxml.py:303
+ record_xml_attribute -- .../_pytest/junitxml.py:300
Add extra xml attributes to the tag for the calling test.
The fixture is callable with ``name, value``. The value is
automatically XML-encoded.
- record_testsuite_property [session scope] -- .../_pytest/junitxml.py:341
+ record_testsuite_property [session scope] -- .../_pytest/junitxml.py:338
Record a new ```` tag as child of the root ````.
This is suitable to writing global information regarding the entire test
@@ -191,7 +214,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
.. _legacy_path: https://py.readthedocs.io/en/latest/path.html
- caplog -- .../_pytest/logging.py:598
+ caplog -- .../_pytest/logging.py:596
Access and control log capturing.
Captured logs are available through the following properties/methods::
@@ -202,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
@@ -226,15 +249,18 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
To undo modifications done by the fixture in a contained scope,
use :meth:`context() `.
- recwarn -- .../_pytest/recwarn.py:35
+ recwarn -- .../_pytest/recwarn.py:34
Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions.
See :ref:`warnings` for information on warning categories.
- tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:241
+ subtests -- .../_pytest/subtests.py:129
+ Provides subtests functionality.
+
+ tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:243
Return a :class:`pytest.TempPathFactory` instance for the test session.
- tmp_path -- .../_pytest/tmpdir.py:256
+ 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 c92cd7d4263..b4e5cee694e 100644
--- a/doc/en/changelog.rst
+++ b/doc/en/changelog.rst
@@ -31,6 +31,880 @@ 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)
+=========================
+
+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)
+=========================
+
+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.
+
+ **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.
+
+ 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.
+
+
+- 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
+ 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)
+=========================
+
+Bug fixes
+---------
+
+- `#13478 `_: Fixed a crash when using :confval:`console_output_style` with ``times`` and a module is skipped.
+
+
+- `#13530 `_: Fixed a crash when using :func:`pytest.approx` and :class:`decimal.Decimal` instances with the :class:`decimal.FloatOperation` trap set.
+
+
+- `#13549 `_: No longer evaluate type annotations in Python ``3.14`` when inspecting function signatures.
+
+ This prevents crashes during module collection when modules do not explicitly use ``from __future__ import annotations`` and import types for annotations within a ``if TYPE_CHECKING:`` block.
+
+
+- `#13559 `_: Added missing `int` and `float` variants to the `Literal` type annotation of the `type` parameter in :meth:`pytest.Parser.addini`.
+
+
+- `#13563 `_: :func:`pytest.approx` now only imports ``numpy`` if NumPy is already in ``sys.modules``. This fixes unconditional import behavior introduced in `8.4.0`.
+
+
+
+Improved documentation
+----------------------
+
+- `#13577 `_: Clarify that ``pytest_generate_tests`` is discovered in test modules/classes; other hooks must be in ``conftest.py`` or plugins.
+
+
+
+Contributor-facing changes
+--------------------------
+
+- `#13480 `_: Self-testing: fixed a few test failures when run with ``-Wdefault`` or a similar override.
+
+
+- `#13547 `_: Self-testing: corrected expected message for ``test_doctest_unexpected_exception`` in Python ``3.14``.
+
+
+- `#13684 `_: Make pytest's own testsuite insensitive to the presence of the ``CI`` environment variable -- by :user:`ogrisel`.
+
+
+pytest 8.4.1 (2025-06-17)
+=========================
+
+Bug fixes
+---------
+
+- `#13461 `_: Corrected ``_pytest.terminal.TerminalReporter.isatty`` to support
+ being called as a method. Before it was just a boolean which could
+ break correct code when using ``-o log_cli=true``).
+
+
+- `#13477 `_: Reintroduced :class:`pytest.PytestReturnNotNoneWarning` which was removed by accident in pytest `8.4`.
+
+ This warning is raised when a test functions returns a value other than ``None``, which is often a mistake made by beginners.
+
+ See :ref:`return-not-none` for more information.
+
+
+- `#13497 `_: Fixed compatibility with ``Twisted 25+``.
+
+
+
+Improved documentation
+----------------------
+
+- `#13492 `_: Fixed outdated warning about ``faulthandler`` not working on Windows.
+
+
+pytest 8.4.0 (2025-06-02)
+=========================
+
+Removals and backward incompatible breaking changes
+---------------------------------------------------
+
+- `#11372 `_: Async tests will now fail, instead of warning+skipping, if you don't have any suitable plugin installed.
+
+
+- `#12346 `_: Tests will now fail, instead of raising a warning, if they return any value other than None.
+
+
+- `#12874 `_: We dropped support for Python 3.8 following its end of life (2024-10-07).
+
+
+- `#12960 `_: Test functions containing a yield now cause an explicit error. They have not been run since pytest 4.0, and were previously marked as an expected failure and deprecation warning.
+
+ See :ref:`the docs ` for more information.
+
+
+
+Deprecations (removal in next major release)
+--------------------------------------------
+
+- `#10839 `_: Requesting an asynchronous fixture without a `pytest_fixture_setup` hook that resolves it will now give a DeprecationWarning. This most commonly happens if a sync test requests an async fixture. This should have no effect on a majority of users with async tests or fixtures using async pytest plugins, but may affect non-standard hook setups or ``autouse=True``. For guidance on how to work around this warning see :ref:`sync-test-async-fixture`.
+
+
+
+New features
+------------
+
+- `#11538 `_: Added :class:`pytest.RaisesGroup` as an equivalent to :func:`pytest.raises` for expecting :exc:`ExceptionGroup`. Also adds :class:`pytest.RaisesExc` which is now the logic behind :func:`pytest.raises` and used as parameter to :class:`pytest.RaisesGroup`. ``RaisesGroup`` includes the ability to specify multiple different expected exceptions, the structure of nested exception groups, and flags for emulating :ref:`except* `. See :ref:`assert-matching-exception-groups` and docstrings for more information.
+
+
+- `#12081 `_: Added :fixture:`capteesys` to capture AND pass output to next handler set by ``--capture=``.
+
+
+- `#12504 `_: :func:`pytest.mark.xfail` now accepts :class:`pytest.RaisesGroup` for the ``raises`` parameter when you expect an exception group. You can also pass a :class:`pytest.RaisesExc` if you e.g. want to make use of the ``check`` parameter.
+
+
+- `#12713 `_: New `--force-short-summary` option to force condensed summary output regardless of verbosity level.
+
+ This lets users still see condensed summary output of failures for quick reference in log files from job outputs, being especially useful if non-condensed output is very verbose.
+
+
+- `#12749 `_: pytest traditionally collects classes/functions in the test module namespace even if they are imported from another file.
+
+ For example:
+
+ .. code-block:: python
+
+ # contents of src/domain.py
+ class Testament: ...
+
+
+ # contents of tests/test_testament.py
+ from domain import Testament
+
+
+ def test_testament(): ...
+
+ In this scenario with the default options, pytest will collect the class `Testament` from `tests/test_testament.py` because it starts with `Test`, even though in this case it is a production class being imported in the test module namespace.
+
+ This behavior can now be prevented by setting the new :confval:`collect_imported_tests` configuration option to ``false``, which will make pytest collect classes/functions from test files **only** if they are defined in that file.
+
+ -- by :user:`FreerGit`
+
+
+- `#12765 `_: Thresholds to trigger snippet truncation can now be set with :confval:`truncation_limit_lines` and :confval:`truncation_limit_chars`.
+
+ See :ref:`truncation-params` for more information.
+
+
+- `#13125 `_: :confval:`console_output_style` now supports ``times`` to show execution time of each test.
+
+
+- `#13192 `_: :func:`pytest.raises` will now raise a warning when passing an empty string to ``match``, as this will match against any value. Use ``match="^$"`` if you want to check that an exception has no message.
+
+
+- `#13192 `_: :func:`pytest.raises` will now print a helpful string diff if matching fails and the match parameter has ``^`` and ``$`` and is otherwise escaped.
+
+
+- `#13192 `_: You can now pass :func:`with pytest.raises(check=fn): `, where ``fn`` is a function which takes a raised exception and returns a boolean. The ``raises`` fails if no exception was raised (as usual), passes if an exception is raised and ``fn`` returns ``True`` (as well as ``match`` and the type matching, if specified, which are checked before), and propagates the exception if ``fn`` returns ``False`` (which likely also fails the test).
+
+
+- `#13228 `_: :ref:`hidden-param` can now be used in ``id`` of :func:`pytest.param` or in
+ ``ids`` of :py:func:`Metafunc.parametrize `.
+ It hides the parameter set from the test name.
+
+
+- `#13253 `_: New flag: :ref:`--disable-plugin-autoload ` which works as an alternative to :envvar:`PYTEST_DISABLE_PLUGIN_AUTOLOAD` when setting environment variables is inconvenient; and allows setting it in config files with :confval:`addopts`.
+
+
+
+Improvements in existing functionality
+--------------------------------------
+
+- `#10224 `_: pytest's ``short`` and ``long`` traceback styles (:ref:`how-to-modifying-python-tb-printing`)
+ now have partial :pep:`657` support and will show specific code segments in the
+ traceback.
+
+ .. code-block:: pytest
+
+ ================================= FAILURES =================================
+ _______________________ test_gets_correct_tracebacks _______________________
+
+ test_tracebacks.py:12: in test_gets_correct_tracebacks
+ assert manhattan_distance(p1, p2) == 1
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ test_tracebacks.py:6: in manhattan_distance
+ return abs(point_1.x - point_2.x) + abs(point_1.y - point_2.y)
+ ^^^^^^^^^
+ E AttributeError: 'NoneType' object has no attribute 'x'
+
+ -- by :user:`ammaraskar`
+
+
+- `#11118 `_: Now :confval:`pythonpath` configures `$PYTHONPATH` earlier than before during the initialization process, which now also affects plugins loaded via the `-p` command-line option.
+
+ -- by :user:`millerdev`
+
+
+- `#11381 `_: The ``type`` parameter of the ``parser.addini`` method now accepts `"int"` and ``"float"`` parameters, facilitating the parsing of configuration values in the configuration file.
+
+ Example:
+
+ .. code-block:: python
+
+ def pytest_addoption(parser):
+ parser.addini("int_value", type="int", default=2, help="my int value")
+ parser.addini("float_value", type="float", default=4.2, help="my float value")
+
+ The `pytest.ini` file:
+
+ .. code-block:: ini
+
+ [pytest]
+ int_value = 3
+ float_value = 5.4
+
+
+- `#11525 `_: Fixtures are now clearly represented in the output as a "fixture object", not as a normal function as before, making it easy for beginners to catch mistakes such as referencing a fixture declared in the same module but not requested in the test function.
+
+ -- by :user:`the-compiler` and :user:`glyphack`
+
+
+- `#12426 `_: A warning is now issued when :ref:`pytest.mark.usefixtures ref` is used without specifying any fixtures. Previously, empty usefixtures markers were silently ignored.
+
+
+- `#12707 `_: Exception chains can be navigated when dropped into Pdb in Python 3.13+.
+
+
+- `#12736 `_: Added a new attribute `name` with the fixed value `"pytest tests"` to the root tag `testsuites` of the junit-xml generated by pytest.
+
+ This attribute is part of many junit-xml specifications and is even part of the `junit-10.xsd` specification that pytest's implementation is based on.
+
+
+- `#12943 `_: If a test fails with an exceptiongroup with a single exception, the contained exception will now be displayed in the short test summary info.
+
+
+- `#12958 `_: A number of :ref:`unraisable ` enhancements:
+
+ * Set the unraisable hook as early as possible and unset it as late as possible, to collect the most possible number of unraisable exceptions.
+ * Call the garbage collector just before unsetting the unraisable hook, to collect any straggling exceptions.
+ * Collect multiple unraisable exceptions per test phase.
+ * Report the :mod:`tracemalloc` allocation traceback (if available).
+ * Avoid using a generator based hook to allow handling :class:`StopIteration` in test failures.
+ * Report the unraisable exception as the cause of the :class:`pytest.PytestUnraisableExceptionWarning` exception if raised.
+ * Compute the ``repr`` of the unraisable object in the unraisable hook so you get the latest information if available, and should help with resurrection of the object.
+
+
+- `#13010 `_: :func:`pytest.approx` now can compare collections that contain numbers and non-numbers mixed.
+
+
+- `#13016 `_: A number of :ref:`threadexception ` enhancements:
+
+ * Set the excepthook as early as possible and unset it as late as possible, to collect the most possible number of unhandled exceptions from threads.
+ * Collect multiple thread exceptions per test phase.
+ * Report the :mod:`tracemalloc` allocation traceback (if available).
+ * Avoid using a generator based hook to allow handling :class:`StopIteration` in test failures.
+ * Report the thread exception as the cause of the :class:`pytest.PytestUnhandledThreadExceptionWarning` exception if raised.
+ * Extract the ``name`` of the thread object in the excepthook which should help with resurrection of the thread.
+
+
+- `#13031 `_: An empty parameter set as in ``pytest.mark.parametrize([], ids=idfunc)`` will no longer trigger a call to ``idfunc`` with internal objects.
+
+
+- `#13115 `_: Allows supplying ``ExceptionGroup[Exception]`` and ``BaseExceptionGroup[BaseException]`` to ``pytest.raises`` to keep full typing on :class:`ExceptionInfo `:
+
+ .. code-block:: python
+
+ with pytest.raises(ExceptionGroup[Exception]) as exc_info:
+ some_function()
+
+ Parametrizing with other exception types remains an error - we do not check the types of child exceptions and thus do not permit code that might look like we do.
+
+
+- `#13122 `_: The ``--stepwise`` mode received a number of improvements:
+
+ * It no longer forgets the last failed test in case pytest is executed later without the flag.
+
+ This enables the following workflow:
+
+ 1. Execute pytest with ``--stepwise``, pytest then stops at the first failing test;
+ 2. Iteratively update the code and run the test in isolation, without the ``--stepwise`` flag (for example in an IDE), until it is fixed.
+ 3. Execute pytest with ``--stepwise`` again and pytest will continue from the previously failed test, and if it passes, continue on to the next tests.
+
+ Previously, at step 3, pytest would start from the beginning, forgetting the previously failed test.
+
+ This change however might cause issues if the ``--stepwise`` mode is used far apart in time, as the state might get stale, so the internal state will be reset automatically in case the test suite changes (for now only the number of tests are considered for this, we might change/improve this on the future).
+
+ * New ``--stepwise-reset``/``--sw-reset`` flag, allowing the user to explicitly reset the stepwise state and restart the workflow from the beginning.
+
+
+- `#13308 `_: Added official support for Python 3.14.
+
+
+- `#13380 `_: Fix :class:`ExceptionGroup` traceback filtering to exclude pytest internals.
+
+
+- `#13415 `_: The author metadata of the BibTex example is now correctly formatted with last names following first names.
+ An example of BibLaTex has been added.
+ BibTex and BibLaTex examples now clearly indicate that what is cited is software.
+
+ -- by :user:`willynilly`
+
+
+- `#13420 `_: Improved test collection performance by optimizing path resolution used in ``FSCollector``.
+
+
+- `#13457 `_: The error message about duplicate parametrization no longer displays an internal stack trace.
+
+
+- `#4112 `_: Using :ref:`pytest.mark.usefixtures ` on :func:`pytest.param` now produces an error instead of silently doing nothing.
+
+
+- `#5473 `_: Replace `:` with `;` in the assertion rewrite warning message so it can be filtered using standard Python warning filters before calling :func:`pytest.main`.
+
+
+- `#6985 `_: Improved :func:`pytest.approx` to enhance the readability of value ranges and tolerances between 0.001 and 1000.
+ * The `repr` method now provides clearer output for values within those ranges, making it easier to interpret the results.
+ * Previously, the output for those ranges of values and tolerances was displayed in scientific notation (e.g., `42 ± 1.0e+00`). The updated method now presents the tolerance as a decimal for better readability (e.g., `42 ± 1`).
+
+ Example:
+
+ **Previous Output:**
+
+ .. code-block:: console
+
+ >>> pytest.approx(42, abs=1)
+ 42 ± 1.0e+00
+
+ **Current Output:**
+
+ .. code-block:: console
+
+ >>> pytest.approx(42, abs=1)
+ 42 ± 1
+
+ -- by :user:`fazeelghafoor`
+
+
+- `#7683 `_: The formerly optional ``pygments`` dependency is now required, causing output always to be source-highlighted (unless disabled via the ``--code-highlight=no`` CLI option).
+
+
+
+Bug fixes
+---------
+
+- `#10404 `_: Apply filterwarnings from config/cli as soon as possible, and revert them as late as possible
+ so that warnings as errors are collected throughout the pytest run and before the
+ unraisable and threadexcept hooks are removed.
+
+ This allows very late warnings and unraisable/threadexcept exceptions to fail the test suite.
+
+ This also changes the warning that the lsof plugin issues from PytestWarning to the new warning PytestFDWarning so it can be more easily filtered.
+
+
+- `#11067 `_: The test report is now consistent regardless if the test xfailed via :ref:`pytest.mark.xfail ` or :func:`pytest.fail`.
+
+ Previously, *xfailed* tests via the marker would have the string ``"reason: "`` prefixed to the message, while those *xfailed* via the function did not. The prefix has been removed.
+
+
+- `#12008 `_: In :pr:`11220`, an unintended change in reordering was introduced by changing the way indices were assigned to direct params. More specifically, before that change, the indices of direct params to metafunc's callspecs were assigned after all parametrizations took place. Now, that change is reverted.
+
+
+- `#12863 `_: Fix applying markers, including :ref:`pytest.mark.parametrize ` when placed above `@staticmethod` or `@classmethod`.
+
+
+- `#12929 `_: Handle StopIteration from test cases, setup and teardown correctly.
+
+
+- `#12938 `_: Fixed ``--durations-min`` argument not respected if ``-vv`` is used.
+
+
+- `#12946 `_: Fixed missing help for :mod:`pdb` commands wrapped by pytest -- by :user:`adamchainz`.
+
+
+- `#12981 `_: Prevent exceptions in :func:`pytest.Config.add_cleanup` callbacks preventing further cleanups.
+
+
+- `#13047 `_: Restore :func:`pytest.approx` handling of equality checks between `bool` and `numpy.bool_` types.
+
+ Comparing `bool` and `numpy.bool_` using :func:`pytest.approx` accidentally changed in version `8.3.4` and `8.3.5` to no longer match:
+
+ .. code-block:: pycon
+
+ >>> import numpy as np
+ >>> from pytest import approx
+ >>> [np.True_, np.True_] == pytest.approx([True, True])
+ False
+
+ This has now been fixed:
+
+ .. code-block:: pycon
+
+ >>> [np.True_, np.True_] == pytest.approx([True, True])
+ True
+
+
+- `#13119 `_: Improved handling of invalid regex patterns for filter warnings by providing a clear error message.
+
+
+- `#13175 `_: The diff is now also highlighted correctly when comparing two strings.
+
+
+- `#13248 `_: Fixed an issue where passing a ``scope`` in :py:func:`Metafunc.parametrize ` with ``indirect=True``
+ could result in other fixtures being unable to depend on the parametrized fixture.
+
+
+- `#13291 `_: Fixed ``repr`` of ``attrs`` objects in assertion failure messages when using ``attrs>=25.2``.
+
+
+- `#13312 `_: Fixed a possible ``KeyError`` crash on PyPy during collection of tests involving higher-scoped parameters.
+
+
+- `#13345 `_: Fix type hints for :attr:`pytest.TestReport.when` and :attr:`pytest.TestReport.location`.
+
+
+- `#13377 `_: Fixed handling of test methods with positional-only parameter syntax.
+
+ Now, methods are supported that formally define ``self`` as positional-only
+ and/or fixture parameters as keyword-only, e.g.:
+
+ .. code-block:: python
+
+ class TestClass:
+
+ def test_method(self, /, *, fixture): ...
+
+ Before, this caused an internal error in pytest.
+
+
+- `#13384 `_: Fixed an issue where pytest could report negative durations.
+
+
+- `#13420 `_: Added ``lru_cache`` to ``nodes._check_initialpaths_for_relpath``.
+
+
+- `#9037 `_: Honor :confval:`disable_test_id_escaping_and_forfeit_all_rights_to_community_support` when escaping ids in parametrized tests.
+
+
+
+Improved documentation
+----------------------
+
+- `#12535 `_: `This
+ example`
+ showed ``print`` statements that do not exactly reflect what the
+ different branches actually do. The fix makes the example more precise.
+
+
+- `#13218 `_: Pointed out in the :func:`pytest.approx` documentation that it considers booleans unequal to numeric zero or one.
+
+
+- `#13221 `_: Improved grouping of CLI options in the ``--help`` output.
+
+
+- `#6649 `_: Added :class:`~pytest.TerminalReporter` to the :ref:`api-reference` documentation page.
+
+
+- `#8612 `_: Add a recipe for handling abstract test classes in the documentation.
+
+ A new example has been added to the documentation to demonstrate how to use a mixin class to handle abstract
+ test classes without manually setting the ``__test__`` attribute for subclasses.
+ This ensures that subclasses of abstract test classes are automatically collected by pytest.
+
+
+
+Packaging updates and notes for downstreams
+-------------------------------------------
+
+- `#13317 `_: Specified minimum allowed versions of ``colorama``, ``iniconfig``,
+ and ``packaging``; and bumped the minimum allowed version
+ of ``exceptiongroup`` for ``python_version<'3.11'`` from a release
+ candidate to a full release.
+
+
+
+Contributor-facing changes
+--------------------------
+
+- `#12017 `_: Mixed internal improvements:
+
+ * Migrate formatting to f-strings in some tests.
+ * Use type-safe constructs in JUnitXML tests.
+ * Moved`` MockTiming`` into ``_pytest.timing``.
+
+ -- by :user:`RonnyPfannschmidt`
+
+
+- `#12647 `_: Fixed running the test suite with the ``hypothesis`` pytest plugin.
+
+
+
+Miscellaneous internal changes
+------------------------------
+
+- `#6649 `_: Added :class:`~pytest.TerminalReporter` to the public pytest API, as it is part of the signature of the :hook:`pytest_terminal_summary` hook.
+
+
pytest 8.3.5 (2025-03-02)
=========================
diff --git a/doc/en/conf.py b/doc/en/conf.py
index c89e14d07fa..81156493131 100644
--- a/doc/en/conf.py
+++ b/doc/en/conf.py
@@ -34,6 +34,7 @@
"sphinx.ext.todo",
"sphinx.ext.viewcode",
"sphinx_removed_in",
+ "sphinx_inline_tabs",
"sphinxcontrib_trio",
"sphinxcontrib.towncrier.ext", # provides `towncrier-draft-entries` directive
"sphinx_issues", # implements `:issue:`, `:pr:` and other GH-related roles
diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst
index 18df64c9204..65a05823517 100644
--- a/doc/en/deprecations.rst
+++ b/doc/en/deprecations.rst
@@ -15,6 +15,41 @@ Below is a complete list of all pytest features which are considered deprecated.
:class:`~pytest.PytestWarning` or subclasses, which can be filtered using :ref:`standard warning filters `.
+.. _monkeypatch-fixup-namespace-packages:
+
+``monkeypatch.syspath_prepend`` with legacy namespace packages
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. deprecated:: 9.0
+
+When using :meth:`monkeypatch.syspath_prepend() `,
+pytest automatically calls ``pkg_resources.fixup_namespace_packages()`` if ``pkg_resources`` is imported.
+This is only needed for legacy namespace packages that use ``pkg_resources.declare_namespace()``.
+
+Legacy namespace packages are deprecated in favor of native namespace packages (:pep:`420`).
+If you are using ``pkg_resources.declare_namespace()`` in your ``__init__.py`` files,
+you should migrate to native namespace packages by removing the ``__init__.py`` files from your namespace packages.
+
+This deprecation warning will only be issued when:
+
+1. ``pkg_resources`` is imported, and
+2. The specific path being prepended contains a declared namespace package (via ``pkg_resources.declare_namespace()``)
+
+To fix this warning, convert your legacy namespace packages to native namespace packages:
+
+**Legacy namespace package** (deprecated):
+
+.. code-block:: python
+
+ # mypkg/__init__.py
+ __import__("pkg_resources").declare_namespace(__name__)
+
+**Native namespace package** (recommended):
+
+Simply remove the ``__init__.py`` file entirely.
+Python 3.3+ natively supports namespace packages without ``__init__.py``.
+
+
.. _sync-test-async-fixture:
sync test depending on async fixture
@@ -316,46 +351,6 @@ Users expected in this case that the ``usefixtures`` mark would have its intende
Now pytest will issue a warning when it encounters this problem, and will raise an error in the future versions.
-Returning non-None value in test functions
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. deprecated:: 7.2
-
-A ``pytest.PytestReturnNotNoneWarning`` is now emitted if a test function returns something other than `None`.
-
-This prevents a common mistake among beginners that expect that returning a `bool` would cause a test to pass or fail, for example:
-
-.. code-block:: python
-
- @pytest.mark.parametrize(
- ["a", "b", "result"],
- [
- [1, 2, 5],
- [2, 3, 8],
- [5, 3, 18],
- ],
- )
- def test_foo(a, b, result):
- return foo(a, b) == result
-
-Given that pytest ignores the return value, this might be surprising that it will never fail.
-
-The proper fix is to change the `return` to an `assert`:
-
-.. code-block:: python
-
- @pytest.mark.parametrize(
- ["a", "b", "result"],
- [
- [1, 2, 5],
- [2, 3, 8],
- [5, 3, 18],
- ],
- )
- def test_foo(a, b, result):
- assert foo(a, b) == result
-
-
The ``yield_fixture`` function/decorator
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -594,18 +589,20 @@ removed in pytest 8 (deprecated since pytest 2.4.0):
- ``parser.addoption(..., type="int/string/float/complex")`` - use ``type=int`` etc. instead.
-The ``--strict`` command-line option
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The ``--strict`` command-line option (reintroduced)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 6.2
-.. versionremoved:: 8.0
+.. versionchanged:: 9.0
-The ``--strict`` command-line option has been deprecated in favor of ``--strict-markers``, which
+The ``--strict`` command-line option had been deprecated in favor of ``--strict-markers``, which
better conveys what the option does.
-We have plans to maybe in the future to reintroduce ``--strict`` and make it an encompassing
-flag for all strictness related options (``--strict-markers`` and ``--strict-config``
-at the moment, more might be introduced in the future).
+In version 8.1, we accidentally un-deprecated ``--strict``.
+
+In version 9.0, we changed ``--strict`` to make it set the new :confval:`strict`
+configuration option. It now enables all strictness related options (including
+:confval:`strict_markers`).
.. _cmdline-preparse-deprecated:
@@ -848,20 +845,38 @@ that manipulate this type of file (for example, Jenkins, Azure Pipelines, etc.).
Users are recommended to try the new ``xunit2`` format and see if their tooling that consumes the JUnit
XML file supports it.
-To use the new format, update your ``pytest.ini``:
+To use the new format, update your configuration file:
+
+.. tab:: toml
+
+ .. code-block:: toml
-.. code-block:: ini
+ [pytest]
+ junit_family = "xunit2"
- [pytest]
- junit_family=xunit2
+.. tab:: ini
+
+ .. code-block:: ini
+
+ [pytest]
+ junit_family = xunit2
If you discover that your tooling does not support the new format, and want to keep using the
legacy version, set the option to ``legacy`` instead:
-.. code-block:: ini
+.. tab:: toml
+
+ .. code-block:: toml
+
+ [pytest]
+ junit_family = "legacy"
+
+.. tab:: ini
+
+ .. code-block:: ini
- [pytest]
- junit_family=legacy
+ [pytest]
+ junit_family = legacy
By using ``legacy`` you will keep using the legacy/xunit1 format when upgrading to
pytest 6.0, where the default format will be ``xunit2``.
diff --git a/doc/en/example/.ruff.toml b/doc/en/example/.ruff.toml
new file mode 100644
index 00000000000..feddc5c0654
--- /dev/null
+++ b/doc/en/example/.ruff.toml
@@ -0,0 +1 @@
+lint.ignore = ["RUF059"]
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 babcd9e2f3a..4f6738207e1 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
@@ -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
@@ -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
@@ -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.
@@ -239,13 +239,11 @@ Registering markers
Registering markers for your test suite is simple:
-.. code-block:: ini
+.. code-block:: toml
- # content of pytest.ini
+ # content of pytest.toml
[pytest]
- markers =
- webtest: mark a test as a webtest.
- slow: mark test as slow.
+ markers = ["webtest: mark a test as a webtest.", "slow: mark test as slow."]
Multiple custom markers can be registered, by defining each one in its own line, as shown in above example.
@@ -264,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.
@@ -286,8 +284,7 @@ For an example on how to add and work with markers from a plugin, see
* Asking for existing markers via ``pytest --markers`` gives good output
- * Typos in function markers are treated as an error if you use
- the ``--strict-markers`` option.
+ * Typos in function markers are treated as an error if you use the :confval:`strict_markers` configuration option.
.. _`scoped-marking`:
@@ -421,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
@@ -435,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
@@ -443,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
@@ -456,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.
@@ -628,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
@@ -644,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
@@ -661,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
@@ -707,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
@@ -733,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/multipython.py b/doc/en/example/multipython.py
index f54524213bc..c04a2868812 100644
--- a/doc/en/example/multipython.py
+++ b/doc/en/example/multipython.py
@@ -10,7 +10,7 @@
import pytest
-pythonlist = ["python3.9", "python3.10", "python3.11"]
+pythonlist = ["python3.11", "python3.12", "python3.13"]
@pytest.fixture(params=pythonlist)
diff --git a/doc/en/example/nonpython.rst b/doc/en/example/nonpython.rst
index aa463e2416b..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
@@ -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
@@ -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
@@ -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
@@ -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 69e715c9db1..7aec1364953 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
@@ -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
-
+
@@ -352,7 +352,7 @@ The first invocation with ``db == "DB1"`` passed while the second with ``db == "
Indirect parametrization
---------------------------------------------------
-Using the ``indirect=True`` parameter when parametrizing a test allows to
+Using the ``indirect=True`` parameter when parametrizing a test allows one to
parametrize a test with a fixture receiving the values before passing them to a
test:
@@ -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
@@ -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
---------------------------------------------------
@@ -568,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
@@ -629,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 6a3b143d580..339944c4758 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,18 +43,20 @@ 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:
+
Keeping duplicate paths specified from command line
----------------------------------------------------
@@ -71,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
@@ -82,29 +84,17 @@ Example:
collected 2 items
...
-As the collector just works on directories, if you specify twice a single test file, ``pytest`` will
-still collect it twice, no matter if the ``--keep-duplicates`` is not specified.
-Example:
-
-.. code-block:: pytest
-
- pytest test_a.py test_a.py
-
- ...
- collected 2 items
- ...
-
Changing directory recursion
-----------------------------------------------------
-You can set the :confval:`norecursedirs` option in an ini-file, for example your ``pytest.ini`` in the project root directory:
+You can set the :confval:`norecursedirs` option in a configuration file:
-.. code-block:: ini
+.. code-block:: toml
- # content of pytest.ini
+ # content of pytest.toml
[pytest]
- norecursedirs = .svn _build tmp*
+ norecursedirs = [".svn", "_build", "tmp*"]
This would tell ``pytest`` to not recurse into typical subversion or sphinx-build directories or into any ``tmp`` prefixed directory.
@@ -118,14 +108,14 @@ the :confval:`python_files`, :confval:`python_classes` and
:confval:`python_functions` in your :ref:`configuration file `.
Here is an example:
-.. code-block:: ini
+.. code-block:: toml
- # content of pytest.ini
+ # content of pytest.toml
# Example 1: have pytest look for "check" instead of "test"
[pytest]
- python_files = check_*.py
- python_classes = Check
- python_functions = *_check
+ python_files = ["check_*.py"]
+ python_classes = ["Check"]
+ python_functions = ["*_check"]
This would make ``pytest`` look for tests in files that match the ``check_*
.py`` glob-pattern, ``Check`` prefixes in classes, and functions and methods
@@ -147,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.ini
+ configfile: pytest.toml
collected 2 items
-
+
@@ -162,12 +152,12 @@ The test collection would look like this:
You can check for multiple glob patterns by adding a space between the patterns:
-.. code-block:: ini
+.. code-block:: toml
+ # content of pytest.toml
# Example 2: have pytest look for files with "test" and "example"
- # content of pytest.ini
[pytest]
- python_files = test_*.py example_*.py
+ python_files = ["test_*.py", "example_*.py"]
.. note::
@@ -178,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:
@@ -188,14 +178,14 @@ example if you have unittest2 installed you can type:
pytest --pyargs unittest2.test.test_skipping -q
which would run the respective test module. Like with
-other options, through an ini-file and the :confval:`addopts` option you
+other options, through a configuration file and the :confval:`addopts` option you
can make this change more permanently:
-.. code-block:: ini
+.. code-block:: toml
- # content of pytest.ini
+ # content of pytest.toml
[pytest]
- addopts = --pyargs
+ addopts = ["--pyargs"]
Now a simple invocation of ``pytest NAME`` will check
if NAME exists as an importable package/module and otherwise
@@ -210,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.ini
+ configfile: pytest.toml
collected 3 items
-
+
@@ -234,14 +224,14 @@ Customizing test collection
You can easily instruct ``pytest`` to discover tests from every Python file:
-.. code-block:: ini
+.. code-block:: toml
- # content of pytest.ini
+ # content of pytest.toml
[pytest]
- python_files = *.py
+ 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:
@@ -294,9 +284,9 @@ 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.ini
+ configfile: pytest.toml
collected 0 items
======================= no tests collected in 0.12s ========================
diff --git a/doc/en/example/reportingdemo.rst b/doc/en/example/reportingdemo.rst
index 5e48815bbc9..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
@@ -384,6 +384,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
i = Foo()
> assert i.b == 2
+ ^^^
failure_demo.py:148:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
@@ -446,6 +447,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
def test_tupleerror(self):
> a, b = [1] # noqa: F841
+ ^^^^
E ValueError: not enough values to unpack (expected 2, got 1)
failure_demo.py:177: ValueError
@@ -457,6 +459,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
items = [1, 2, 3]
print(f"items is {items!r}")
> a, b = items.pop()
+ ^^^^
E TypeError: cannot unpack non-iterable int object
failure_demo.py:182: TypeError
@@ -468,6 +471,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
def test_some_error(self):
> if namenotexi: # noqa: F821
+ ^^^^^^^^^^
E NameError: name 'namenotexi' is not defined
failure_demo.py:185: NameError
@@ -526,6 +530,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
def test_z1_unpack_error(self):
items = []
> a, b = items
+ ^^^^
E ValueError: not enough values to unpack (expected 2, got 0)
failure_demo.py:219: ValueError
@@ -536,6 +541,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
def test_z2_type_error(self):
items = 3
> a, b = items
+ ^^^^
E TypeError: cannot unpack non-iterable int object
failure_demo.py:223: TypeError
@@ -568,12 +574,12 @@ Here is a nice run of several failures and how ``pytest`` presents things:
E + where False = ('456')
E + where = '123'.startswith
E + where '123' = .f at 0xdeadbeef0029>()
- E + and '456' = .g at 0xdeadbeef0003>()
+ E + and '456' = .g at 0xdeadbeef002a>()
failure_demo.py:237: AssertionError
_____________________ TestMoreErrors.test_global_func ______________________
- self =
+ self =
def test_global_func(self):
> assert isinstance(globf(42), float)
@@ -584,18 +590,18 @@ Here is a nice run of several failures and how ``pytest`` presents things:
failure_demo.py:240: AssertionError
_______________________ TestMoreErrors.test_instance _______________________
- self =
+ self =
def test_instance(self):
self.x = 6 * 7
> assert self.x != 42
E assert 42 != 42
- E + where 42 = .x
+ E + where 42 = .x
failure_demo.py:244: AssertionError
_______________________ TestMoreErrors.test_compare ________________________
- self =
+ self =
def test_compare(self):
> assert globf(10) < 5
@@ -605,7 +611,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
failure_demo.py:247: AssertionError
_____________________ TestMoreErrors.test_try_finally ______________________
- self =
+ self =
def test_try_finally(self):
x = 1
@@ -616,7 +622,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
failure_demo.py:252: AssertionError
___________________ TestCustomAssertMsg.test_single_line ___________________
- self =
+ self =
def test_single_line(self):
class A:
@@ -631,16 +637,16 @@ Here is a nice run of several failures and how ``pytest`` presents things:
failure_demo.py:263: AssertionError
____________________ TestCustomAssertMsg.test_multiline ____________________
- self =
+ self =
def test_multiline(self):
class A:
a = 1
b = 2
- > assert (
- A.a == b
- ), "A.a appears not to be b\nor does not appear to be b\none of those"
+ > assert A.a == b, (
+ "A.a appears not to be b\nor does not appear to be b\none of those"
+ )
E AssertionError: A.a appears not to be b
E or does not appear to be b
E one of those
@@ -650,7 +656,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
failure_demo.py:270: AssertionError
___________________ TestCustomAssertMsg.test_custom_repr ___________________
- self =
+ self =
def test_custom_repr(self):
class JSON:
diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst
index 69d973e51d0..8b35f0ebca5 100644
--- a/doc/en/example/simple.rst
+++ b/doc/en/example/simple.rst
@@ -11,12 +11,11 @@ every time you use ``pytest``. For example, if you always want to see
detailed info on skipped and xfailed tests, as well as have terser "dot"
progress output, you can write it into a configuration file:
-.. code-block:: ini
+.. code-block:: toml
- # content of pytest.ini
+ # content of pytest.toml
[pytest]
- addopts = -ra -q
-
+ addopts = ["-ra", "-q"]
Alternatively, you can set a ``PYTEST_ADDOPTS`` environment variable to add command
line options while the environment is in use:
@@ -29,7 +28,7 @@ Here's how the command-line is built in the presence of ``addopts`` or the envir
.. code-block:: text
- $PYTEST_ADDOPTS
+ $PYTEST_ADDOPTS
So if the user executes in the command-line:
@@ -44,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:
@@ -104,6 +103,7 @@ Let's run this without supplying our new option:
elif cmdopt == "type2":
print("second")
> assert 0 # to see what was printed
+ ^^^^^^^^
E assert 0
test_sample.py:6: AssertionError
@@ -130,6 +130,7 @@ And now with supplying a command line option:
elif cmdopt == "type2":
print("second")
> assert 0 # to see what was printed
+ ^^^^^^^^
E assert 0
test_sample.py:6: AssertionError
@@ -165,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
@@ -232,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
@@ -296,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
@@ -312,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
@@ -350,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
@@ -441,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
@@ -469,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?
@@ -484,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
@@ -523,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
@@ -629,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
@@ -646,7 +649,7 @@ If we run this:
test_step.py:11: AssertionError
========================= short test summary info ==========================
- XFAIL test_step.py::TestUserHandling::test_deletion - reason: previous test failed (test_modification)
+ XFAIL test_step.py::TestUserHandling::test_deletion - previous test failed (test_modification)
================== 1 failed, 2 passed, 1 xfailed in 0.12s ==================
We'll see that ``test_deletion`` was not executed because ``test_modification``
@@ -711,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
@@ -725,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, 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
@@ -736,6 +739,7 @@ We can run this:
def test_a1(db):
> assert 0, db # to show value
+ ^^^^^^^^^^^^
E AssertionError:
E assert 0
@@ -746,6 +750,7 @@ We can run this:
def test_a2(db):
> assert 0, db # to show value
+ ^^^^^^^^^^^^
E AssertionError:
E assert 0
@@ -831,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
@@ -942,11 +947,11 @@ 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
- test_module.py Esetting up a test failed or skipped test_module.py::test_setup_fails
+ test_module.py Esetting up a test failed test_module.py::test_setup_fails
Fexecuting test failed or skipped test_module.py::test_call_fails
F
@@ -993,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/ci.rst b/doc/en/explanation/ci.rst
index 45fe658d14f..6f6734f395b 100644
--- a/doc/en/explanation/ci.rst
+++ b/doc/en/explanation/ci.rst
@@ -17,8 +17,7 @@ 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,
-regardless of their value:
+Pytest knows it is in a CI environment when either one of these environment variables are set to a non-empty value:
* `CI`: used by many CI systems.
* `BUILD_NUMBER`: used by Jenkins.
diff --git a/doc/en/explanation/goodpractices.rst b/doc/en/explanation/goodpractices.rst
index 51c0b960aed..bbc64ec662d 100644
--- a/doc/en/explanation/goodpractices.rst
+++ b/doc/en/explanation/goodpractices.rst
@@ -94,14 +94,13 @@ This has the following benefits:
For new projects, we recommend to use ``importlib`` :ref:`import mode `
(see which-import-mode_ for a detailed explanation).
-To this end, add the following to your ``pyproject.toml``:
+To this end, add the following to your configuration file:
.. code-block:: toml
- [tool.pytest.ini_options]
- addopts = [
- "--import-mode=importlib",
- ]
+ # content of pytest.toml
+ [pytest]
+ addopts = ["--import-mode=importlib"]
.. _src-layout:
@@ -126,12 +125,21 @@ which are better explained in this excellent `blog post`_ by Ionel Cristian Măr
PYTHONPATH=src pytest
or in a permanent manner by using the :confval:`pythonpath` configuration variable and adding the
- following to your ``pyproject.toml``:
+ following to your configuration file:
- .. code-block:: toml
+ .. tab:: toml
+
+ .. code-block:: toml
+
+ [pytest]
+ pythonpath = ["src"]
+
+ .. tab:: ini
+
+ .. code-block:: ini
- [tool.pytest.ini_options]
- pythonpath = "src"
+ [pytest]
+ pythonpath = src
.. note::
@@ -162,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
@@ -209,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.
@@ -313,3 +321,75 @@ A list of the lints detected by flake8-pytest-style can be found on its `PyPI pa
.. note::
flake8-pytest-style is not an official pytest project. Some of the rules enforce certain style choices, such as using `@pytest.fixture()` over `@pytest.fixture`, but you can configure the plugin to fit your preferred style.
+
+.. _`strict mode`:
+
+Using pytest's strict mode
+--------------------------
+
+.. versionadded:: 9.0
+
+Pytest contains a set of configuration options that make it more strict.
+The options are off by default for compatibility or other reasons,
+but you should enable them if you can.
+
+You can enable all of the strictness options at once by setting the :confval:`strict` configuration option:
+
+.. tab:: toml
+
+ .. code-block:: toml
+
+ [pytest]
+ strict = true
+
+.. tab:: ini
+
+ .. code-block:: ini
+
+ [pytest]
+ strict = true
+
+See the :confval:`strict` documentation for the options it enables and their effect.
+
+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:
+
+.. tab:: toml
+
+ .. code-block:: toml
+
+ [pytest]
+ strict_config = true
+ strict_markers = true
+ strict_parametrization_ids = true
+ strict_xfail = true
+
+.. tab:: ini
+
+ .. code-block:: ini
+
+ [pytest]
+ strict_config = true
+ strict_markers = true
+ 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:
+
+.. tab:: toml
+
+ .. code-block:: toml
+
+ [pytest]
+ strict = true
+ strict_parametrization_ids = false
+
+.. tab:: ini
+
+ .. code-block:: ini
+
+ [pytest]
+ strict = true
+ strict_parametrization_ids = false
diff --git a/doc/en/explanation/pythonpath.rst b/doc/en/explanation/pythonpath.rst
index e68f455cedf..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,12 +44,12 @@ 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 `.
Same as ``prepend``, requires test module names to be unique when the test directory tree is
- not arranged in packages, because the modules will put in :py:data:`sys.modules` after importing.
+ not arranged in packages, because the modules will be put in :py:data:`sys.modules` after importing.
.. _`import-mode-importlib`:
@@ -64,7 +64,7 @@ these values:
* Test modules can't import each other.
* Testing utility modules in the tests directories (for example a ``tests.helpers`` module containing test-related functions/classes)
- are not importable. The recommendation in this case it to place testing utility modules together with the application/library
+ are not importable. The recommendation in this case is to place testing utility modules together with the application/library
code, for example ``app.testing.helpers``.
Important: by "test utility modules", we mean functions/classes which are imported by
@@ -152,7 +152,7 @@ this case ``foo/``). To load the module, it will insert ``root/`` to the front
The same logic applies to the ``conftest.py`` file: it will be imported as ``foo.conftest`` module.
Preserving the full package name is important when tests live in a package to avoid problems
-and allow test modules to have duplicated names. This is also discussed in details in
+and allow test modules to have duplicated names. This is also discussed in detail in
:ref:`test discovery`.
Standalone test modules / ``conftest.py`` files
@@ -182,7 +182,7 @@ with the ``conftest.py`` file by adding ``root/foo`` to :py:data:`sys.path` to i
For this reason this layout cannot have test modules with the same name, as they all will be
imported in the global import namespace.
-This is also discussed in details in :ref:`test discovery`.
+This is also discussed in detail in :ref:`test discovery`.
.. _`pytest vs python -m pytest`:
diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst
index 41469de3864..3ba30a90b34 100644
--- a/doc/en/getting-started.rst
+++ b/doc/en/getting-started.rst
@@ -9,8 +9,6 @@ Get Started
Install ``pytest``
----------------------------------------
-``pytest`` requires: Python 3.8+ or PyPy3.
-
1. Run the following command in your command line:
.. code-block:: bash
@@ -22,7 +20,7 @@ Install ``pytest``
.. code-block:: bash
$ pytest --version
- pytest 8.3.5
+ pytest 9.0.2
.. _`simpletest`:
@@ -47,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
@@ -75,7 +73,7 @@ The ``[100%]`` refers to the overall progress of running all test cases. After i
Run multiple tests
----------------------------------------------------------
-``pytest`` will run all files of the form test_*.py or \*_test.py in the current directory and its subdirectories. More generally, it follows :ref:`standard test discovery rules `.
+``pytest`` will run all files of the form ``test_*.py`` or ``*_test.py`` in the current directory and its subdirectories. More generally, it follows :ref:`standard test discovery rules `.
Assert that a certain exception is raised
@@ -201,6 +199,26 @@ This is outlined below:
Note that attributes added at class level are *class attributes*, so they will be shared between tests.
+Compare floating-point values with pytest.approx
+--------------------------------------------------------------
+
+``pytest`` also provides a number of utilities to make writing tests easier.
+For example, you can use :func:`pytest.approx` to compare floating-point
+values that may have small rounding errors:
+
+.. code-block:: python
+
+ # content of test_approx.py
+ import pytest
+
+
+ def test_sum():
+ assert (0.1 + 0.2) == pytest.approx(0.3)
+
+This avoids the need for manual tolerance checks or using
+``math.isclose`` and works with scalars, lists, and NumPy arrays.
+
+
Request a unique temporary directory for functional tests
--------------------------------------------------------------
@@ -244,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 6bc8f6fed33..4ef2664b1d5 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
@@ -66,6 +66,33 @@ See :ref:`assert-details` for more information on assertion introspection.
.. _`assertraises`:
+Assertions about approximate equality
+-------------------------------------
+
+When comparing floating point values (or arrays of floats), small rounding
+errors are common. Instead of using ``assert abs(a - b) < tol`` or
+``numpy.isclose``, you can use :func:`pytest.approx`:
+
+.. code-block:: python
+
+ import pytest
+ import numpy as np
+
+
+ def test_floats():
+ assert (0.1 + 0.2) == pytest.approx(0.3)
+
+
+ def test_arrays():
+ a = np.array([1.0, 2.0, 3.0])
+ b = np.array([0.9999, 2.0001, 3.0])
+ assert a == pytest.approx(b)
+
+``pytest.approx`` works with scalars, lists, dictionaries, and NumPy arrays.
+It also supports comparisons involving NaNs.
+
+See :func:`pytest.approx` for details.
+
Assertions about expected exceptions
------------------------------------------
@@ -377,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
@@ -476,6 +503,50 @@ the conftest file:
FAILED test_foocompare.py::test_compare - assert Comparing Foo instances:
1 failed in 0.12s
+.. _`return-not-none`:
+
+Returning non-None value in test functions
+------------------------------------------
+
+A :class:`pytest.PytestReturnNotNoneWarning` is emitted when a test function returns a value other than ``None``.
+
+This helps prevent a common mistake made by beginners who assume that returning a ``bool`` (e.g., ``True`` or ``False``) will determine whether a test passes or fails.
+
+Example:
+
+.. code-block:: python
+
+ @pytest.mark.parametrize(
+ ["a", "b", "result"],
+ [
+ [1, 2, 5],
+ [2, 3, 8],
+ [5, 3, 18],
+ ],
+ )
+ def test_foo(a, b, result):
+ return foo(a, b) == result # Incorrect usage, do not do this.
+
+Since pytest ignores return values, it might be surprising that the test will never fail based on the returned value.
+
+The correct fix is to replace the ``return`` statement with an ``assert``:
+
+.. code-block:: python
+
+ @pytest.mark.parametrize(
+ ["a", "b", "result"],
+ [
+ [1, 2, 5],
+ [2, 3, 8],
+ [5, 3, 18],
+ ],
+ )
+ def test_foo(a, b, result):
+ assert foo(a, b) == result
+
+
+
+
.. _assert-details:
.. _`assert introspection`:
@@ -512,7 +583,7 @@ Note that you still get the benefits of assertion introspection, the only change
the ``.pyc`` files won't be cached on disk.
Additionally, rewriting will silently skip caching if it cannot write new ``.pyc`` files,
-i.e. in a read-only filesystem or a zipfile.
+e.g. in a read-only filesystem or a zipfile.
Disabling assert rewriting
@@ -528,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 a3b2a862534..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,13 +80,13 @@ 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
$ 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
@@ -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):
@@ -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
@@ -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,13 +275,13 @@ 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
$ 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 '*' ---------------------------
@@ -289,21 +289,19 @@ You can always peek at the content of the cache using the
{'test_caching.py::test_function': True}
cache/nodeids contains:
['test_caching.py::test_function']
- cache/stepwise contains:
- []
example/value contains:
42
========================== 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
$ 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/*' -----------------------
@@ -316,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
@@ -332,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 e6affd80ea1..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
@@ -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 4b1de6f3704..3f55467b434 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
@@ -66,6 +66,7 @@ as an error:
def test_one():
> assert api_v1() == 1
+ ^^^^^^^^
test_show_warnings.py:10:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
@@ -79,30 +80,32 @@ as an error:
FAILED test_show_warnings.py::test_one - UserWarning: api v1, should use ...
1 failed in 0.12s
-The same option can be set in the ``pytest.ini`` or ``pyproject.toml`` file using the
-``filterwarnings`` ini option. For example, the configuration below will ignore all
+The same option can be set in the configuration file using the
+:confval:`filterwarnings` configuration option. For example, the configuration below will ignore all
user warnings and specific deprecation warnings matching a regex, but will transform
all other warnings into errors.
-.. code-block:: ini
+.. tab:: toml
- # pytest.ini
- [pytest]
- filterwarnings =
- error
- ignore::UserWarning
- ignore:function ham\(\) is deprecated:DeprecationWarning
+ .. code-block:: toml
-.. code-block:: toml
+ [pytest]
+ filterwarnings = [
+ "error",
+ "ignore::UserWarning",
+ # note the use of single quote below to denote "raw" strings in TOML
+ 'ignore:function ham\(\) is deprecated:DeprecationWarning',
+ ]
+
+.. tab:: ini
- # pyproject.toml
- [tool.pytest.ini_options]
- filterwarnings = [
- "error",
- "ignore::UserWarning",
- # note the use of single quote below to denote "raw" strings in TOML
- 'ignore:function ham\(\) is deprecated:DeprecationWarning',
- ]
+ .. code-block:: ini
+
+ [pytest]
+ filterwarnings =
+ error
+ ignore::UserWarning
+ ignore:function ham\(\) is deprecated:DeprecationWarning
When a warning matches more than one option in the list, the action for the last matching option
@@ -111,7 +114,7 @@ is performed.
.. note::
- The ``-W`` flag and the ``filterwarnings`` ini option use warning filters that are
+ The ``-W`` flag and the :confval:`filterwarnings` configuration option use warning filters that are
similar in structure, but each configuration option interprets its filter
differently. For example, *message* in ``filterwarnings`` is a string containing a
regular expression that the start of the warning message must match,
@@ -168,7 +171,7 @@ You can specify multiple filters with separate decorators:
Filters applied using a mark take precedence over filters passed on the command line or configured
-by the :confval:`filterwarnings` ini option.
+by the :confval:`filterwarnings` configuration option.
You may apply a filter to all tests of a class by using the :ref:`filterwarnings ` mark as a class
decorator or to all tests in a module by setting the :globalvar:`pytestmark` variable:
@@ -195,13 +198,22 @@ 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
----------------------------------
-This plugin is enabled by default but can be disabled entirely in your ``pytest.ini`` file with:
+This plugin is enabled by default but can be disabled entirely in your configuration file with:
+
+.. tab:: toml
+
+ .. code-block:: toml
+
+ [pytest]
+ addopts = ["-p", "no:warnings"]
+
+.. tab:: ini
.. code-block:: ini
@@ -226,16 +238,27 @@ However, in the specific case where users capture any type of warnings in their
no warning will be displayed at all.
Sometimes it is useful to hide some specific deprecation warnings that happen in code that you have no control over
-(such as third-party libraries), in which case you might use the warning filters options (ini or marks) to ignore
+(such as third-party libraries), in which case you might use the warning filters options (configuration or marks) to ignore
those warnings.
For example:
-.. code-block:: ini
+.. tab:: toml
+
+ .. code-block:: toml
+
+ [pytest]
+ filterwarnings = [
+ 'ignore:.*U.*mode is deprecated:DeprecationWarning',
+ ]
+
+.. tab:: ini
+
+ .. code-block:: ini
- [pytest]
- filterwarnings =
- ignore:.*U.*mode is deprecated:DeprecationWarning
+ [pytest]
+ filterwarnings =
+ ignore:.*U.*mode is deprecated:DeprecationWarning
This will ignore all warnings of type ``DeprecationWarning`` where the start of the message matches
diff --git a/doc/en/how-to/doctest.rst b/doc/en/how-to/doctest.rst
index c2a6cc8e958..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:
@@ -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
@@ -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:
@@ -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
@@ -68,27 +68,34 @@ and functions, including from test modules:
============================ 2 passed in 0.12s =============================
You can make these changes permanent in your project by
-putting them into a pytest.ini file like this:
+putting them into a configuration file like this:
-.. code-block:: ini
+.. code-block:: toml
- # content of pytest.ini
+ # content of pytest.toml
[pytest]
- addopts = --doctest-modules
-
+ addopts = ["--doctest-modules"]
Encoding
--------
The default encoding is **UTF-8**, but you can specify the encoding
that will be used for those doctest files using the
-``doctest_encoding`` ini option:
+:confval:`doctest_encoding` configuration option:
-.. code-block:: ini
+.. tab:: toml
- # content of pytest.ini
- [pytest]
- doctest_encoding = latin1
+ .. code-block:: toml
+
+ [pytest]
+ doctest_encoding = "latin1"
+
+.. tab:: ini
+
+ .. code-block:: ini
+
+ [pytest]
+ doctest_encoding = latin1
.. _using doctest options:
@@ -102,10 +109,19 @@ configuration file.
For example, to make pytest ignore trailing whitespaces and ignore
lengthy exception stack traces you can just write:
-.. code-block:: ini
+.. tab:: toml
- [pytest]
- doctest_optionflags = NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL
+ .. code-block:: toml
+
+ [pytest]
+ doctest_optionflags = ["NORMALIZE_WHITESPACE", "IGNORE_EXCEPTION_DETAIL"]
+
+.. tab:: ini
+
+ .. code-block:: ini
+
+ [pytest]
+ doctest_optionflags = NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL
Alternatively, options can be enabled by an inline comment in the doc test
itself:
@@ -307,7 +323,7 @@ While the built-in pytest support provides a good set of functionalities for usi
doctests, if you use them extensively you might be interested in those external packages
which add many more features, and include pytest integration:
-* `pytest-doctestplus `__: provides
+* `pytest-doctestplus `__: provides
advanced doctest support and enables the testing of reStructuredText (".rst") files.
* `Sybil `__: provides a way to test examples in
diff --git a/doc/en/how-to/failures.rst b/doc/en/how-to/failures.rst
index b3d0c155b48..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:
@@ -112,7 +112,7 @@ on the command-line.
Also the :confval:`faulthandler_timeout=X` configuration option can be used
to dump the traceback of all threads if a test takes longer than ``X``
-seconds to finish (not available on Windows).
+seconds to finish.
.. note::
diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst
index 8f84e4867a6..5c5a239e8d4 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
@@ -449,6 +449,7 @@ marked ``smtp_connection`` fixture function. Running the test looks like this:
assert response == 250
assert b"smtp.gmail.com" in msg
> assert 0 # for demo purposes
+ ^^^^^^^^
E assert 0
test_module.py:7: AssertionError
@@ -460,6 +461,7 @@ marked ``smtp_connection`` fixture function. Running the test looks like this:
response, msg = smtp_connection.noop()
assert response == 250
> assert 0 # for demo purposes
+ ^^^^^^^^
E assert 0
test_module.py:13: AssertionError
@@ -771,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
@@ -805,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
@@ -1308,6 +1310,7 @@ So let's just do another run:
assert response == 250
assert b"smtp.gmail.com" in msg
> assert 0 # for demo purposes
+ ^^^^^^^^
E assert 0
test_module.py:7: AssertionError
@@ -1319,6 +1322,7 @@ So let's just do another run:
response, msg = smtp_connection.noop()
assert response == 250
> assert 0 # for demo purposes
+ ^^^^^^^^
E assert 0
test_module.py:13: AssertionError
@@ -1343,6 +1347,7 @@ So let's just do another run:
response, msg = smtp_connection.noop()
assert response == 250
> assert 0 # for demo purposes
+ ^^^^^^^^
E assert 0
test_module.py:13: AssertionError
@@ -1363,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
@@ -1414,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
-
+