Compare commits

..

66 Commits
main ... 7.4.x

Author SHA1 Message Date
James Frost 40d58e0ce7
Add html_baseurl to sphinx conf.py (#12364) (#12391)
This is used to set the <link rel="canonical" href="X"> tag that points to the canonical version of the webpage. Including this indicates to search engines which version to include in their indexes, and should prevent older versions showing up.

Fixes #12363
2024-05-30 08:08:19 -03:00
github-actions[bot] 549190651e
[7.4.x] doc: Remove sold out training (#11824)
Co-authored-by: Florian Bruhin <me@the-compiler.org>
2024-01-16 14:07:26 +00:00
github-actions[bot] cf72d1a40e
[7.4.x] doc: Update training dates and add pytest sprint (#11820)
Co-authored-by: Florian Bruhin <me@the-compiler.org>
2024-01-15 20:18:31 +00:00
Ran Benita 18dcd9d38d
Merge pull request #11752 from pytest-dev/release-7.4.4
Prepare release 7.4.4
2023-12-31 14:10:58 +02:00
pytest bot 33f694f4b3 Prepare release version 7.4.4 2023-12-31 10:17:27 +00:00
Ran Benita 76c107c463
Merge pull request #11751 from bluetech/backport-11143-to-7.4.x
(cherry picked from commit 084d756ae6)

[ran: adapted to 7.4.x, fixed changelog issue number]
2023-12-31 12:12:34 +02:00
github-actions[bot] 531d76daa4
[7.4.x] Improve reporting from __iter__ exceptions (#11749) 2023-12-31 12:11:02 +02:00
Zac Hatfield-Dodds a0f58fa9e7 Merge pull request #11143 from tushar-deepsource/patch-1
(cherry picked from commit 084d756ae6)

[ran: adapted to 7.4.x, fixed changelog issue number]
2023-12-31 11:53:19 +02:00
github-actions[bot] b1f3387d42
[7.4.x] #11091: documentation should use hypthonated properties (#11750) 2023-12-31 11:50:38 +02:00
Ran Benita 2cdd619bf4
Merge pull request #11747 from pytest-dev/backport-11711-to-7.4.x
[7.4.x] nodes: fix tracebacks from collection errors are not getting pruned
2023-12-31 11:15:21 +02:00
Ran Benita d06c05bd23 [7.4.x] nodes: fix tracebacks from collection errors are not getting pruned 2023-12-31 08:14:55 +00:00
github-actions[bot] 5582bfcddf
[7.4.x] Improves clarity in Sphinx documentation for function signature. (#11702)
Co-authored-by: Arthur Richard <arthur.richard2299@gmail.com>
2023-12-14 08:19:40 -03:00
github-actions[bot] 13024efd7a
[7.4.x] Fix for operation on closed file in faulthandler teardown (#11631)
Co-authored-by: Simon Blanchard <bnomis@gmail.com>
2023-11-22 20:25:29 +00:00
github-actions[bot] a40dacf657
[7.4.x] XFAIL TestLocalPath.test_make_numbered_dir_multiprocess_safe (#11616)
Co-authored-by: Miro Hrončok <miro@hroncok.cz>
2023-11-14 15:08:28 +00:00
Ran Benita 3550906ead
Merge pull request #11570 from pytest-dev/backport-11567-to-7.4.x
[7.4.x] doc/reference: fix sidebar TOC depth
2023-10-30 09:26:36 +02:00
Ran Benita bd068705b1 [7.4.x] doc/reference: fix sidebar TOC depth 2023-10-30 07:02:22 +00:00
Bruno Oliveira ec5bd27cc7
Update build-and-inspect-python-package action (#11561) (#11562)
This should fix the action for Python 3.12.

Ref: hynek/build-and-inspect-python-package#72
(cherry picked from commit 247436819a)
2023-10-27 10:36:51 -03:00
Bruno Oliveira a32feda04c
Fix tag name generated by deploy workflow (#11550) (#11554)
Traditionally pytest publishes tags in the form `X.Y.Z`, however the deploy workflow (copied from somewhere else) published tags in the form `vX.Y.Z`.

This is the root cause of #11548, because it tried to publish the release notes for tag `X.Y.Z` (which did not exist).

Fix #11548

(cherry picked from commit c1728948ac)
2023-10-25 13:28:22 -03:00
github-actions[bot] f8070ffb9b
[7.4.x] Add deploy instructions using the command-line (#11553)
Co-authored-by: Bruno Oliveira <nicoddemus@gmail.com>
2023-10-25 13:37:56 +00:00
Bruno Oliveira 53df6164b4
Merge pull request #11546 from pytest-dev/release-7.4.3
Prepare release 7.4.3
2023-10-24 16:38:09 -03:00
Bruno Oliveira 2390610696
Tweak changelog.rst 2023-10-24 15:45:08 -03:00
pytest bot a0714aa007 Prepare release version 7.4.3 2023-10-24 18:43:16 +00:00
github-actions[bot] 44ad1c9811
[7.4.x] fix #10447 - consider marks in reverse mro order to give base classes priority (#11545)
Co-authored-by: Ronny Pfannschmidt <opensource@ronnypfannschmidt.de>
2023-10-24 15:04:13 +00:00
github-actions[bot] 5dc77253d4
[7.4.x] Ensure logging tests always cleanup after themselves (#11541)
Co-authored-by: Bruno Oliveira <nicoddemus@gmail.com>
2023-10-23 14:28:04 +00:00
github-actions[bot] a517827318
[7.4.x] Configure ReadTheDocs to fail on warnings (#11540)
Co-authored-by: Bruno Oliveira <nicoddemus@gmail.com>
2023-10-23 13:23:18 +00:00
github-actions[bot] 21fe071d79
[7.4.x] fix for ValueError raised in faulthandler teardown code (#11455)
Co-authored-by: Simon Blanchard <bnomis@gmail.com>
2023-09-20 12:41:01 +00:00
Bruno Oliveira f8bb8572fe
Force terminal width when running tests (#11425) (#11432)
Related to #11423

(cherry picked from commit 241f2a890e)
2023-09-11 09:48:22 -03:00
github-actions[bot] 1944dc06d3
[7.4.x] Fix --import-mode=importlib when root contains `__init__.py` file (#11426)
Co-authored-by: Bruno Oliveira <nicoddemus@gmail.com>
2023-09-10 13:27:53 +00:00
Bruno Oliveira 946634c84c
Merge pull request #11419 from nicoddemus/backport-11414-to-7.4.x
[7.4.x] Fix assert rewriting with assignment expressions (#11414)
2023-09-09 10:08:41 -03:00
github-actions[bot] d849a3ed64
[7.4.x] fix: closes #11343's [attr-defined] type errors (#11421)
Co-authored-by: Warren Markham <rabbitsinwarrens@gmail.com>
2023-09-09 13:02:31 +00:00
Bruno Oliveira 721a0881fb Skip test_assertion_walrus_different_test_cases on Python 3.7 2023-09-09 09:43:15 -03:00
Marc Mueller 5341b9cd67 Fix assert rewriting with assignment expressions (#11414)
Fixes #11239

(cherry picked from commit 7259e8db98)
2023-09-09 09:13:10 -03:00
Bruno Oliveira c39bdf6190
Adjustments to the release process (#11410) (#11415)
As discussed in #11408:

* Improve documentation for the release process.
* Fix the description for the PRs created by the `prepare release pr` workflow.
* Fix pushing tag in the `deploy` workflow.

(cherry picked from commit e5c81fa41a)
2023-09-08 08:42:55 -03:00
Bruno Oliveira b0c4775a28
Merge pull request #11408 from pytest-dev/release-7.4.2
Prepare release 7.4.2
2023-09-07 15:47:56 -03:00
pytest bot 45f34dfb8d Prepare release version 7.4.2 2023-09-07 17:21:49 +00:00
Bruno Oliveira e4f022f0d8
Merge pull request #11406 from nicoddemus/backport-11404-to-7.4.x
[7.4.x] Fix crash when passing a very long cmdline argument (#11404)
2023-09-07 14:14:40 -03:00
Bruno Oliveira 63b0c6f75f Use _pytest.pathlib.safe_exists in get_dirs_from_args
Related to #11394
2023-09-07 13:50:02 -03:00
Bruno Oliveira 884b911a9c Fix crash when passing a very long cmdline argument (#11404)
Fixes #11394

(cherry picked from commit 28ccf476b9)
2023-09-07 12:54:41 -03:00
github-actions[bot] 6e49a74089
[7.4.x] Fix doctest collection of `functools.cached_property` objects. (#11403)
Co-authored-by: Ronny Pfannschmidt <opensource@ronnypfannschmidt.de>
2023-09-07 13:33:12 +00:00
github-actions[bot] 79c2012d40
[7.4.x] doc: Remove done training (#11400)
Co-authored-by: Florian Bruhin <me@the-compiler.org>
2023-09-06 13:50:00 +00:00
github-actions[bot] de69883e3a
[7.4.x] improve plugin list disclaimer (#11398)
Co-authored-by: Stefaan Lippens <soxofaan@users.noreply.github.com>
2023-09-06 11:02:29 +00:00
github-actions[bot] 1de00e9830
[7.4.x] Fix import_path for packages (#11395)
Co-authored-by: Bruno Oliveira <nicoddemus@gmail.com>
2023-09-05 23:07:48 +00:00
Bruno Oliveira 7f5d9b9df4
Fix user_properties not saved to XML if fixture errors during teardown (#11382)
Move handling of user_properties to `finalize()`.

Previously if a fixture failed during teardown, `pytest_runtest_logreport` would not be called with "teardown", resulting in the user properties not being saved on the JUnit XML file.

Fixes: #11367
(cherry picked from commit 917ce9aa01)

Co-authored-by: Israel Fruchter <israel.fruchter@gmail.com>
2023-09-03 15:01:56 -03:00
Bruno Oliveira 82eb86f707
Merge pull request #11377 from pytest-dev/release-7.4.1
Prepare release 7.4.1
2023-09-02 12:41:32 -03:00
Bruno Oliveira 0319a0d4fd Checkout source code during deploy
We need the checked out repository in order to push the tag.
2023-09-02 12:38:39 -03:00
Bruno Oliveira 7855a72d2c Improve CI workflow
* Build the package only once, and test on all platforms.
* Deploy is now triggered manually via an Action, which is then responsible for tagging the repository after the package has been uploaded successfully.
* Drop 'docs': we nowadays rely on readthedocs preview PR builds.
2023-09-02 08:46:22 -03:00
pytest bot 7a0a0e8b08 Prepare release version 7.4.1 2023-09-02 11:03:06 +00:00
github-actions[bot] fbcfd3a52e
[7.4.x] Update CONTRIBUTING.rst (#11371)
Co-authored-by: Sourabh Beniwal <sourabhbeniwal@outlook.com>
2023-08-30 08:57:49 -03:00
github-actions[bot] b170081788
[7.4.x] Issue 11354 fixing docs for lfnf (#11364)
Co-authored-by: Sean Patrick Malloy <spmalloy@ucdavis.edu>
2023-08-29 00:40:49 +00:00
Ran Benita 7a5f2feefb
[7.4.x] Fixes for typed pluggy (#11355)
Since version 1.3 pluggy added typing, which requires some fixes to
please mypy.
2023-08-26 22:15:32 +00:00
github-actions[bot] 69140717d4
[7.4.x] Improve duplicate values documentation (#11296)
Co-authored-by: Bruno Oliveira <nicoddemus@gmail.com>
2023-08-08 14:44:03 +03:00
Bruno Oliveira 5c7c3f6329
Merge pull request #11294 from The-Compiler/pluggy-py38
ci: Use Python 3.8 to test latest pluggy
2023-08-07 08:13:03 -03:00
Florian Bruhin ba40975bb7 ci: Use Python 3.8 to test latest pluggy
Pluggy dropped Python 3.7 support.
Also see 165fbbd12a

Fixes #11293
2023-08-07 12:08:56 +02:00
github-actions[bot] e3fe7286f8
[7.4.x] doc: Link pytest.main to how-to guide (#11290)
Co-authored-by: Florian Bruhin <me@the-compiler.org>
2023-08-07 10:47:37 +02:00
github-actions[bot] 34c73944e1
[7.4.x] doc: update information about assertion messages (#11286)
Co-authored-by: Christoph Anton Mitterer <mail@christoph.anton.mitterer.name>
2023-08-07 10:47:12 +02:00
github-actions[bot] 350122abb2
[7.4.x] Remove ep2023 training (#11242)
Co-authored-by: Florian Bruhin <me@the-compiler.org>
2023-07-22 18:40:56 +00:00
github-actions[bot] 06ff7ca13b
[7.4.x] Clarify docs for pytest.main default behavior (#11188)
Co-authored-by: antosikv <79337398+antosikv@users.noreply.github.com>
2023-07-09 15:54:59 +00:00
github-actions[bot] 6dfe498c77
[7.4.x] doc: fix EncodingWarnings in examples (#11182)
Co-authored-by: Ran Benita <ran@unusedvar.com>
2023-07-08 19:17:21 +00:00
github-actions[bot] a566b78730
[7.4.x] reference: improve the node types docs a bit (#11181)
Co-authored-by: Bruno Oliveira <nicoddemus@gmail.com>
2023-07-08 19:07:55 +00:00
github-actions[bot] 511adf85be
[7.4.x] Fix error assertion handling in approx when None in dict comparison (#11180)
Co-authored-by: Zac Hatfield-Dodds <zac.hatfield.dodds@gmail.com>
2023-07-08 18:37:35 +00:00
github-actions[bot] c71b5df734
[7.4.x] Add child modules as attributes of parent modules. (#11163)
* [7.4.x] Add child modules as attributes of parent modules.

* Update 10337.bugfix.rst

---------

Co-authored-by: akhilramkee <31619526+akhilramkee@users.noreply.github.com>
Co-authored-by: Bruno Oliveira <nicoddemus@gmail.com>
2023-07-08 15:11:26 -03:00
github-actions[bot] d53951836d
[7.4.x] Update open trainings (#11172)
Co-authored-by: Florian Bruhin <me@the-compiler.org>
2023-07-04 21:49:24 +00:00
github-actions[bot] a4d7254d18
[7.4.x] Fix duplicated imports with importlib mode and doctest-modules (#11164)
Co-authored-by: Bruno Oliveira <nicoddemus@gmail.com>
2023-07-03 16:33:47 +00:00
Bruno Oliveira b6c55787fe
Switch to deploy environment and configure for pypi oidc (#10925) (#11162)
Closes #10871
Closes #10870

Co-authored-by: Ronny Pfannschmidt <opensource@ronnypfannschmidt.de>
2023-07-03 16:17:02 +00:00
Ran Benita fb03d1388b
Merge pull request #11131 from pytest-dev/release-7.4.0
Prepare release 7.4.0
2023-06-23 14:18:43 +03:00
pytest bot d9bf9dbec1 Prepare release version 7.4.0
[ran: made some fixups]
2023-06-23 14:03:58 +03:00
386 changed files with 11246 additions and 21643 deletions

View File

@ -29,5 +29,3 @@ exclude_lines =
^\s*if TYPE_CHECKING: ^\s*if TYPE_CHECKING:
^\s*@overload( |$) ^\s*@overload( |$)
^\s*@pytest\.mark\.xfail

View File

@ -23,13 +23,6 @@ afc607cfd81458d4e4f3b1f3cf8cc931b933907e
5f95dce95602921a70bfbc7d8de2f7712c5e4505 5f95dce95602921a70bfbc7d8de2f7712c5e4505
# ran pyupgrade-docs again # ran pyupgrade-docs again
75d0b899bbb56d6849e9d69d83a9426ed3f43f8b 75d0b899bbb56d6849e9d69d83a9426ed3f43f8b
# move argument parser to own file # move argument parser to own file
c9df77cbd6a365dcb73c39618e4842711817e871 c9df77cbd6a365dcb73c39618e4842711817e871
# Replace reorder-python-imports by isort due to black incompatibility (#11896)
8b54596639f41dfac070030ef20394b9001fe63c
# Run blacken-docs with black's 2024's style
4546d5445aaefe6a03957db028c263521dfb5c4b
# Migration to ruff / ruff format
4588653b2497ed25976b7aaff225b889fb476756
# Use format specifiers instead of percent format
4788165e69d08e10fc6b9c0124083fb358e2e9b0

View File

@ -1,20 +0,0 @@
---
branch-protection-check-name: Changelog entry
action-hints:
check-title-prefix: "Chronographer: "
external-docs-url: >-
https://docs.pytest.org/en/latest/contributing.html#preparing-pull-requests
inline-markdown: >-
See
https://docs.pytest.org/en/latest/contributing.html#preparing-pull-requests
for details.
enforce-name:
suffix: .rst
exclude:
humans:
- pyup-bot
labels:
skip-changelog: skip news
...

View File

@ -1,7 +0,0 @@
---
backport_branch_prefix: patchback/backports/
backport_label_prefix: 'backport ' # IMPORTANT: the labels are space-delimited
# target_branch_prefix: '' # The project's backport branches are non-prefixed
...

51
.github/workflows/backport.yml vendored Normal file
View File

@ -0,0 +1,51 @@
name: backport
on:
# Note that `pull_request_target` has security implications:
# https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
# In particular:
# - Only allow triggers that can be used only be trusted users
# - Don't execute any code from the target branch
# - Don't use cache
pull_request_target:
types: [labeled]
# Set permissions at the job level.
permissions: {}
jobs:
backport:
if: startsWith(github.event.label.name, 'backport ') && github.event.pull_request.merged
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
persist-credentials: true
- name: Create backport PR
run: |
set -eux
git config --global user.name "pytest bot"
git config --global user.email "pytestbot@gmail.com"
label='${{ github.event.label.name }}'
target_branch="${label#backport }"
backport_branch=backport-${{ github.event.number }}-to-"${target_branch}"
subject="[$target_branch] $(gh pr view --json title -q .title ${{ github.event.number }})"
git checkout origin/"${target_branch}" -b "${backport_branch}"
git cherry-pick -x --mainline 1 ${{ github.event.pull_request.merge_commit_sha }}
git commit --amend --message "$subject"
git push --set-upstream origin --force-with-lease "${backport_branch}"
gh pr create \
--base "${target_branch}" \
--title "${subject}" \
--body "Backport of PR #${{ github.event.number }} to $target_branch branch. PR created by backport workflow."
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -19,21 +19,14 @@ jobs:
SETUPTOOLS_SCM_PRETEND_VERSION: ${{ github.event.inputs.version }} SETUPTOOLS_SCM_PRETEND_VERSION: ${{ github.event.inputs.version }}
timeout-minutes: 10 timeout-minutes: 10
# Required by attest-build-provenance-github.
permissions:
id-token: write
attestations: write
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
persist-credentials: false persist-credentials: false
- name: Build and Check Package - name: Build and Check Package
uses: hynek/build-and-inspect-python-package@v2.6.0 uses: hynek/build-and-inspect-python-package@v1.5.3
with:
attest-build-provenance-github: 'true'
deploy: deploy:
if: github.repository == 'pytest-dev/pytest' if: github.repository == 'pytest-dev/pytest'
@ -45,16 +38,16 @@ jobs:
id-token: write id-token: write
contents: write contents: write
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Download Package - name: Download Package
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: Packages name: Packages
path: dist path: dist
- name: Publish package to PyPI - name: Publish package to PyPI
uses: pypa/gh-action-pypi-publish@v1.9.0 uses: pypa/gh-action-pypi-publish@v1.8.5
- name: Push tag - name: Push tag
run: | run: |
@ -74,35 +67,24 @@ jobs:
permissions: permissions:
contents: write contents: write
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
persist-credentials: false persist-credentials: false
- name: Download Package
uses: actions/download-artifact@v4
with:
name: Packages
path: dist
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v5 uses: actions/setup-python@v4
with: with:
python-version: "3.11" python-version: "3.10"
- name: Install tox - name: Install tox
run: | run: |
python -m pip install --upgrade pip python -m pip install --upgrade pip
pip install --upgrade tox pip install --upgrade tox
- name: Generate release notes - name: Publish GitHub release notes
env:
GH_RELEASE_NOTES_TOKEN: ${{ github.token }}
run: | run: |
sudo apt-get install pandoc sudo apt-get install pandoc
tox -e generate-gh-release-notes -- ${{ github.event.inputs.version }} scripts/latest-release-notes.md tox -e publish-gh-release-notes
- name: Publish GitHub Release
uses: softprops/action-gh-release@v2
with:
body_path: scripts/latest-release-notes.md
files: dist/*
tag_name: ${{ github.event.inputs.version }}

View File

@ -27,12 +27,12 @@ jobs:
pull-requests: write pull-requests: write
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v5 uses: actions/setup-python@v4
with: with:
python-version: "3.8" python-version: "3.8"

View File

@ -10,14 +10,14 @@ jobs:
permissions: permissions:
issues: write issues: write
steps: steps:
- uses: actions/stale@v9 - uses: actions/stale@v8
with: with:
debug-only: false debug-only: false
days-before-issue-stale: 14 days-before-issue-stale: 14
days-before-issue-close: 7 days-before-issue-close: 7
only-labels: "status: needs information" only-labels: "status: needs information"
stale-issue-label: "stale" stale-issue-label: "stale"
stale-issue-message: "This issue is stale because it has the `status: needs information` label and requested follow-up information was not provided for 14 days." stale-issue-message: "This issue is stale because it has been open for 14 days with no activity."
close-issue-message: "This issue was closed because it has the `status: needs information` label and follow-up information has not been provided for 7 days since being marked as stale." close-issue-message: "This issue was closed because it has been inactive for 7 days since being marked as stale."
days-before-pr-stale: -1 days-before-pr-stale: -1
days-before-pr-close: -1 days-before-pr-close: -1

View File

@ -14,11 +14,6 @@ on:
branches: branches:
- main - main
- "[0-9]+.[0-9]+.x" - "[0-9]+.[0-9]+.x"
types:
- opened # default
- synchronize # default
- reopened # default
- ready_for_review # used in PRs created from the release workflow
env: env:
PYTEST_ADDOPTS: "--color=yes" PYTEST_ADDOPTS: "--color=yes"
@ -35,12 +30,12 @@ jobs:
package: package:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
persist-credentials: false persist-credentials: false
- name: Build and Check Package - name: Build and Check Package
uses: hynek/build-and-inspect-python-package@v2.6.0 uses: hynek/build-and-inspect-python-package@v1.5.3
build: build:
needs: [package] needs: [package]
@ -54,35 +49,38 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
name: [ name: [
"windows-py37",
"windows-py38", "windows-py38",
"windows-py38-pluggy", "windows-py38-pluggy",
"windows-py39", "windows-py39",
"windows-py310", "windows-py310",
"windows-py311", "windows-py311",
"windows-py312", "windows-py312",
"windows-py313",
"ubuntu-py37",
"ubuntu-py37-freeze",
"ubuntu-py38", "ubuntu-py38",
"ubuntu-py38-pluggy", "ubuntu-py38-pluggy",
"ubuntu-py38-freeze",
"ubuntu-py39", "ubuntu-py39",
"ubuntu-py310", "ubuntu-py310",
"ubuntu-py311", "ubuntu-py311",
"ubuntu-py312", "ubuntu-py312",
"ubuntu-py313",
"ubuntu-pypy3", "ubuntu-pypy3",
"macos-py38", "macos-py37",
"macos-py39", "macos-py39",
"macos-py310", "macos-py310",
"macos-py312", "macos-py312",
"macos-py313",
"doctesting", "doctesting",
"plugins", "plugins",
] ]
include: include:
- name: "windows-py37"
python: "3.7"
os: windows-latest
tox_env: "py37-numpy"
- name: "windows-py38" - name: "windows-py38"
python: "3.8" python: "3.8"
os: windows-latest os: windows-latest
@ -105,27 +103,27 @@ jobs:
os: windows-latest os: windows-latest
tox_env: "py311" tox_env: "py311"
- name: "windows-py312" - name: "windows-py312"
python: "3.12" python: "3.12-dev"
os: windows-latest os: windows-latest
tox_env: "py312" tox_env: "py312"
- name: "windows-py313"
python: "3.13-dev"
os: windows-latest
tox_env: "py313"
- name: "ubuntu-py37"
python: "3.7"
os: ubuntu-latest
tox_env: "py37-lsof-numpy-pexpect"
use_coverage: true
- name: "ubuntu-py37-freeze"
python: "3.7"
os: ubuntu-latest
tox_env: "py37-freeze"
- name: "ubuntu-py38" - name: "ubuntu-py38"
python: "3.8" python: "3.8"
os: ubuntu-latest os: ubuntu-latest
tox_env: "py38-lsof-numpy-pexpect" tox_env: "py38-xdist"
use_coverage: true
- name: "ubuntu-py38-pluggy" - name: "ubuntu-py38-pluggy"
python: "3.8" python: "3.8"
os: ubuntu-latest os: ubuntu-latest
tox_env: "py38-pluggymain-pylib-xdist" tox_env: "py38-pluggymain-pylib-xdist"
- name: "ubuntu-py38-freeze"
python: "3.8"
os: ubuntu-latest
tox_env: "py38-freeze"
- name: "ubuntu-py39" - name: "ubuntu-py39"
python: "3.9" python: "3.9"
os: ubuntu-latest os: ubuntu-latest
@ -140,24 +138,19 @@ jobs:
tox_env: "py311" tox_env: "py311"
use_coverage: true use_coverage: true
- name: "ubuntu-py312" - name: "ubuntu-py312"
python: "3.12" python: "3.12-dev"
os: ubuntu-latest os: ubuntu-latest
tox_env: "py312" tox_env: "py312"
use_coverage: true use_coverage: true
- name: "ubuntu-py313"
python: "3.13-dev"
os: ubuntu-latest
tox_env: "py313"
use_coverage: true
- name: "ubuntu-pypy3" - name: "ubuntu-pypy3"
python: "pypy-3.8" python: "pypy-3.7"
os: ubuntu-latest os: ubuntu-latest
tox_env: "pypy3-xdist" tox_env: "pypy3-xdist"
- name: "macos-py38" - name: "macos-py37"
python: "3.8" python: "3.7"
os: macos-latest os: macos-latest
tox_env: "py38-xdist" tox_env: "py37-xdist"
- name: "macos-py39" - name: "macos-py39"
python: "3.9" python: "3.9"
os: macos-latest os: macos-latest
@ -168,59 +161,35 @@ jobs:
os: macos-latest os: macos-latest
tox_env: "py310-xdist" tox_env: "py310-xdist"
- name: "macos-py312" - name: "macos-py312"
python: "3.12" python: "3.12-dev"
os: macos-latest os: macos-latest
tox_env: "py312-xdist" tox_env: "py312-xdist"
- name: "macos-py313"
python: "3.13-dev"
os: macos-latest
tox_env: "py313-xdist"
- name: "plugins" - name: "plugins"
python: "3.12" python: "3.9"
os: ubuntu-latest os: ubuntu-latest
tox_env: "plugins" tox_env: "plugins"
- name: "doctesting" - name: "doctesting"
python: "3.8" python: "3.7"
os: ubuntu-latest os: ubuntu-latest
tox_env: "doctesting" tox_env: "doctesting"
use_coverage: true use_coverage: true
continue-on-error: >-
${{
contains(
fromJSON(
'[
"windows-py38-pluggy",
"windows-py313",
"ubuntu-py38-pluggy",
"ubuntu-py38-freeze",
"ubuntu-py313",
"macos-py38",
"macos-py313"
]'
),
matrix.name
)
&& true
|| false
}}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
persist-credentials: false persist-credentials: false
- name: Download Package - name: Download Package
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: Packages name: Packages
path: dist path: dist
- name: Set up Python ${{ matrix.python }} - name: Set up Python ${{ matrix.python }}
uses: actions/setup-python@v5 uses: actions/setup-python@v4
with: with:
python-version: ${{ matrix.python }} python-version: ${{ matrix.python }}
check-latest: ${{ endsWith(matrix.python, '-dev') }} check-latest: ${{ endsWith(matrix.python, '-dev') }}
@ -246,22 +215,9 @@ jobs:
- name: Upload coverage to Codecov - name: Upload coverage to Codecov
if: "matrix.use_coverage" if: "matrix.use_coverage"
uses: codecov/codecov-action@v4 uses: codecov/codecov-action@v3
continue-on-error: true
with: with:
fail_ci_if_error: false fail_ci_if_error: true
files: ./coverage.xml files: ./coverage.xml
verbose: true verbose: true
check: # This job does nothing and is only used for the branch protection
if: always()
needs:
- build
runs-on: ubuntu-latest
steps:
- name: Decide whether the needed jobs succeeded or failed
uses: re-actors/alls-green@223e4bb7a751b91f43eda76992bcfbf23b8b0302
with:
jobs: ${{ toJSON(needs) }}

View File

@ -20,34 +20,25 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Setup Python - name: Setup Python
uses: actions/setup-python@v5 uses: actions/setup-python@v4
with: with:
python-version: "3.11" python-version: 3.8
cache: pip
- name: requests-cache
uses: actions/cache@v4
with:
path: ~/.cache/pytest-plugin-list/
key: plugins-http-cache-${{ github.run_id }} # Can use time based key as well
restore-keys: plugins-http-cache-
- name: Install dependencies - name: Install dependencies
run: | run: |
python -m pip install --upgrade pip python -m pip install --upgrade pip
pip install packaging requests tabulate[widechars] tqdm requests-cache platformdirs pip install packaging requests tabulate[widechars] tqdm
- name: Update Plugin List - name: Update Plugin List
run: python scripts/update-plugin-list.py run: python scripts/update-plugin-list.py
- name: Create Pull Request - name: Create Pull Request
id: pr uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38
uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c
with: with:
commit-message: '[automated] Update plugin list' commit-message: '[automated] Update plugin list'
author: 'pytest bot <pytestbot@users.noreply.github.com>' author: 'pytest bot <pytestbot@users.noreply.github.com>'
@ -56,13 +47,3 @@ jobs:
branch-suffix: short-commit-hash branch-suffix: short-commit-hash
title: '[automated] Update plugin list' title: '[automated] Update plugin list'
body: '[automated] Update plugin list' body: '[automated] Update plugin list'
draft: true
- name: Instruct the maintainers to trigger CI by undrafting the PR
env:
GITHUB_TOKEN: ${{ github.token }}
run: >-
gh pr comment
--body 'Please mark the PR as ready for review to trigger PR checks.'
--repo '${{ github.repository }}'
'${{ steps.pr.outputs.pull-request-number }}'

2
.gitignore vendored
View File

@ -25,6 +25,7 @@ src/_pytest/_version.py
doc/*/_build doc/*/_build
doc/*/.doctrees doc/*/.doctrees
doc/*/_changelog_towncrier_draft.rst
build/ build/
dist/ dist/
*.egg-info *.egg-info
@ -50,7 +51,6 @@ coverage.xml
.settings .settings
.vscode .vscode
__pycache__/ __pycache__/
.python-version
# generated by pip # generated by pip
pip-wheel-metadata/ pip-wheel-metadata/

View File

@ -1,62 +1,77 @@
repos: repos:
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/psf/black
rev: "v0.4.10" rev: 23.3.0
hooks: hooks:
- id: ruff - id: black
args: ["--fix"] args: [--safe, --quiet]
- id: ruff-format - repo: https://github.com/asottile/blacken-docs
rev: 1.14.0
hooks:
- id: blacken-docs
additional_dependencies: [black==23.1.0]
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0 rev: v4.4.0
hooks: hooks:
- id: trailing-whitespace - id: trailing-whitespace
- id: end-of-file-fixer - id: end-of-file-fixer
- id: fix-encoding-pragma
args: [--remove]
- id: check-yaml - id: check-yaml
- repo: https://github.com/adamchainz/blacken-docs - id: debug-statements
rev: 1.16.0 exclude: _pytest/(debugging|hookspec).py
language_version: python3
- repo: https://github.com/PyCQA/autoflake
rev: v2.1.1
hooks: hooks:
- id: blacken-docs - id: autoflake
additional_dependencies: [black==24.1.1] name: autoflake
args: ["--in-place", "--remove-unused-variables", "--remove-all-unused-imports"]
language: python
files: \.py$
- repo: https://github.com/PyCQA/flake8
rev: 6.0.0
hooks:
- id: flake8
language_version: python3
additional_dependencies:
- flake8-typing-imports==1.12.0
- flake8-docstrings==1.5.0
- repo: https://github.com/asottile/reorder-python-imports
rev: v3.10.0
hooks:
- id: reorder-python-imports
args: ['--application-directories=.:src', --py37-plus]
- repo: https://github.com/asottile/pyupgrade
rev: v3.7.0
hooks:
- id: pyupgrade
args: [--py37-plus]
- repo: https://github.com/asottile/setup-cfg-fmt
rev: v2.3.0
hooks:
- id: setup-cfg-fmt
args: ["--max-py-version=3.12", "--include-version-classifiers"]
- repo: https://github.com/pre-commit/pygrep-hooks - repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.10.0 rev: v1.10.0
hooks: hooks:
- id: python-use-type-annotations - id: python-use-type-annotations
- repo: https://github.com/pre-commit/mirrors-mypy - repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.10.0 rev: v1.3.0
hooks: hooks:
- id: mypy - id: mypy
files: ^(src/|testing/|scripts/) files: ^(src/|testing/)
args: [] args: []
additional_dependencies: additional_dependencies:
- iniconfig>=1.1.0 - iniconfig>=1.1.0
- attrs>=19.2.0 - attrs>=19.2.0
- pluggy>=1.5.0
- packaging - packaging
- tomli - tomli
- types-pkg_resources - types-pkg_resources
- types-tabulate
# for mypy running on python>=3.11 since exceptiongroup is only a dependency # for mypy running on python>=3.11 since exceptiongroup is only a dependency
# on <3.11 # on <3.11
- exceptiongroup>=1.0.0rc8 - exceptiongroup>=1.0.0rc8
- repo: https://github.com/tox-dev/pyproject-fmt
rev: "2.1.3"
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.16.0
hooks:
- id: pyupgrade
stages: [manual]
- repo: local - repo: local
hooks: hooks:
- id: pylint
name: pylint
entry: pylint
language: system
types: [python]
args: ["-rn", "-sn", "--fail-on=I"]
stages: [manual]
- id: rst - id: rst
name: rst name: rst
entry: rst-lint --encoding utf-8 entry: rst-lint --encoding utf-8
@ -66,50 +81,9 @@ repos:
- id: changelogs-rst - id: changelogs-rst
name: changelog filenames name: changelog filenames
language: fail language: fail
entry: >- entry: 'changelog files must be named ####.(breaking|bugfix|deprecation|doc|feature|improvement|trivial|vendor).rst'
changelog files must be named exclude: changelog/(\d+\.(breaking|bugfix|deprecation|doc|feature|improvement|trivial|vendor).rst|README.rst|_template.rst)
####.(
breaking
| deprecation
| feature
| improvement
| bugfix
| vendor
| doc
| packaging
| contrib
| misc
)(.#)?(.rst)?
exclude: >-
(?x)
^
changelog/(
\.gitignore
|\d+\.(
breaking
|deprecation
|feature
|improvement
|bugfix
|vendor
|doc
|packaging
|contrib
|misc
)(\.\d+)?(\.rst)?
|README\.rst
|_template\.rst
)
$
files: ^changelog/ files: ^changelog/
- id: changelogs-user-role
name: Changelog files should use a non-broken :user:`name` role
language: pygrep
entry: :user:([^`]+`?|`[^`]+[\s,])
pass_filenames: true
types:
- file
- rst
- id: py-deprecated - id: py-deprecated
name: py library is deprecated name: py library is deprecated
language: pygrep language: pygrep

View File

@ -14,16 +14,11 @@ sphinx:
fail_on_warning: true fail_on_warning: true
build: build:
os: ubuntu-24.04 os: ubuntu-20.04
tools: tools:
python: >- python: "3.9"
3.12
apt_packages: apt_packages:
- inkscape - inkscape
jobs:
post_checkout:
- git fetch --unshallow || true
- git fetch --tags || true
formats: formats:
- epub - epub

47
AUTHORS
View File

@ -11,7 +11,6 @@ Adam Johnson
Adam Stewart Adam Stewart
Adam Uhlir Adam Uhlir
Ahn Ki-Wook Ahn Ki-Wook
Akhilesh Ramakrishnan
Akiomi Kamakura Akiomi Kamakura
Alan Velasco Alan Velasco
Alessio Izzo Alessio Izzo
@ -36,7 +35,6 @@ Andrey Paramonov
Andrzej Klajnert Andrzej Klajnert
Andrzej Ostrowski Andrzej Ostrowski
Andy Freeland Andy Freeland
Anita Hammer
Anthon van der Neut Anthon van der Neut
Anthony Shaw Anthony Shaw
Anthony Sottile Anthony Sottile
@ -55,14 +53,10 @@ Aviral Verma
Aviv Palivoda Aviv Palivoda
Babak Keyvani Babak Keyvani
Barney Gale Barney Gale
Ben Brown
Ben Gartner Ben Gartner
Ben Leith
Ben Webb Ben Webb
Benjamin Peterson Benjamin Peterson
Benjamin Schubert
Bernard Pratz Bernard Pratz
Bo Wu
Bob Ippolito Bob Ippolito
Brian Dorsey Brian Dorsey
Brian Larsen Brian Larsen
@ -95,14 +89,12 @@ Christopher Dignam
Christopher Gilling Christopher Gilling
Claire Cecil Claire Cecil
Claudio Madotto Claudio Madotto
Clément M.T. Robert
CrazyMerlyn CrazyMerlyn
Cristian Vera Cristian Vera
Cyrus Maden Cyrus Maden
Damian Skrzypczak Damian Skrzypczak
Daniel Grana Daniel Grana
Daniel Hahler Daniel Hahler
Daniel Miller
Daniel Nuri Daniel Nuri
Daniel Sánchez Castelló Daniel Sánchez Castelló
Daniel Valenzuela Zenteno Daniel Valenzuela Zenteno
@ -120,7 +112,6 @@ Daw-Ran Liou
Debi Mishra Debi Mishra
Denis Kirisov Denis Kirisov
Denivy Braiam Rück Denivy Braiam Rück
Dheeraj C K
Dhiren Serai Dhiren Serai
Diego Russo Diego Russo
Dmitry Dygalo Dmitry Dygalo
@ -131,8 +122,6 @@ Edison Gustavo Muenz
Edoardo Batini Edoardo Batini
Edson Tadeu M. Manoel Edson Tadeu M. Manoel
Eduardo Schettino Eduardo Schettino
Edward Haigh
Eero Vaher
Eli Boyarski Eli Boyarski
Elizaveta Shashkova Elizaveta Shashkova
Éloi Rivard Éloi Rivard
@ -140,24 +129,18 @@ Endre Galaczi
Eric Hunsberger Eric Hunsberger
Eric Liu Eric Liu
Eric Siegerman Eric Siegerman
Eric Yuan
Erik Aronesty Erik Aronesty
Erik Hasse
Erik M. Bray Erik M. Bray
Evan Kepner Evan Kepner
Evgeny Seliverstov Evgeny Seliverstov
Fabian Sturm
Fabien Zarifian Fabien Zarifian
Fabio Zadrozny Fabio Zadrozny
Farbod Ahmadian
faph
Felix Hofstätter Felix Hofstätter
Felix Nieuwenhuizen Felix Nieuwenhuizen
Feng Ma Feng Ma
Florian Bruhin Florian Bruhin
Florian Dahlitz Florian Dahlitz
Floris Bruynooghe Floris Bruynooghe
Fraser Stark
Gabriel Landau Gabriel Landau
Gabriel Reis Gabriel Reis
Garvit Shubham Garvit Shubham
@ -202,7 +185,6 @@ Javier Romero
Jeff Rackauckas Jeff Rackauckas
Jeff Widman Jeff Widman
Jenni Rinker Jenni Rinker
Jens Tröger
John Eddie Ayson John Eddie Ayson
John Litborn John Litborn
John Towler John Towler
@ -213,7 +195,6 @@ Jordan Guymon
Jordan Moldow Jordan Moldow
Jordan Speicher Jordan Speicher
Joseph Hunkeler Joseph Hunkeler
Joseph Sawaya
Josh Karpel Josh Karpel
Joshua Bronson Joshua Bronson
Jurko Gospodnetić Jurko Gospodnetić
@ -242,11 +223,9 @@ Kyle Altendorf
Lawrence Mitchell Lawrence Mitchell
Lee Kamentsky Lee Kamentsky
Lev Maximov Lev Maximov
Levon Saldamli
Lewis Cowles Lewis Cowles
Llandy Riveron Del Risco Llandy Riveron Del Risco
Loic Esteve Loic Esteve
lovetheguitar
Lukas Bednar Lukas Bednar
Luke Murphy Luke Murphy
Maciek Fijalkowski Maciek Fijalkowski
@ -258,11 +237,9 @@ Marc Mueller
Marc Schlaich Marc Schlaich
Marcelo Duarte Trevisani Marcelo Duarte Trevisani
Marcin Bachry Marcin Bachry
Marc Bresson
Marco Gorelli Marco Gorelli
Mark Abramowitz Mark Abramowitz
Mark Dickinson Mark Dickinson
Mark Vong
Marko Pacak Marko Pacak
Markus Unterwaditzer Markus Unterwaditzer
Martijn Faassen Martijn Faassen
@ -283,29 +260,21 @@ Michael Droettboom
Michael Goerz Michael Goerz
Michael Krebs Michael Krebs
Michael Seifert Michael Seifert
Michael Vogt
Michal Wajszczuk Michal Wajszczuk
Michał Górny
Michał Zięba Michał Zięba
Mickey Pashov Mickey Pashov
Mihai Capotă Mihai Capotă
Mihail Milushev
Mike Hoyle (hoylemd) Mike Hoyle (hoylemd)
Mike Lundy Mike Lundy
Milan Lesnek
Miro Hrončok Miro Hrončok
mrbean-bremen
Nathan Goldbaum
Nathaniel Compton Nathaniel Compton
Nathaniel Waisbrot Nathaniel Waisbrot
Ned Batchelder Ned Batchelder
Neil Martin
Neven Mundar Neven Mundar
Nicholas Devenish Nicholas Devenish
Nicholas Murphy Nicholas Murphy
Niclas Olofsson Niclas Olofsson
Nicolas Delaby Nicolas Delaby
Nico Vidal
Nikolay Kondratyev Nikolay Kondratyev
Nipunn Koorapati Nipunn Koorapati
Oleg Pidsadnyi Oleg Pidsadnyi
@ -318,7 +287,6 @@ Ondřej Súkup
Oscar Benjamin Oscar Benjamin
Parth Patel Parth Patel
Patrick Hayes Patrick Hayes
Patrick Lannigan
Paul Müller Paul Müller
Paul Reece Paul Reece
Pauli Virtanen Pauli Virtanen
@ -331,7 +299,6 @@ Pierre Sassoulas
Pieter Mulder Pieter Mulder
Piotr Banaszkiewicz Piotr Banaszkiewicz
Piotr Helm Piotr Helm
Poulami Sau
Prakhar Gurunani Prakhar Gurunani
Prashant Anand Prashant Anand
Prashant Sharma Prashant Sharma
@ -348,7 +315,6 @@ Raphael Pierzina
Rafal Semik Rafal Semik
Raquel Alegre Raquel Alegre
Ravi Chandra Ravi Chandra
Reagan Lee
Robert Holt Robert Holt
Roberto Aldera Roberto Aldera
Roberto Polli Roberto Polli
@ -359,26 +325,20 @@ Ronny Pfannschmidt
Ross Lawley Ross Lawley
Ruaridh Williamson Ruaridh Williamson
Russel Winder Russel Winder
Russell Martin
Ryan Puddephatt Ryan Puddephatt
Ryan Wooden Ryan Wooden
Sadra Barikbin
Saiprasad Kale Saiprasad Kale
Samuel Colvin Samuel Colvin
Samuel Dion-Girardeau Samuel Dion-Girardeau
Samuel Jirovec
Samuel Searles-Bryant Samuel Searles-Bryant
Samuel Therrien (Avasam)
Samuele Pedroni Samuele Pedroni
Sanket Duthade Sanket Duthade
Sankt Petersbug Sankt Petersbug
Saravanan Padmanaban Saravanan Padmanaban
Sean Malloy
Segev Finer Segev Finer
Serhii Mozghovyi Serhii Mozghovyi
Seth Junot Seth Junot
Shantanu Jain Shantanu Jain
Sharad Nair
Shubham Adep Shubham Adep
Simon Blanchard Simon Blanchard
Simon Gomizelj Simon Gomizelj
@ -395,13 +355,11 @@ Stefano Taschini
Steffen Allner Steffen Allner
Stephan Obermann Stephan Obermann
Sven-Hendrik Haase Sven-Hendrik Haase
Sviatoslav Sydorenko
Sylvain Marié Sylvain Marié
Tadek Teleżyński Tadek Teleżyński
Takafumi Arakaki Takafumi Arakaki
Taneli Hukkinen Taneli Hukkinen
Tanvi Mehta Tanvi Mehta
Tanya Agarwal
Tarcisio Fischer Tarcisio Fischer
Tareq Alayan Tareq Alayan
Tatiana Ovary Tatiana Ovary
@ -430,14 +388,12 @@ Victor Rodriguez
Victor Uriarte Victor Uriarte
Vidar T. Fauske Vidar T. Fauske
Vijay Arora Vijay Arora
Virendra Patil
Virgil Dupras Virgil Dupras
Vitaly Lashmanov Vitaly Lashmanov
Vivaan Verma Vivaan Verma
Vlad Dragos Vlad Dragos
Vlad Radziuk Vlad Radziuk
Vladyslav Rachek Vladyslav Rachek
Volodymyr Kochetkov
Volodymyr Piskun Volodymyr Piskun
Wei Lin Wei Lin
Wil Cooley Wil Cooley
@ -448,14 +404,11 @@ Xixi Zhao
Xuan Luong Xuan Luong
Xuecong Liao Xuecong Liao
Yannick Péroux Yannick Péroux
Yao Xiao
Yoav Caspi Yoav Caspi
Yuliang Shao Yuliang Shao
Yusuke Kadowaki Yusuke Kadowaki
Yutian Li
Yuval Shimon Yuval Shimon
Zac Hatfield-Dodds Zac Hatfield-Dodds
Zach Snicker
Zachary Kneupper Zachary Kneupper
Zachary OBrien Zachary OBrien
Zhouxin Qiu Zhouxin Qiu

View File

@ -1,10 +1,14 @@
============================ ============================
Contributing Contribution getting started
============================ ============================
Contributions are highly welcomed and appreciated. Every little bit of help counts, Contributions are highly welcomed and appreciated. Every little bit of help counts,
so do not hesitate! so do not hesitate!
.. contents::
:depth: 2
:backlinks: none
.. _submitfeedback: .. _submitfeedback:
@ -124,7 +128,7 @@ For example:
Submitting Plugins to pytest-dev Submitting Plugins to pytest-dev
-------------------------------- --------------------------------
Development of the pytest core, support code, and some plugins happens Pytest development of the core, some plugins and support code happens
in repositories living under the ``pytest-dev`` organisations: in repositories living under the ``pytest-dev`` organisations:
- `pytest-dev on GitHub <https://github.com/pytest-dev>`_ - `pytest-dev on GitHub <https://github.com/pytest-dev>`_
@ -193,12 +197,11 @@ Short version
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
#. Fork the repository. #. Fork the repository.
#. Fetch tags from upstream if necessary (if you cloned only main `git fetch --tags https://github.com/pytest-dev/pytest`).
#. Enable and install `pre-commit <https://pre-commit.com>`_ to ensure style-guides and code checks are followed. #. Enable and install `pre-commit <https://pre-commit.com>`_ to ensure style-guides and code checks are followed.
#. Follow `PEP-8 <https://www.python.org/dev/peps/pep-0008/>`_ for naming. #. Follow **PEP-8** for naming and `black <https://github.com/psf/black>`_ for formatting.
#. Tests are run using ``tox``:: #. Tests are run using ``tox``::
tox -e linting,py39 tox -e linting,py37
The test environments above are usually enough to cover most cases locally. The test environments above are usually enough to cover most cases locally.
@ -233,7 +236,6 @@ Here is a simple overview, with pytest-specific bits:
$ git clone git@github.com:YOUR_GITHUB_USERNAME/pytest.git $ git clone git@github.com:YOUR_GITHUB_USERNAME/pytest.git
$ cd pytest $ cd pytest
$ git fetch --tags https://github.com/pytest-dev/pytest
# now, create your own branch off "main": # now, create your own branch off "main":
$ git checkout -b your-bugfix-branch-name main $ git checkout -b your-bugfix-branch-name main
@ -270,35 +272,35 @@ Here is a simple overview, with pytest-specific bits:
#. Run all the tests #. Run all the tests
You need to have Python 3.8 or later available in your system. Now You need to have Python 3.7 available in your system. Now
running tests is as simple as issuing this command:: running tests is as simple as issuing this command::
$ tox -e linting,py39 $ tox -e linting,py37
This command will run tests via the "tox" tool against Python 3.9 This command will run tests via the "tox" tool against Python 3.7
and also perform "lint" coding-style checks. 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 <https://www.python.org/dev/peps/pep-0008/>`_ for naming. #. 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.7 and pass options to pytest
(e.g. enter pdb on failure) to pytest you can do:: (e.g. enter pdb on failure) to pytest you can do::
$ tox -e py39 -- --pdb $ tox -e py37 -- --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.7::
$ tox -e py39 -- testing/test_config.py $ tox -e py37 -- testing/test_config.py
When committing, ``pre-commit`` will re-format the files if necessary. When committing, ``pre-commit`` will re-format the files if necessary.
#. If instead of using ``tox`` you prefer to run the tests directly, then we suggest to create a virtual environment and use #. If instead of using ``tox`` you prefer to run the tests directly, then we suggest to create a virtual environment and use
an editable install with the ``dev`` extra:: an editable install with the ``testing`` extra::
$ python3 -m venv .venv $ python3 -m venv .venv
$ source .venv/bin/activate # Linux $ source .venv/bin/activate # Linux
$ .venv/Scripts/activate.bat # Windows $ .venv/Scripts/activate.bat # Windows
$ pip install -e ".[dev]" $ pip install -e ".[testing]"
Afterwards, you can edit the files and run pytest normally:: Afterwards, you can edit the files and run pytest normally::

View File

@ -20,13 +20,16 @@
:target: https://codecov.io/gh/pytest-dev/pytest :target: https://codecov.io/gh/pytest-dev/pytest
:alt: Code coverage Status :alt: Code coverage Status
.. image:: https://github.com/pytest-dev/pytest/actions/workflows/test.yml/badge.svg .. image:: https://github.com/pytest-dev/pytest/workflows/test/badge.svg
:target: https://github.com/pytest-dev/pytest/actions?query=workflow%3Atest :target: https://github.com/pytest-dev/pytest/actions?query=workflow%3Atest
.. image:: https://results.pre-commit.ci/badge/github/pytest-dev/pytest/main.svg .. image:: https://results.pre-commit.ci/badge/github/pytest-dev/pytest/main.svg
:target: https://results.pre-commit.ci/latest/github/pytest-dev/pytest/main :target: https://results.pre-commit.ci/latest/github/pytest-dev/pytest/main
:alt: pre-commit.ci status :alt: pre-commit.ci status
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/psf/black
.. image:: https://www.codetriage.com/pytest-dev/pytest/badges/users.svg .. image:: https://www.codetriage.com/pytest-dev/pytest/badges/users.svg
:target: https://www.codetriage.com/pytest-dev/pytest :target: https://www.codetriage.com/pytest-dev/pytest
@ -94,12 +97,12 @@ Features
- `Modular fixtures <https://docs.pytest.org/en/stable/explanation/fixtures.html>`_ for - `Modular fixtures <https://docs.pytest.org/en/stable/explanation/fixtures.html>`_ for
managing small or parametrized long-lived test resources managing small or parametrized long-lived test resources
- Can run `unittest <https://docs.pytest.org/en/stable/how-to/unittest.html>`_ (or trial) - Can run `unittest <https://docs.pytest.org/en/stable/how-to/unittest.html>`_ (or trial),
test suites out of the box `nose <https://docs.pytest.org/en/stable/how-to/nose.html>`_ test suites out of the box
- Python 3.8+ or PyPy3 - Python 3.7+ or PyPy3
- Rich plugin architecture, with over 1300+ `external plugins <https://docs.pytest.org/en/latest/reference/plugin_list.html>`_ and thriving community - Rich plugin architecture, with over 850+ `external plugins <https://docs.pytest.org/en/latest/reference/plugin_list.html>`_ and thriving community
Documentation Documentation

View File

@ -23,9 +23,9 @@ members of the `contributors team`_ interested in receiving funding.
The current list of contributors receiving funding are: The current list of contributors receiving funding are:
* `@asottile`_
* `@nicoddemus`_ * `@nicoddemus`_
* `@The-Compiler`_ * `@The-Compiler`_
* `@RonnyPfannschmidt`_
Contributors interested in receiving a part of the funds just need to submit a PR adding their Contributors interested in receiving a part of the funds just need to submit a PR adding their
name to the list. Contributors that want to stop receiving the funds should also submit a PR name to the list. Contributors that want to stop receiving the funds should also submit a PR
@ -55,6 +55,6 @@ funds. Just drop a line to one of the `@pytest-dev/tidelift-admins`_ or use the
.. _`@pytest-dev/tidelift-admins`: https://github.com/orgs/pytest-dev/teams/tidelift-admins/members .. _`@pytest-dev/tidelift-admins`: https://github.com/orgs/pytest-dev/teams/tidelift-admins/members
.. _`agreement`: https://tidelift.com/docs/lifting/agreement .. _`agreement`: https://tidelift.com/docs/lifting/agreement
.. _`@asottile`: https://github.com/asottile
.. _`@nicoddemus`: https://github.com/nicoddemus .. _`@nicoddemus`: https://github.com/nicoddemus
.. _`@The-Compiler`: https://github.com/The-Compiler .. _`@The-Compiler`: https://github.com/The-Compiler
.. _`@RonnyPfannschmidt`: https://github.com/RonnyPfannschmidt

View File

@ -1,16 +1,12 @@
from __future__ import annotations
import sys import sys
if __name__ == "__main__": if __name__ == "__main__":
import cProfile import cProfile
import pytest # NOQA
import pstats import pstats
import pytest # noqa: F401
script = sys.argv[1:] if len(sys.argv) > 1 else ["empty.py"] script = sys.argv[1:] if len(sys.argv) > 1 else ["empty.py"]
cProfile.run(f"pytest.cmdline.main({script!r})", "prof") cProfile.run("pytest.cmdline.main(%r)" % script, "prof")
p = pstats.Stats("prof") p = pstats.Stats("prof")
p.strip_dirs() p.strip_dirs()
p.sort_stats("cumulative") p.sort_stats("cumulative")

View File

@ -2,11 +2,8 @@
# 2.7.5 3.3.2 # 2.7.5 3.3.2
# FilesCompleter 75.1109 69.2116 # FilesCompleter 75.1109 69.2116
# FastFilesCompleter 0.7383 1.0760 # FastFilesCompleter 0.7383 1.0760
from __future__ import annotations
import timeit import timeit
imports = [ imports = [
"from argcomplete.completers import FilesCompleter as completer", "from argcomplete.completers import FilesCompleter as completer",
"from _pytest._argcomplete import FastFilesCompleter as completer", "from _pytest._argcomplete import FastFilesCompleter as completer",

View File

@ -1,5 +1,2 @@
from __future__ import annotations
for i in range(1000): for i in range(1000):
exec("def test_func_%d(): pass" % i) exec("def test_func_%d(): pass" % i)

View File

@ -1,5 +1,3 @@
from __future__ import annotations
import pytest import pytest

View File

@ -1,8 +1,5 @@
from __future__ import annotations
import pytest import pytest
SKIP = True SKIP = True

View File

@ -1,8 +1,5 @@
from __future__ import annotations
from unittest import TestCase # noqa: F401 from unittest import TestCase # noqa: F401
for i in range(15000): for i in range(15000):
exec( exec(
f""" f"""

View File

@ -1,6 +1,3 @@
from __future__ import annotations
for i in range(5000): for i in range(5000):
exec( exec(
f""" f"""

34
changelog/.gitignore vendored
View File

@ -1,34 +0,0 @@
*
!.gitignore
!_template.rst
!README.rst
!*.bugfix
!*.bugfix.rst
!*.bugfix.*.rst
!*.breaking
!*.breaking.rst
!*.breaking.*.rst
!*.contrib
!*.contrib.rst
!*.contrib.*.rst
!*.deprecation
!*.deprecation.rst
!*.deprecation.*.rst
!*.doc
!*.doc.rst
!*.doc.*.rst
!*.feature
!*.feature.rst
!*.feature.*.rst
!*.improvement
!*.improvement.rst
!*.improvement.*.rst
!*.misc
!*.misc.rst
!*.misc.*.rst
!*.packaging
!*.packaging.rst
!*.packaging.*.rst
!*.vendor
!*.vendor.rst
!*.vendor.*.rst

View File

@ -1,4 +0,0 @@
Fix reporting of teardown errors in higher-scoped fixtures when using `--maxfail` or `--stepwise`.
Originally added in pytest 8.0.0, but reverted in 8.0.2 due to a regression in pytest-xdist.
This regression was fixed in pytest-xdist 3.6.1.

View File

@ -1 +0,0 @@
:func:`pytest.approx` now correctly handles :class:`Sequence <collections.abc.Sequence>`-like objects.

View File

@ -1 +0,0 @@
Documented using :envvar:`PYTEST_VERSION` to detect if code is running from within a pytest run.

View File

@ -1,11 +0,0 @@
Fixed a regression in pytest 8.0 where tracebacks get longer and longer when multiple
tests fail due to a shared higher-scope fixture which raised -- by :user:`bluetech`.
Also fixed a similar regression in pytest 5.4 for collectors which raise during setup.
The fix necessitated internal changes which may affect some plugins:
* ``FixtureDef.cached_result[2]`` is now a tuple ``(exc, tb)``
instead of ``exc``.
* ``SetupState.stack`` failures are now a tuple ``(exc, tb)``
instead of ``exc``.

View File

@ -1,11 +0,0 @@
Added `--xfail-tb` flag, which turns on traceback output for XFAIL results.
* If the `--xfail-tb` flag is not sent, tracebacks for XFAIL results are NOT shown.
* The style of traceback for XFAIL is set with `--tb`, and can be `auto|long|short|line|native|no`.
* Note: Even if you have `--xfail-tb` set, you won't see them if `--tb=no`.
Some history:
With pytest 8.0, `-rx` or `-ra` would not only turn on summary reports for xfail, but also report the tracebacks for xfail results. This caused issues with some projects that utilize xfail, but don't want to see all of the xfail tracebacks.
This change detaches xfail tracebacks from `-rx`, and now we turn on xfail tracebacks with `--xfail-tb`. With this, the default `-rx`/ `-ra` behavior is identical to pre-8.0 with respect to xfail tracebacks. While this is a behavior change, it brings default behavior back to pre-8.0.0 behavior, which ultimately was considered the better course of action.

View File

@ -1 +0,0 @@
12204.bugfix.rst

View File

@ -1 +0,0 @@
Fix collection error upon encountering an :mod:`abstract <abc>` class, including abstract `unittest.TestCase` subclasses.

View File

@ -1,8 +0,0 @@
Added support for keyword matching in marker expressions.
Now tests can be selected by marker keyword arguments.
Supported values are :class:`int`, (unescaped) :class:`str`, :class:`bool` & :data:`None`.
See :ref:`marker examples <marker_keyword_expression_example>` for more information.
-- by :user:`lovetheguitar`

View File

@ -1 +0,0 @@
Fix a regression in pytest 8.0.0 where package-scoped parameterized items were not correctly reordered to minimize setups/teardowns in some cases.

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

@ -0,0 +1 @@
The documentation webpages now links to a canonical version to reduce outdated documentation in search engine results.

View File

@ -1 +0,0 @@
Fix crash with `assert testcase is not None` assertion failure when re-running unittest tests using plugins like pytest-rerunfailures. Regressed in 8.2.2.

View File

@ -1,3 +0,0 @@
Migrated all internal type-annotations to the python3.10+ style by using the `annotations` future import.
-- by :user:`RonnyPfannschmidt`

View File

@ -1,6 +0,0 @@
The external plugin mentions in the documentation now avoid mentioning
:std:doc:`setuptools entry-points <setuptools:index>` as the concept is
much more generic nowadays. Instead, the terminology of "external",
"installed", or "third-party" plugins (or packages) replaces that.
-- by :user:`webknjaz`

View File

@ -1,4 +0,0 @@
The console output now uses the "third-party plugins" terminology,
replacing the previously established but confusing and outdated
reference to :std:doc:`setuptools <setuptools:index>`
-- by :user:`webknjaz`.

View File

@ -1 +0,0 @@
Fixed a crash when returning category ``"error"`` or ``"failed"`` with a custom test status from :hook:`pytest_report_teststatus` hook -- :user:`pbrezina`.

View File

@ -1,13 +0,0 @@
The change log draft preview integration has been refactored to use a
third party extension ``sphinxcontib-towncrier``. The previous in-repo
script was putting the change log preview file at
:file:`doc/en/_changelog_towncrier_draft.rst`. Said file is no longer
ignored in Git and might show up among untracked files in the
development environments of the contributors. To address that, the
contributors can run the following command that will clean it up:
.. code-block:: console
$ git clean -x -i -- doc/en/_changelog_towncrier_draft.rst
-- by :user:`webknjaz`

View File

@ -1,5 +0,0 @@
All the undocumented ``tox`` environments now have descriptions.
They can be listed in one's development environment by invoking
``tox -av`` in a terminal.
-- by :user:`webknjaz`

View File

@ -1,11 +0,0 @@
The changelog configuration has been updated to introduce more accurate
audience-tailored categories. Previously, there was a ``trivial``
change log fragment type with an unclear and broad meaning. It was
removed and we now have ``contrib``, ``misc`` and ``packaging`` in
place of it.
The new change note types target the readers who are downstream
packagers and project contributors. Additionally, the miscellaneous
section is kept for unspecified updates that do not fit anywhere else.
-- by :user:`webknjaz`

View File

@ -1,7 +0,0 @@
The UX of the GitHub automation making pull requests to update the
plugin list has been updated. Previously, the maintainers had to close
the automatically created pull requests and re-open them to trigger the
CI runs. From now on, they only need to click the `Ready for review`
button instead.
-- by :user:`webknjaz`

View File

@ -1 +0,0 @@
Improve handling of invalid regex patterns in :func:`pytest.raises(match=r'...') <pytest.raises>` by providing a clear error message.

View File

@ -1,4 +0,0 @@
The ``:pull:`` RST role has been replaced with a shorter
``:pr:`` due to starting to use the implementation from
the third-party :pypi:`sphinx-issues` Sphinx extension
-- by :user:`webknjaz`.

View File

@ -1,6 +0,0 @@
The coverage reporting configuration has been updated to exclude
pytest's own tests marked as expected to fail from the coverage
report. This has an effect of reducing the influence of flaky
tests on the resulting number.
-- by :user:`webknjaz`

View File

@ -1,7 +0,0 @@
The ``extlinks`` Sphinx extension is no longer enabled. The ``:bpo:``
role it used to declare has been removed with that. BPO itself has
migrated to GitHub some years ago and it is possible to link the
respective issues by using their GitHub issue numbers and the
``:issue:`` role that the ``sphinx-issues`` extension implements.
-- by :user:`webknjaz`

View File

@ -1,3 +0,0 @@
The ``_in_venv()`` function now detects Python virtual environments by
checking for a :file:`pyvenv.cfg` file, ensuring reliable detection on
various platforms -- by :user:`zachsnickers`.

View File

@ -1 +0,0 @@
12544.improvement.rst

View File

@ -1,2 +0,0 @@
Possible typos in using the ``:user:`` RST role is now being linted
through the pre-commit tool integration -- by :user:`webknjaz`.

View File

@ -1 +0,0 @@
Do not truncate arguments to functions in output when running with `-vvv`.

View File

@ -1,38 +0,0 @@
The readability of assertion introspection of bound methods has been enhanced
-- by :user:`farbodahm`, :user:`webknjaz`, :user:`obestwalter`, :user:`flub`
and :user:`glyphack`.
Earlier, it was like:
.. code-block:: console
=================================== FAILURES ===================================
_____________________________________ test _____________________________________
def test():
> assert Help().fun() == 2
E assert 1 == 2
E + where 1 = <bound method Help.fun of <example.Help instance at 0x256a830>>()
E + where <bound method Help.fun of <example.Help instance at 0x256a830>> = <example.Help instance at 0x256a830>.fun
E + where <example.Help instance at 0x256a830> = Help()
example.py:7: AssertionError
=========================== 1 failed in 0.03 seconds ===========================
And now it's like:
.. code-block:: console
=================================== FAILURES ===================================
_____________________________________ test _____________________________________
def test():
> assert Help().fun() == 2
E assert 1 == 2
E + where 1 = fun()
E + where fun = <test_local.Help object at 0x1074be230>.fun
E + where <test_local.Help object at 0x1074be230> = Help()
test_local.py:13: AssertionError
=========================== 1 failed in 0.03 seconds ===========================

View File

@ -1 +0,0 @@
Fixed progress percentages (the ``[ 87%]`` at the edge of the screen) sometimes not aligning correctly when running with pytest-xdist ``-n``.

View File

@ -1 +0,0 @@
Added timezone information to the testsuite timestamp in the JUnit XML report.

View File

@ -20,22 +20,10 @@ Each file should be named like ``<ISSUE>.<TYPE>.rst``, where
* ``deprecation``: feature deprecation. * ``deprecation``: feature deprecation.
* ``breaking``: a change which may break existing suites, such as feature removal or behavior change. * ``breaking``: a change which may break existing suites, such as feature removal or behavior change.
* ``vendor``: changes in packages vendored in pytest. * ``vendor``: changes in packages vendored in pytest.
* ``packaging``: notes for downstreams about unobvious side effects * ``trivial``: fixing a small typo or internal change that might be noteworthy.
and tooling. changes in the test invocation considerations and
runtime assumptions.
* ``contrib``: stuff that affects the contributor experience. e.g.
Running tests, building the docs, setting up the development
environment.
* ``misc``: changes that are hard to assign to any of the above
categories.
So for example: ``123.feature.rst``, ``456.bugfix.rst``. So for example: ``123.feature.rst``, ``456.bugfix.rst``.
.. tip::
See :file:`pyproject.toml` for all available categories
(``tool.towncrier.type``).
If your PR fixes an issue, use that number here. If there is no issue, If your PR fixes an issue, use that number here. If there is no issue,
then after you submit the PR and get the PR number you can add a then after you submit the PR and get the PR number you can add a
changelog using that instead. changelog using that instead.

View File

@ -1,9 +1,4 @@
# reference: https://docs.codecov.io/docs/codecovyml-reference # reference: https://docs.codecov.io/docs/codecovyml-reference
---
codecov:
token: 1eca3b1f-31a2-4fb8-a8c3-138b441b50a7 #repo token
coverage: coverage:
status: status:
patch: true patch: true

View File

@ -1,7 +0,0 @@
<style>
.logo {text-align: center;}
</style>
<a class="logo" href="{{ pathto('contents') }}">
<img src="{{ pathto('_static/pytest1.png', 1) }}" width="70%" height="70%" text="Pytest Logo"/>
</a>

View File

@ -0,0 +1,15 @@
{#
basic/searchbox.html with heading removed.
#}
{%- if pagename != "search" and builder != "singlehtml" %}
<div id="searchbox" style="display: none" role="search">
<div class="searchformwrapper">
<form class="search" action="{{ pathto('search') }}" method="get">
<input type="text" name="q" aria-labelledby="searchlabel"
placeholder="Search"/>
<input type="submit" value="{{ _('Go') }}" />
</form>
</div>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
{%- endif %}

View File

@ -1,7 +0,0 @@
<style>
ul {list-style: none;}
li {margin: 0.4em 0;}
@media (min-width: 46em) {
#features {width: 50%;}
}
</style>

View File

@ -44,7 +44,7 @@ Partner projects, sign up here! (by 22 March)
What does it mean to "adopt pytest"? What does it mean to "adopt pytest"?
----------------------------------------- -----------------------------------------
There can be many different definitions of "success". Pytest can run many unittest_ tests by default, so using pytest as your testrunner may be possible from day 1. Job done, right? There can be many different definitions of "success". Pytest can run many nose_ and unittest_ tests by default, so using pytest as your testrunner may be possible from day 1. Job done, right?
Progressive success might look like: Progressive success might look like:
@ -62,6 +62,7 @@ Progressive success might look like:
It may be after the month is up, the partner project decides that pytest is not right for it. That's okay - hopefully the pytest team will also learn something about its weaknesses or deficiencies. It may be after the month is up, the partner project decides that pytest is not right for it. That's okay - hopefully the pytest team will also learn something about its weaknesses or deficiencies.
.. _nose: nose.html
.. _unittest: unittest.html .. _unittest: unittest.html
.. _assert: assert.html .. _assert: assert.html
.. _pycmd: https://bitbucket.org/hpk42/pycmd/overview .. _pycmd: https://bitbucket.org/hpk42/pycmd/overview

View File

@ -6,17 +6,6 @@ Release announcements
:maxdepth: 2 :maxdepth: 2
release-8.2.2
release-8.2.1
release-8.2.0
release-8.1.2
release-8.1.1
release-8.1.0
release-8.0.2
release-8.0.1
release-8.0.0
release-8.0.0rc2
release-8.0.0rc1
release-7.4.4 release-7.4.4
release-7.4.3 release-7.4.3
release-7.4.2 release-7.4.2

View File

@ -62,7 +62,7 @@ New Features
- new "-q" option which decreases verbosity and prints a more - new "-q" option which decreases verbosity and prints a more
nose/unittest-style "dot" output. nose/unittest-style "dot" output.
- many, many, more detailed improvements details - many many more detailed improvements details
Fixes Fixes
----------------------- -----------------------
@ -109,7 +109,7 @@ Important Notes
in conftest.py files. They will cause nothing special. in conftest.py files. They will cause nothing special.
- removed support for calling the pre-1.0 collection API of "run()" and "join" - removed support for calling the pre-1.0 collection API of "run()" and "join"
- removed reading option values from conftest.py files or env variables. - removed reading option values from conftest.py files or env variables.
This can now be done much, much, better and easier through the ini-file This can now be done much much better and easier through the ini-file
mechanism and the "addopts" entry in particular. mechanism and the "addopts" entry in particular.
- removed the "disabled" attribute in test classes. Use the skipping - removed the "disabled" attribute in test classes. Use the skipping
and pytestmark mechanism to skip or xfail a test class. and pytestmark mechanism to skip or xfail a test class.

View File

@ -4,7 +4,7 @@ pytest-2.2.2: bug fixes
pytest-2.2.2 (updated to 2.2.3 to fix packaging issues) is a minor pytest-2.2.2 (updated to 2.2.3 to fix packaging issues) is a minor
backward-compatible release of the versatile py.test testing tool. It backward-compatible release of the versatile py.test testing tool. It
contains bug fixes and a few refinements particularly to reporting with contains bug fixes and a few refinements particularly to reporting with
"--collectonly", see below for details. "--collectonly", see below for betails.
For general information see here: For general information see here:

View File

@ -181,7 +181,7 @@ Bug fixes:
partially failed (finalizers would not always be called before) partially failed (finalizers would not always be called before)
- fix issue320 - fix class scope for fixtures when mixed with - fix issue320 - fix class scope for fixtures when mixed with
module-level functions. Thanks Anatoly Bubenkoff. module-level functions. Thanks Anatloy Bubenkoff.
- you can specify "-q" or "-qq" to get different levels of "quieter" - you can specify "-q" or "-qq" to get different levels of "quieter"
reporting (thanks Katarzyna Jachim) reporting (thanks Katarzyna Jachim)

View File

@ -83,7 +83,7 @@ holger krekel
Thanks Ralph Schmitt for the precise failure example. Thanks Ralph Schmitt for the precise failure example.
- fix issue244 by implementing special index for parameters to only use - fix issue244 by implementing special index for parameters to only use
indices for parametrized test ids indices for paramentrized test ids
- fix issue287 by running all finalizers but saving the exception - fix issue287 by running all finalizers but saving the exception
from the first failing finalizer and re-raising it so teardown will from the first failing finalizer and re-raising it so teardown will

View File

@ -73,7 +73,7 @@ holger krekel
- cleanup setup.py a bit and specify supported versions. Thanks Jurko - cleanup setup.py a bit and specify supported versions. Thanks Jurko
Gospodnetic for the PR. Gospodnetic for the PR.
- change XPASS colour to yellow rather than red when tests are run - change XPASS colour to yellow rather then red when tests are run
with -v. with -v.
- fix issue473: work around mock putting an unbound method into a class - fix issue473: work around mock putting an unbound method into a class

View File

@ -55,7 +55,7 @@ holger krekel
github. See https://pytest.org/en/stable/contributing.html . github. See https://pytest.org/en/stable/contributing.html .
Thanks to Anatoly for pushing and initial work on this. Thanks to Anatoly for pushing and initial work on this.
- fix issue650: new option ``--doctest-ignore-import-errors`` which - fix issue650: new option ``--docttest-ignore-import-errors`` which
will turn import errors in doctests into skips. Thanks Charles Cloud will turn import errors in doctests into skips. Thanks Charles Cloud
for the complete PR. for the complete PR.

View File

@ -45,7 +45,7 @@ The py.test Development Team
**New Features** **New Features**
* New ``pytest.mark.skip`` mark, which unconditionally skips marked tests. * New ``pytest.mark.skip`` mark, which unconditionally skips marked tests.
Thanks :user:`MichaelAquilina` for the complete PR (:pr:`1040`). Thanks :user:`MichaelAquilina` for the complete PR (:pull:`1040`).
* ``--doctest-glob`` may now be passed multiple times in the command-line. * ``--doctest-glob`` may now be passed multiple times in the command-line.
Thanks :user:`jab` and :user:`nicoddemus` for the PR. Thanks :user:`jab` and :user:`nicoddemus` for the PR.

View File

@ -44,7 +44,7 @@ The py.test Development Team
Thanks :user:`nicoddemus` for the PR. Thanks :user:`nicoddemus` for the PR.
* Fix (:issue:`469`): junit parses report.nodeid incorrectly, when params IDs * Fix (:issue:`469`): junit parses report.nodeid incorrectly, when params IDs
contain ``::``. Thanks :user:`tomviner` for the PR (:pr:`1431`). contain ``::``. Thanks :user:`tomviner` for the PR (:pull:`1431`).
* Fix (:issue:`578`): SyntaxErrors * Fix (:issue:`578`): SyntaxErrors
containing non-ascii lines at the point of failure generated an internal containing non-ascii lines at the point of failure generated an internal

View File

@ -44,14 +44,14 @@ The py.test Development Team
* Fix Xfail does not work with condition keyword argument. * Fix Xfail does not work with condition keyword argument.
Thanks :user:`astraw38` for reporting the issue (:issue:`1496`) and :user:`tomviner` Thanks :user:`astraw38` for reporting the issue (:issue:`1496`) and :user:`tomviner`
for PR the (:pr:`1524`). for PR the (:pull:`1524`).
* Fix win32 path issue when putting custom config file with absolute path * Fix win32 path issue when putting custom config file with absolute path
in ``pytest.main("-c your_absolute_path")``. in ``pytest.main("-c your_absolute_path")``.
* Fix maximum recursion depth detection when raised error class is not aware * Fix maximum recursion depth detection when raised error class is not aware
of unicode/encoded bytes. of unicode/encoded bytes.
Thanks :user:`prusse-martin` for the PR (:pr:`1506`). Thanks :user:`prusse-martin` for the PR (:pull:`1506`).
* Fix ``pytest.mark.skip`` mark when used in strict mode. * Fix ``pytest.mark.skip`` mark when used in strict mode.
Thanks :user:`pquentin` for the PR and :user:`RonnyPfannschmidt` for Thanks :user:`pquentin` for the PR and :user:`RonnyPfannschmidt` for

View File

@ -1,26 +0,0 @@
pytest-8.0.0
=======================================
The pytest team is proud to announce the 8.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:
* Bruno Oliveira
* Ran Benita
Happy testing,
The pytest Development Team

View File

@ -1,82 +0,0 @@
pytest-8.0.0rc1
=======================================
The pytest team is proud to announce the 8.0.0rc1 release!
This release contains new features, improvements, bug fixes, and breaking changes, so users
are encouraged to take a look at the CHANGELOG carefully:
https://docs.pytest.org/en/stable/changelog.html
For complete documentation, please visit:
https://docs.pytest.org/en/stable/
As usual, you can upgrade from PyPI via:
pip install -U pytest
Thanks to all of the contributors to this release:
* Akhilesh Ramakrishnan
* Aleksandr Brodin
* Anthony Sottile
* Arthur Richard
* Avasam
* Benjamin Schubert
* Bruno Oliveira
* Carsten Grohmann
* Cheukting
* Chris Mahoney
* Christoph Anton Mitterer
* DetachHead
* Erik Hasse
* Florian Bruhin
* Fraser Stark
* Ha Pam
* Hugo van Kemenade
* Isaac Virshup
* Israel Fruchter
* Jens Tröger
* Jon Parise
* Kenny Y
* Lesnek
* Marc Mueller
* Michał Górny
* Mihail Milushev
* Milan Lesnek
* Miro Hrončok
* Patrick Lannigan
* Ran Benita
* Reagan Lee
* Ronny Pfannschmidt
* Sadra Barikbin
* Sean Malloy
* Sean Patrick Malloy
* Sharad Nair
* Simon Blanchard
* Sourabh Beniwal
* Stefaan Lippens
* Tanya Agarwal
* Thomas Grainger
* Tom Mortimer-Jones
* Tushar Sadhwani
* Tyler Smart
* Uday Kumar
* Warren Markham
* WarrenTheRabbit
* Zac Hatfield-Dodds
* Ziad Kermadi
* akhilramkee
* antosikv
* bowugit
* mickeypash
* neilmartin2000
* pomponchik
* ryanpudd
* touilleWoman
* ubaumann
Happy testing,
The pytest Development Team

View File

@ -1,32 +0,0 @@
pytest-8.0.0rc2
=======================================
The pytest team is proud to announce the 8.0.0rc2 prerelease!
This is a prerelease, not intended for production use, but to test the upcoming features and improvements
in order to catch any major problems before the final version is released to the major public.
We appreciate your help testing this out before the final release, making sure to report any
regressions to our issue tracker:
https://github.com/pytest-dev/pytest/issues
When doing so, please include the string ``[prerelease]`` in the title.
You can upgrade from PyPI via:
pip install pytest==8.0.0rc2
Users are encouraged to take a look at the CHANGELOG carefully:
https://docs.pytest.org/en/release-8.0.0rc2/changelog.html
Thanks to all the contributors to this release:
* Ben Brown
* Bruno Oliveira
* Ran Benita
Happy testing,
The pytest Development Team

View File

@ -1,21 +0,0 @@
pytest-8.0.1
=======================================
pytest 8.0.1 has just been released to PyPI.
This is a bug-fix release, being a drop-in replacement. To upgrade::
pip install --upgrade pytest
The full changelog is available at https://docs.pytest.org/en/stable/changelog.html.
Thanks to all of the contributors to this release:
* Bruno Oliveira
* Clément Robert
* Pierre Sassoulas
* Ran Benita
Happy testing,
The pytest Development Team

View File

@ -1,18 +0,0 @@
pytest-8.0.2
=======================================
pytest 8.0.2 has just been released to PyPI.
This is a bug-fix release, being a drop-in replacement. To upgrade::
pip install --upgrade pytest
The full changelog is available at https://docs.pytest.org/en/stable/changelog.html.
Thanks to all of the contributors to this release:
* Ran Benita
Happy testing,
The pytest Development Team

View File

@ -1,54 +0,0 @@
pytest-8.1.0
=======================================
The pytest team is proud to announce the 8.1.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:
* Ben Brown
* Ben Leith
* Bruno Oliveira
* Clément Robert
* Dave Hall
* Dương Quốc Khánh
* Eero Vaher
* Eric Larson
* Fabian Sturm
* Faisal Fawad
* Florian Bruhin
* Franck Charras
* Joachim B Haga
* John Litborn
* Loïc Estève
* Marc Bresson
* Patrick Lannigan
* Pierre Sassoulas
* Ran Benita
* Reagan Lee
* Ronny Pfannschmidt
* Russell Martin
* clee2000
* donghui
* faph
* jakkdl
* mrbean-bremen
* robotherapist
* whysage
* woutdenolf
Happy testing,
The pytest Development Team

View File

@ -1,18 +0,0 @@
pytest-8.1.1
=======================================
pytest 8.1.1 has just been released to PyPI.
This is a bug-fix release, being a drop-in replacement. To upgrade::
pip install --upgrade pytest
The full changelog is available at https://docs.pytest.org/en/stable/changelog.html.
Thanks to all of the contributors to this release:
* Ran Benita
Happy testing,
The pytest Development Team

View File

@ -1,18 +0,0 @@
pytest-8.1.2
=======================================
pytest 8.1.2 has just been released to PyPI.
This is a bug-fix release, being a drop-in replacement. To upgrade::
pip install --upgrade pytest
The full changelog is available at https://docs.pytest.org/en/stable/changelog.html.
Thanks to all of the contributors to this release:
* Bruno Oliveira
Happy testing,
The pytest Development Team

View File

@ -1,43 +0,0 @@
pytest-8.2.0
=======================================
The pytest team is proud to announce the 8.2.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:
* Bruno Oliveira
* Daniel Miller
* Florian Bruhin
* HolyMagician03-UMich
* John Litborn
* Levon Saldamli
* Linghao Zhang
* Manuel López-Ibáñez
* Pierre Sassoulas
* Ran Benita
* Ronny Pfannschmidt
* Sebastian Meyer
* Shekhar verma
* Tamir Duberstein
* Tobias Stoeckmann
* dj
* jakkdl
* poulami-sau
* tserg
Happy testing,
The pytest Development Team

View File

@ -1,19 +0,0 @@
pytest-8.2.1
=======================================
pytest 8.2.1 has just been released to PyPI.
This is a bug-fix release, being a drop-in replacement. To upgrade::
pip install --upgrade pytest
The full changelog is available at https://docs.pytest.org/en/stable/changelog.html.
Thanks to all of the contributors to this release:
* Bruno Oliveira
* Ran Benita
Happy testing,
The pytest Development Team

View File

@ -1,19 +0,0 @@
pytest-8.2.2
=======================================
pytest 8.2.2 has just been released to PyPI.
This is a bug-fix release, being a drop-in replacement. To upgrade::
pip install --upgrade pytest
The full changelog is available at https://docs.pytest.org/en/stable/changelog.html.
Thanks to all of the contributors to this release:
* Bruno Oliveira
* Ran Benita
Happy testing,
The pytest Development Team

View File

@ -49,7 +49,7 @@ place on 20th, 21st, 22nd, 24th and 25th. On the 23rd we took a break
day for some hot hiking in the Black Forest. day for some hot hiking in the Black Forest.
Sprint activity was organised heavily around pairing, with plenty of group Sprint activity was organised heavily around pairing, with plenty of group
discussions to take advantage of the high bandwidth, and lightning talks discusssions to take advantage of the high bandwidth, and lightning talks
as well. as well.

View File

@ -5,26 +5,30 @@ Backwards Compatibility Policy
.. versionadded: 6.0 .. versionadded: 6.0
Pytest is an actively evolving project that has been decades in the making. pytest is actively evolving and is a project that has been decades in the making,
We keep learning about new and better structures to express different details about testing. we keep learning about new and better structures to express different details about testing.
While we implement those modifications, we try to ensure an easy transition and don't want to impose unnecessary churn on our users and community/plugin authors. While we implement those modifications we try to ensure an easy transition and don't want to impose unnecessary churn on our users and community/plugin authors.
As of now, pytest considers multiple types of backward compatibility transitions: As of now, pytest considers multiple types of backward compatibility transitions:
a) trivial: APIs that trivially translate to the new mechanism and do not cause problematic changes. a) trivial: APIs which trivially translate to the new mechanism,
and do not cause problematic changes.
We try to support those indefinitely while encouraging users to switch to newer or better mechanisms through documentation. We try to support those indefinitely while encouraging users to switch to newer/better mechanisms through documentation.
b) transitional: the old and new APIs don't conflict, and we can help users transition by using warnings while supporting both for a prolonged period of time. b) transitional: the old and new API don't conflict
and we can help users transition by using warnings, while supporting both for a prolonged time.
We will only start the removal of deprecated functionality in major releases (e.g., if we deprecate something in 3.0, we will start to remove it in 4.0), and keep it around for at least two minor releases (e.g., if we deprecate something in 3.9 and 4.0 is the next release, we start to remove it in 5.0, not in 4.0). We will only start the removal of deprecated functionality in major releases (e.g. if we deprecate something in 3.0 we will start to remove it in 4.0), and keep it around for at least two minor releases (e.g. if we deprecate something in 3.9 and 4.0 is the next release, we start to remove it in 5.0, not in 4.0).
A deprecated feature scheduled to be removed in major version X will use the warning class `PytestRemovedInXWarning` (a subclass of :class:`~pytest.PytestDeprecationWarning`). A deprecated feature scheduled to be removed in major version X will use the warning class `PytestRemovedInXWarning` (a subclass of :class:`~pytest.PytestDeprecationwarning`).
When the deprecation expires (e.g., 4.0 is released), we won't remove the deprecated functionality immediately but will use the standard warning filters to turn `PytestRemovedInXWarning` (e.g., `PytestRemovedIn4Warning`) into **errors** by default. This approach makes it explicit that removal is imminent and still gives you time to turn the deprecated feature into a warning instead of an error so it can be dealt with in your own time. In the next minor release (e.g., 4.1), the feature will be effectively removed. When the deprecation expires (e.g. 4.0 is released), we won't remove the deprecated functionality immediately, but will use the standard warning filters to turn `PytestRemovedInXWarning` (e.g. `PytestRemovedIn4Warning`) into **errors** by default. This approach makes it explicit that removal is imminent, and still gives you time to turn the deprecated feature into a warning instead of an error so it can be dealt with in your own time. In the next minor release (e.g. 4.1), the feature will be effectively removed.
c) True breakage should only be considered when a normal transition is unreasonably unsustainable and would offset important developments or features by years. In addition, they should be limited to APIs where the number of actual users is very small (for example, only impacting some plugins) and can be coordinated with the community in advance.
c) true breakage: should only be considered when normal transition is unreasonably unsustainable and would offset important development/features by years.
In addition, they should be limited to APIs where the number of actual users is very small (for example only impacting some plugins), and can be coordinated with the community in advance.
Examples for such upcoming changes: Examples for such upcoming changes:
@ -58,11 +62,11 @@ Focus primary on smooth transition - stance (pre 6.0)
Keeping backwards compatibility has a very high priority in the pytest project. Although we have deprecated functionality over the years, most of it is still supported. All deprecations in pytest were done because simpler or more efficient ways of accomplishing the same tasks have emerged, making the old way of doing things unnecessary. Keeping backwards compatibility has a very high priority in the pytest project. Although we have deprecated functionality over the years, most of it is still supported. All deprecations in pytest were done because simpler or more efficient ways of accomplishing the same tasks have emerged, making the old way of doing things unnecessary.
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. 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: ``-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.
We will only start the removal of deprecated functionality in major releases (e.g. if we deprecate something in 3.0, we will start to remove it in 4.0), and keep it around for at least two minor releases (e.g. if we deprecate something in 3.9 and 4.0 is the next release, we start to remove it in 5.0, not in 4.0). We will only start the removal of deprecated functionality in major releases (e.g. if we deprecate something in 3.0 we will start to remove it in 4.0), and keep it around for at least two minor releases (e.g. if we deprecate something in 3.9 and 4.0 is the next release, we start to remove it in 5.0, not in 4.0).
When the deprecation expires (e.g. 4.0 is released), we won't remove the deprecated functionality immediately, but will use the standard warning filters to turn them into **errors** by default. This approach makes it explicit that removal is imminent, and still gives you time to turn the deprecated feature into a warning instead of an error so it can be dealt with in your own time. In the next minor release (e.g. 4.1), the feature will be effectively removed. When the deprecation expires (e.g. 4.0 is released), we won't remove the deprecated functionality immediately, but will use the standard warning filters to turn them into **errors** by default. This approach makes it explicit that removal is imminent, and still gives you time to turn the deprecated feature into a warning instead of an error so it can be dealt with in your own time. In the next minor release (e.g. 4.1), the feature will be effectively removed.
@ -83,7 +87,6 @@ Released pytest versions support all Python versions that are actively maintaine
============== =================== ============== ===================
pytest version min. Python version pytest version min. Python version
============== =================== ============== ===================
8.0+ 3.8+
7.1+ 3.7+ 7.1+ 3.7+
6.2 - 7.0 3.6+ 6.2 - 7.0 3.6+
5.0 - 6.1 3.5+ 5.0 - 6.1 3.5+

View File

@ -18,11 +18,11 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
$ pytest --fixtures -v $ pytest --fixtures -v
=========================== test session starts ============================ =========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
cachedir: .pytest_cache cachedir: .pytest_cache
rootdir: /home/sweet/project rootdir: /home/sweet/project
collected 0 items collected 0 items
cache -- .../_pytest/cacheprovider.py:560 cache -- .../_pytest/cacheprovider.py:532
Return a cache object that can persist state between testing sessions. Return a cache object that can persist state between testing sessions.
cache.get(key, default) cache.get(key, default)
@ -33,7 +33,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
Values can be any object handled by the json stdlib module. Values can be any object handled by the json stdlib module.
capsysbinary -- .../_pytest/capture.py:1003 capsysbinary -- .../_pytest/capture.py:1001
Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``. Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``.
The captured output is made available via ``capsysbinary.readouterr()`` The captured output is made available via ``capsysbinary.readouterr()``
@ -43,6 +43,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
Returns an instance of :class:`CaptureFixture[bytes] <pytest.CaptureFixture>`. Returns an instance of :class:`CaptureFixture[bytes] <pytest.CaptureFixture>`.
Example: Example:
.. code-block:: python .. code-block:: python
def test_output(capsysbinary): def test_output(capsysbinary):
@ -50,7 +51,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
captured = capsysbinary.readouterr() captured = capsysbinary.readouterr()
assert captured.out == b"hello\n" assert captured.out == b"hello\n"
capfd -- .../_pytest/capture.py:1030 capfd -- .../_pytest/capture.py:1029
Enable text capturing of writes to file descriptors ``1`` and ``2``. Enable text capturing of writes to file descriptors ``1`` and ``2``.
The captured output is made available via ``capfd.readouterr()`` method The captured output is made available via ``capfd.readouterr()`` method
@ -60,6 +61,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
Returns an instance of :class:`CaptureFixture[str] <pytest.CaptureFixture>`. Returns an instance of :class:`CaptureFixture[str] <pytest.CaptureFixture>`.
Example: Example:
.. code-block:: python .. code-block:: python
def test_system_echo(capfd): def test_system_echo(capfd):
@ -77,6 +79,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
Returns an instance of :class:`CaptureFixture[bytes] <pytest.CaptureFixture>`. Returns an instance of :class:`CaptureFixture[bytes] <pytest.CaptureFixture>`.
Example: Example:
.. code-block:: python .. code-block:: python
def test_system_echo(capfdbinary): def test_system_echo(capfdbinary):
@ -84,7 +87,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
captured = capfdbinary.readouterr() captured = capfdbinary.readouterr()
assert captured.out == b"hello\n" assert captured.out == b"hello\n"
capsys -- .../_pytest/capture.py:976 capsys -- .../_pytest/capture.py:973
Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``. Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``.
The captured output is made available via ``capsys.readouterr()`` method The captured output is made available via ``capsys.readouterr()`` method
@ -94,6 +97,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
Returns an instance of :class:`CaptureFixture[str] <pytest.CaptureFixture>`. Returns an instance of :class:`CaptureFixture[str] <pytest.CaptureFixture>`.
Example: Example:
.. code-block:: python .. code-block:: python
def test_output(capsys): def test_output(capsys):
@ -101,7 +105,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
captured = capsys.readouterr() captured = capsys.readouterr()
assert captured.out == "hello\n" assert captured.out == "hello\n"
doctest_namespace [session scope] -- .../_pytest/doctest.py:738 doctest_namespace [session scope] -- .../_pytest/doctest.py:757
Fixture that returns a :py:class:`dict` that will be injected into the Fixture that returns a :py:class:`dict` that will be injected into the
namespace of doctests. namespace of doctests.
@ -115,7 +119,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
For more details: :ref:`doctest_namespace`. For more details: :ref:`doctest_namespace`.
pytestconfig [session scope] -- .../_pytest/fixtures.py:1338 pytestconfig [session scope] -- .../_pytest/fixtures.py:1353
Session-scoped fixture that returns the session's :class:`pytest.Config` Session-scoped fixture that returns the session's :class:`pytest.Config`
object. object.
@ -125,7 +129,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
if pytestconfig.getoption("verbose") > 0: if pytestconfig.getoption("verbose") > 0:
... ...
record_property -- .../_pytest/junitxml.py:284 record_property -- .../_pytest/junitxml.py:282
Add extra properties to the calling test. Add extra properties to the calling test.
User properties become part of the test report and are available to the User properties become part of the test report and are available to the
@ -139,13 +143,13 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
def test_function(record_property): def test_function(record_property):
record_property("example_key", 1) record_property("example_key", 1)
record_xml_attribute -- .../_pytest/junitxml.py:307 record_xml_attribute -- .../_pytest/junitxml.py:305
Add extra xml attributes to the tag for the calling test. Add extra xml attributes to the tag for the calling test.
The fixture is callable with ``name, value``. The value is The fixture is callable with ``name, value``. The value is
automatically XML-encoded. automatically XML-encoded.
record_testsuite_property [session scope] -- .../_pytest/junitxml.py:345 record_testsuite_property [session scope] -- .../_pytest/junitxml.py:343
Record a new ``<property>`` tag as child of the root ``<testsuite>``. Record a new ``<property>`` tag as child of the root ``<testsuite>``.
This is suitable to writing global information regarding the entire test This is suitable to writing global information regarding the entire test
@ -170,18 +174,18 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
`pytest-xdist <https://github.com/pytest-dev/pytest-xdist>`__ plugin. See `pytest-xdist <https://github.com/pytest-dev/pytest-xdist>`__ plugin. See
:issue:`7767` for details. :issue:`7767` for details.
tmpdir_factory [session scope] -- .../_pytest/legacypath.py:303 tmpdir_factory [session scope] -- .../_pytest/legacypath.py:302
Return a :class:`pytest.TempdirFactory` instance for the test session. Return a :class:`pytest.TempdirFactory` instance for the test session.
tmpdir -- .../_pytest/legacypath.py:310 tmpdir -- .../_pytest/legacypath.py:309
Return a temporary directory path object which is unique to each test Return a temporary directory path object which is unique to each test
function invocation, created as a sub directory of the base temporary function invocation, created as a sub directory of the base temporary
directory. directory.
By default, a new base temporary directory is created each test session, By default, a new base temporary directory is created each test session,
and old bases are removed after 3 sessions, to aid in debugging. If and old bases are removed after 3 sessions, to aid in debugging. If
``--basetemp`` is used then it is cleared each session. See ``--basetemp`` is used then it is cleared each session. See :ref:`base
:ref:`temporary directory location and retention`. temporary directory`.
The returned object is a `legacy_path`_ object. The returned object is a `legacy_path`_ object.
@ -192,7 +196,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
.. _legacy_path: https://py.readthedocs.io/en/latest/path.html .. _legacy_path: https://py.readthedocs.io/en/latest/path.html
caplog -- .../_pytest/logging.py:602 caplog -- .../_pytest/logging.py:570
Access and control log capturing. Access and control log capturing.
Captured logs are available through the following properties/methods:: Captured logs are available through the following properties/methods::
@ -203,7 +207,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.record_tuples -> list of (logger_name, level, message) tuples
* caplog.clear() -> clear captured records and formatted log output string * caplog.clear() -> clear captured records and formatted log output string
monkeypatch -- .../_pytest/monkeypatch.py:33 monkeypatch -- .../_pytest/monkeypatch.py:30
A convenient fixture for monkey-patching. A convenient fixture for monkey-patching.
The fixture provides these methods to modify objects, dictionaries, or The fixture provides these methods to modify objects, dictionaries, or
@ -227,16 +231,16 @@ 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, To undo modifications done by the fixture in a contained scope,
use :meth:`context() <pytest.MonkeyPatch.context>`. use :meth:`context() <pytest.MonkeyPatch.context>`.
recwarn -- .../_pytest/recwarn.py:32 recwarn -- .../_pytest/recwarn.py:30
Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions. Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions.
See https://docs.pytest.org/en/latest/how-to/capture-warnings.html for information See https://docs.pytest.org/en/latest/how-to/capture-warnings.html for information
on warning categories. on warning categories.
tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:242 tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:245
Return a :class:`pytest.TempPathFactory` instance for the test session. Return a :class:`pytest.TempPathFactory` instance for the test session.
tmp_path -- .../_pytest/tmpdir.py:257 tmp_path -- .../_pytest/tmpdir.py:260
Return a temporary directory path object which is unique to each test Return a temporary directory path object which is unique to each test
function invocation, created as a sub directory of the base temporary function invocation, created as a sub directory of the base temporary
directory. directory.
@ -245,8 +249,8 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
and old bases are removed after 3 sessions, to aid in debugging. and old bases are removed after 3 sessions, to aid in debugging.
This behavior can be configured with :confval:`tmp_path_retention_count` and This behavior can be configured with :confval:`tmp_path_retention_count` and
:confval:`tmp_path_retention_policy`. :confval:`tmp_path_retention_policy`.
If ``--basetemp`` is used then it is cleared each session. See If ``--basetemp`` is used then it is cleared each session. See :ref:`base
:ref:`temporary directory location and retention`. temporary directory`.
The returned object is a :class:`pathlib.Path` object. The returned object is a :class:`pathlib.Path` object.

File diff suppressed because it is too large Load Diff

View File

@ -15,33 +15,20 @@
# #
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
# The short X.Y version. # The short X.Y version.
from __future__ import annotations import ast
import os import os
from pathlib import Path
import shutil import shutil
import sys
from textwrap import dedent from textwrap import dedent
from typing import List
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from _pytest import __version__ as full_version from _pytest import __version__ as version
version = full_version.split("+")[0]
if TYPE_CHECKING: if TYPE_CHECKING:
import sphinx.application import sphinx.application
PROJECT_ROOT_DIR = Path(__file__).parents[2].resolve()
IS_RELEASE_ON_RTD = (
os.getenv("READTHEDOCS", "False") == "True"
and os.environ["READTHEDOCS_VERSION_TYPE"] == "tag"
)
if IS_RELEASE_ON_RTD:
tags: set[str]
# pylint: disable-next=used-before-assignment
tags.add("is_release") # noqa: F821
release = ".".join(version.split(".")[:2]) release = ".".join(version.split(".")[:2])
# If extensions (or modules to document with autodoc) are in another directory, # If extensions (or modules to document with autodoc) are in another directory,
@ -79,16 +66,16 @@ latex_elements = {
# Add any Sphinx extension module names here, as strings. They can be extensions # Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [ extensions = [
"pallets_sphinx_themes",
"pygments_pytest", "pygments_pytest",
"sphinx.ext.autodoc", "sphinx.ext.autodoc",
"sphinx.ext.autosummary", "sphinx.ext.autosummary",
"sphinx.ext.extlinks",
"sphinx.ext.intersphinx", "sphinx.ext.intersphinx",
"sphinx.ext.todo", "sphinx.ext.todo",
"sphinx.ext.viewcode", "sphinx.ext.viewcode",
"sphinx_removed_in", "sphinx_removed_in",
"sphinxcontrib_trio", "sphinxcontrib_trio",
"sphinxcontrib.towncrier.ext", # provides `towncrier-draft-entries` directive
"sphinx_issues", # implements `:issue:`, `:pr:` and other GH-related roles
] ]
# Building PDF docs on readthedocs requires inkscape for svg to pdf # Building PDF docs on readthedocs requires inkscape for svg to pdf
@ -154,6 +141,10 @@ add_module_names = False
# output. They are ignored by default. # output. They are ignored by default.
# show_authors = False # show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = "sphinx"
# A list of ignored prefixes for module index sorting. # A list of ignored prefixes for module index sorting.
# modindex_common_prefix = [] # modindex_common_prefix = []
@ -170,59 +161,24 @@ linkcheck_ignore = [
linkcheck_workers = 5 linkcheck_workers = 5
nitpicky = True _repo = "https://github.com/pytest-dev/pytest"
nitpick_ignore = [ extlinks = {
# TODO (fix in pluggy?) "bpo": ("https://bugs.python.org/issue%s", "bpo-%s"),
("py:class", "HookCaller"), "pypi": ("https://pypi.org/project/%s/", "%s"),
("py:class", "HookspecMarker"), "issue": (f"{_repo}/issues/%s", "issue #%s"),
("py:exc", "PluginValidationError"), "pull": (f"{_repo}/pull/%s", "pull request #%s"),
# Might want to expose/TODO (https://github.com/pytest-dev/pytest/issues/7469) "user": ("https://github.com/%s", "@%s"),
("py:class", "ExceptionRepr"), }
("py:class", "Exit"),
("py:class", "SubRequest"),
("py:class", "SubRequest"),
("py:class", "TerminalReporter"),
("py:class", "_pytest._code.code.TerminalRepr"),
("py:class", "TerminalRepr"),
("py:class", "_pytest.fixtures.FixtureFunctionMarker"),
("py:class", "_pytest.logging.LogCaptureHandler"),
("py:class", "_pytest.mark.structures.ParameterSet"),
# Intentionally undocumented/private
("py:class", "_pytest._code.code.Traceback"),
("py:class", "_pytest._py.path.LocalPath"),
("py:class", "_pytest.capture.CaptureResult"),
("py:class", "_pytest.compat.NotSetType"),
("py:class", "_pytest.python.PyCollector"),
("py:class", "_pytest.python.PyobjMixin"),
("py:class", "_pytest.python_api.RaisesContext"),
("py:class", "_pytest.recwarn.WarningsChecker"),
("py:class", "_pytest.reports.BaseReport"),
# Undocumented third parties
("py:class", "_tracing.TagTracerSub"),
("py:class", "warnings.WarningMessage"),
# Undocumented type aliases
("py:class", "LEGACY_PATH"),
("py:class", "_PluggyPlugin"),
# TypeVars
("py:class", "_pytest._code.code.E"),
("py:class", "E"), # due to delayed annotation
("py:class", "_pytest.fixtures.FixtureFunction"),
("py:class", "_pytest.nodes._NodeType"),
("py:class", "_NodeType"), # due to delayed annotation
("py:class", "_pytest.python_api.E"),
("py:class", "_pytest.recwarn.T"),
("py:class", "_pytest.runner.TResult"),
("py:obj", "_pytest.fixtures.FixtureValue"),
("py:obj", "_pytest.stash.T"),
("py:class", "_ScopeName"),
]
# -- Options for HTML output --------------------------------------------------- # -- Options for HTML output ---------------------------------------------------
sys.path.append(os.path.abspath("_themes"))
html_theme_path = ["_themes"]
# The theme to use for HTML and HTML Help pages. See the documentation for # The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes. # a list of builtin themes.
html_theme = "furo" html_theme = "flask"
# Theme options are theme-specific and customize the look and feel of a theme # Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the # further. For a list of options available for each theme, see the
@ -237,7 +193,7 @@ html_theme = "furo"
html_title = "pytest documentation" html_title = "pytest documentation"
# A shorter title for the navigation bar. Default is the same as html_title. # A shorter title for the navigation bar. Default is the same as html_title.
html_short_title = f"pytest-{release}" html_short_title = "pytest-%s" % release
# The name of an image file (relative to this directory) to place at the top # The name of an image file (relative to this directory) to place at the top
# of the sidebar. # of the sidebar.
@ -267,24 +223,18 @@ html_favicon = "img/favicon.png"
html_sidebars = { html_sidebars = {
"index": [ "index": [
"sidebar/brand.html", "slim_searchbox.html",
"sidebar/search.html",
"sidebar/scroll-start.html",
"sidebarintro.html", "sidebarintro.html",
"globaltoc.html", "globaltoc.html",
"links.html", "links.html",
"sidebar/scroll-end.html", "sourcelink.html",
"style.html",
], ],
"**": [ "**": [
"sidebar/brand.html", "slim_searchbox.html",
"sidebar/search.html",
"sidebar/scroll-start.html",
"globaltoc.html", "globaltoc.html",
"relations.html", "relations.html",
"links.html", "links.html",
"sidebar/scroll-end.html", "sourcelink.html",
"style.html",
], ],
} }
@ -347,6 +297,10 @@ latex_documents = [
) )
] ]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
latex_logo = "img/pytest1.png"
# For "manual" documents, if this is true, then toplevel headings are parts, # For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters. # not chapters.
# latex_use_parts = False # latex_use_parts = False
@ -401,7 +355,7 @@ epub_copyright = "2013, holger krekel et alii"
# The format is a list of tuples containing the path and title. # The format is a list of tuples containing the path and title.
# epub_pre_files = [] # epub_pre_files = []
# HTML files that should be inserted after the pages created by sphinx. # HTML files shat should be inserted after the pages created by sphinx.
# The format is a list of tuples containing the path and title. # The format is a list of tuples containing the path and title.
# epub_post_files = [] # epub_post_files = []
@ -433,18 +387,6 @@ texinfo_documents = [
) )
] ]
# -- Options for towncrier_draft extension -----------------------------------
towncrier_draft_autoversion_mode = "draft" # or: 'sphinx-version', 'sphinx-release'
towncrier_draft_include_empty = True
towncrier_draft_working_directory = PROJECT_ROOT_DIR
towncrier_draft_config_path = "pyproject.toml" # relative to cwd
# -- Options for sphinx_issues extension -----------------------------------
issues_github_path = "pytest-dev/pytest"
intersphinx_mapping = { intersphinx_mapping = {
"pluggy": ("https://pluggy.readthedocs.io/en/stable", None), "pluggy": ("https://pluggy.readthedocs.io/en/stable", None),
@ -458,7 +400,30 @@ intersphinx_mapping = {
} }
def setup(app: sphinx.application.Sphinx) -> None: def configure_logging(app: "sphinx.application.Sphinx") -> None:
"""Configure Sphinx's WarningHandler to handle (expected) missing include."""
import sphinx.util.logging
import logging
class WarnLogFilter(logging.Filter):
def filter(self, record: logging.LogRecord) -> bool:
"""Ignore warnings about missing include with "only" directive.
Ref: https://github.com/sphinx-doc/sphinx/issues/2150."""
if (
record.msg.startswith('Problems with "include" directive path:')
and "_changelog_towncrier_draft.rst" in record.msg
):
return False
return True
logger = logging.getLogger(sphinx.util.logging.NAMESPACE)
warn_handler = [x for x in logger.handlers if x.level == logging.WARNING]
assert len(warn_handler) == 1, warn_handler
warn_handler[0].filters.insert(0, WarnLogFilter())
def setup(app: "sphinx.application.Sphinx") -> None:
app.add_crossref_type( app.add_crossref_type(
"fixture", "fixture",
"fixture", "fixture",
@ -487,6 +452,27 @@ def setup(app: sphinx.application.Sphinx) -> None:
indextemplate="pair: %s; hook", indextemplate="pair: %s; hook",
) )
configure_logging(app)
# Make Sphinx mark classes with "final" when decorated with @final.
# We need this because we import final from pytest._compat, not from
# typing (for Python < 3.8 compat), so Sphinx doesn't detect it.
# To keep things simple we accept any `@final` decorator.
# Ref: https://github.com/pytest-dev/pytest/pull/7780
import sphinx.pycode.ast
import sphinx.pycode.parser
original_is_final = sphinx.pycode.parser.VariableCommentPicker.is_final
def patched_is_final(self, decorators: List[ast.expr]) -> bool:
if original_is_final(self, decorators):
return True
return any(
sphinx.pycode.ast.unparse(decorator) == "final" for decorator in decorators
)
sphinx.pycode.parser.VariableCommentPicker.is_final = patched_is_final
# legacypath.py monkey-patches pytest.Testdir in. Import the file so # legacypath.py monkey-patches pytest.Testdir in. Import the file so
# that autodoc can discover references to it. # that autodoc can discover references to it.
import _pytest.legacypath # noqa: F401 import _pytest.legacypath # noqa: F401

View File

@ -1,4 +1 @@
from __future__ import annotations
collect_ignore = ["conf.py"] collect_ignore = ["conf.py"]

View File

@ -22,16 +22,23 @@ Contact channels
requests to GitHub. requests to GitHub.
- ``#pytest`` `on irc.libera.chat <ircs://irc.libera.chat:6697/#pytest>`_ IRC - ``#pytest`` `on irc.libera.chat <ircs://irc.libera.chat:6697/#pytest>`_ IRC
channel for random questions (using an IRC client, or `via webchat channel for random questions (using an IRC client, `via webchat
<https://web.libera.chat/#pytest>`) <https://web.libera.chat/#pytest>`_, or `via Matrix
- ``#pytest`` `on Matrix https://matrix.to/#/#pytest:matrix.org>`. <https://matrix.to/#/%23pytest:libera.chat>`_).
- private mail to Holger.Krekel at gmail com if you want to communicate sensitive issues
- `merlinux.eu`_ offers pytest and tox-related professional teaching and
consulting.
.. _`pytest issue tracker`: https://github.com/pytest-dev/pytest/issues .. _`pytest issue tracker`: https://github.com/pytest-dev/pytest/issues
.. _`old issue tracker`: https://bitbucket.org/hpk42/py-trunk/issues/ .. _`old issue tracker`: https://bitbucket.org/hpk42/py-trunk/issues/
.. _`pytest discussions`: https://github.com/pytest-dev/pytest/discussions .. _`pytest discussions`: https://github.com/pytest-dev/pytest/discussions
.. _`merlinux.eu`: https://merlinux.eu/
.. _`get an account`: .. _`get an account`:
.. _tetamap: https://tetamap.wordpress.com/ .. _tetamap: https://tetamap.wordpress.com/

View File

@ -44,6 +44,7 @@ How-to guides
how-to/existingtestsuite how-to/existingtestsuite
how-to/unittest how-to/unittest
how-to/nose
how-to/xunit_setup how-to/xunit_setup
how-to/bash-completion how-to/bash-completion

View File

@ -7,6 +7,10 @@ This page lists all pytest features that are currently deprecated or have been r
The objective is to give users a clear rationale why a certain feature has been removed, and what alternatives The objective is to give users a clear rationale why a certain feature has been removed, and what alternatives
should be used instead. should be used instead.
.. contents::
:depth: 3
:local:
Deprecated Features Deprecated Features
------------------- -------------------
@ -15,39 +19,129 @@ Below is a complete list of all pytest features which are considered deprecated.
:class:`~pytest.PytestWarning` or subclasses, which can be filtered using :ref:`standard warning filters <warnings>`. :class:`~pytest.PytestWarning` or subclasses, which can be filtered using :ref:`standard warning filters <warnings>`.
.. _import-or-skip-import-error: .. _nose-deprecation:
``pytest.importorskip`` default behavior regarding :class:`ImportError` Support for tests written for nose
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 8.2 .. deprecated:: 7.2
Traditionally :func:`pytest.importorskip` will capture :class:`ImportError`, with the original intent being to skip Support for running tests written for `nose <https://nose.readthedocs.io/en/latest/>`__ is now deprecated.
tests where a dependent module is not installed, for example testing with different dependencies.
However some packages might be installed in the system, but are not importable due to ``nose`` has been in maintenance mode-only for years, and maintaining the plugin is not trivial as it spills
some other issue, for example, a compilation error or a broken installation. In those cases :func:`pytest.importorskip` over the code base (see :issue:`9886` for more details).
would still silently skip the test, but more often than not users would like to see the unexpected
error so the underlying issue can be fixed.
In ``8.2`` the ``exc_type`` parameter has been added, giving users the ability of passing :class:`ModuleNotFoundError` setup/teardown
to skip tests only if the module cannot really be found, and not because of some other error. ^^^^^^^^^^^^^^
Catching only :class:`ModuleNotFoundError` by default (and letting other errors propagate) would be the best solution, One thing that might catch users by surprise is that plain ``setup`` and ``teardown`` methods are not pytest native,
however for backward compatibility, pytest will keep the existing behavior but raise an warning if: they are in fact part of the ``nose`` support.
1. The captured exception is of type :class:`ImportError`, and:
2. The user does not pass ``exc_type`` explicitly.
If the import attempt raises :class:`ModuleNotFoundError` (the usual case), then the module is skipped and no .. code-block:: python
warning is emitted.
This way, the usual cases will keep working the same way, while unexpected errors will now issue a warning, with class Test:
users being able to supress the warning by passing ``exc_type=ImportError`` explicitly. def setup(self):
self.resource = make_resource()
In ``9.0``, the warning will turn into an error, and in ``9.1`` :func:`pytest.importorskip` will only capture def teardown(self):
:class:`ModuleNotFoundError` by default and no warnings will be issued anymore -- but users can still capture self.resource.close()
:class:`ImportError` by passing it to ``exc_type``.
def test_foo(self):
...
def test_bar(self):
...
Native pytest support uses ``setup_method`` and ``teardown_method`` (see :ref:`xunit-method-setup`), so the above should be changed to:
.. code-block:: python
class Test:
def setup_method(self):
self.resource = make_resource()
def teardown_method(self):
self.resource.close()
def test_foo(self):
...
def test_bar(self):
...
This is easy to do in an entire code base by doing a simple find/replace.
@with_setup
^^^^^^^^^^^
Code using `@with_setup <with-setup-nose>`_ such as this:
.. code-block:: python
from nose.tools import with_setup
def setup_some_resource():
...
def teardown_some_resource():
...
@with_setup(setup_some_resource, teardown_some_resource)
def test_foo():
...
Will also need to be ported to a supported pytest style. One way to do it is using a fixture:
.. code-block:: python
import pytest
def setup_some_resource():
...
def teardown_some_resource():
...
@pytest.fixture
def some_resource():
setup_some_resource()
yield
teardown_some_resource()
def test_foo(some_resource):
...
.. _`with-setup-nose`: https://nose.readthedocs.io/en/latest/testing_tools.html?highlight=with_setup#nose.tools.with_setup
.. _instance-collector-deprecation:
The ``pytest.Instance`` collector
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. versionremoved:: 7.0
The ``pytest.Instance`` collector type has been removed.
Previously, Python test methods were collected as :class:`~pytest.Class` -> ``Instance`` -> :class:`~pytest.Function`.
Now :class:`~pytest.Class` collects the test methods directly.
Most plugins which reference ``Instance`` do so in order to ignore or skip it,
using a check such as ``if isinstance(node, Instance): return``.
Such plugins should simply remove consideration of ``Instance`` on pytest>=7.
However, to keep such uses working, a dummy type has been instanted in ``pytest.Instance`` and ``_pytest.python.Instance``,
and importing it emits a deprecation warning. This will be removed in pytest 8.
.. _node-ctor-fspath-deprecation: .. _node-ctor-fspath-deprecation:
@ -83,12 +177,13 @@ arguments they only pass on to the superclass.
resolved in future versions as we slowly get rid of the :pypi:`py` resolved in future versions as we slowly get rid of the :pypi:`py`
dependency (see :issue:`9283` for a longer discussion). dependency (see :issue:`9283` for a longer discussion).
Due to the ongoing migration of methods like :meth:`~pytest.Item.reportinfo` Due to the ongoing migration of methods like :meth:`~_pytest.Item.reportinfo`
which still is expected to return a ``py.path.local`` object, nodes still have which still is expected to return a ``py.path.local`` object, nodes still have
both ``fspath`` (``py.path.local``) and ``path`` (``pathlib.Path``) attributes, both ``fspath`` (``py.path.local``) and ``path`` (``pathlib.Path``) attributes,
no matter what argument was used in the constructor. We expect to deprecate the no matter what argument was used in the constructor. We expect to deprecate the
``fspath`` attribute in a future release. ``fspath`` attribute in a future release.
.. _legacy-path-hooks-deprecated:
Configuring hook specs/impls using markers Configuring hook specs/impls using markers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -102,11 +197,13 @@ have been available since years and should be used instead.
.. code-block:: python .. code-block:: python
@pytest.mark.tryfirst @pytest.mark.tryfirst
def pytest_runtest_call(): ... def pytest_runtest_call():
...
# or # or
def pytest_runtest_call(): ... def pytest_runtest_call():
...
pytest_runtest_call.tryfirst = True pytest_runtest_call.tryfirst = True
@ -116,7 +213,8 @@ should be changed to:
.. code-block:: python .. code-block:: python
@pytest.hookimpl(tryfirst=True) @pytest.hookimpl(tryfirst=True)
def pytest_runtest_call(): ... def pytest_runtest_call():
...
Changed ``hookimpl`` attributes: Changed ``hookimpl`` attributes:
@ -131,8 +229,6 @@ Changed ``hookwrapper`` attributes:
* ``historic`` * ``historic``
.. _legacy-path-hooks-deprecated:
``py.path.local`` arguments for hooks replaced with ``pathlib.Path`` ``py.path.local`` arguments for hooks replaced with ``pathlib.Path``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -177,6 +273,62 @@ Directly constructing the following classes is now deprecated:
These constructors have always been considered private, but now issue a deprecation warning, which may become a hard error in pytest 8. These constructors have always been considered private, but now issue a deprecation warning, which may become a hard error in pytest 8.
.. _cmdline-preparse-deprecated:
Passing ``msg=`` to ``pytest.skip``, ``pytest.fail`` or ``pytest.exit``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 7.0
Passing the keyword argument ``msg`` to :func:`pytest.skip`, :func:`pytest.fail` or :func:`pytest.exit`
is now deprecated and ``reason`` should be used instead. This change is to bring consistency between these
functions and the ``@pytest.mark.skip`` and ``@pytest.mark.xfail`` markers which already accept a ``reason`` argument.
.. code-block:: python
def test_fail_example():
# old
pytest.fail(msg="foo")
# new
pytest.fail(reason="bar")
def test_skip_example():
# old
pytest.skip(msg="foo")
# new
pytest.skip(reason="bar")
def test_exit_example():
# old
pytest.exit(msg="foo")
# new
pytest.exit(reason="bar")
Implementing the ``pytest_cmdline_preparse`` hook
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 7.0
Implementing the :hook:`pytest_cmdline_preparse` hook has been officially deprecated.
Implement the :hook:`pytest_load_initial_conftests` hook instead.
.. code-block:: python
def pytest_cmdline_preparse(config: Config, args: List[str]) -> None:
...
# becomes:
def pytest_load_initial_conftests(
early_config: Config, parser: Parser, args: List[str]
) -> None:
...
.. _diamond-inheritance-deprecated: .. _diamond-inheritance-deprecated:
Diamond inheritance between :class:`pytest.Collector` and :class:`pytest.Item` Diamond inheritance between :class:`pytest.Collector` and :class:`pytest.Item`
@ -184,7 +336,7 @@ Diamond inheritance between :class:`pytest.Collector` and :class:`pytest.Item`
.. deprecated:: 7.0 .. deprecated:: 7.0
Defining a custom pytest node type which is both an :class:`~pytest.Item` and a :class:`~pytest.Collector` (e.g. :class:`~pytest.File`) now issues a warning. Defining a custom pytest node type which is both an :class:`pytest.Item <Item>` and a :class:`pytest.Collector <Collector>` (e.g. :class:`pytest.File <File>`) now issues a warning.
It was never sanely supported and triggers hard to debug errors. It was never sanely supported and triggers hard to debug errors.
Some plugins providing linting/code analysis have been using this as a hack. Some plugins providing linting/code analysis have been using this as a hack.
@ -196,8 +348,8 @@ Instead, a separate collector node should be used, which collects the item. See
.. _uncooperative-constructors-deprecated: .. _uncooperative-constructors-deprecated:
Constructors of custom :class:`~_pytest.nodes.Node` subclasses should take ``**kwargs`` Constructors of custom :class:`pytest.Node` subclasses should take ``**kwargs``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 7.0 .. deprecated:: 7.0
@ -228,22 +380,28 @@ conflicts (such as :class:`pytest.File` now taking ``path`` instead of
``fspath``, as :ref:`outlined above <node-ctor-fspath-deprecation>`), a ``fspath``, as :ref:`outlined above <node-ctor-fspath-deprecation>`), a
deprecation warning is now raised. deprecation warning is now raised.
Applying a mark to a fixture function Backward compatibilities in ``Parser.addoption``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 7.4 .. deprecated:: 2.4
Applying a mark to a fixture function never had any effect, but it is a common user error. Several behaviors of :meth:`Parser.addoption <pytest.Parser.addoption>` are now
scheduled for removal in pytest 8 (deprecated since pytest 2.4.0):
.. code-block:: python - ``parser.addoption(..., help=".. %default ..")`` - use ``%(default)s`` instead.
- ``parser.addoption(..., type="int/string/float/complex")`` - use ``type=int`` etc. instead.
@pytest.mark.usefixtures("clean_database")
@pytest.fixture
def user() -> User: ...
Users expected in this case that the ``usefixtures`` mark would have its intended effect of using the ``clean_database`` fixture when ``user`` was invoked, when in fact it has no effect at all. Using ``pytest.warns(None)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now pytest will issue a warning when it encounters this problem, and will raise an error in the future versions. .. deprecated:: 7.0
:func:`pytest.warns(None) <pytest.warns>` is now deprecated because it was frequently misused.
Its correct usage was checking that the code emits at least one warning of any type - like ``pytest.warns()``
or ``pytest.warns(Warning)``.
See :ref:`warns use cases` for examples.
Returning non-None value in test functions Returning non-None value in test functions
@ -286,6 +444,19 @@ The proper fix is to change the `return` to an `assert`:
assert foo(a, b) == result assert foo(a, b) == result
The ``--strict`` command-line option
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 6.2
The ``--strict`` command-line option has been deprecated in favor of ``--strict-markers``, which
better conveys what the option does.
We have plans to maybe in the future to reintroduce ``--strict`` and make it an encompassing
flag for all strictness related options (``--strict-markers`` and ``--strict-config``
at the moment, more might be introduced in the future).
The ``yield_fixture`` function/decorator The ``yield_fixture`` function/decorator
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -296,348 +467,12 @@ The ``yield_fixture`` function/decorator
It has been so for a very long time, so can be search/replaced safely. It has been so for a very long time, so can be search/replaced safely.
Removed Features and Breaking Changes Removed Features
------------------------------------- ----------------
As stated in our :ref:`backwards-compatibility` policy, deprecated features are removed only in major releases after As stated in our :ref:`backwards-compatibility` policy, deprecated features are removed only in major releases after
an appropriate period of deprecation has passed. an appropriate period of deprecation has passed.
Some breaking changes which could not be deprecated are also listed.
.. _nose-deprecation:
Support for tests written for nose
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 7.2
.. versionremoved:: 8.0
Support for running tests written for `nose <https://nose.readthedocs.io/en/latest/>`__ is now deprecated.
``nose`` has been in maintenance mode-only for years, and maintaining the plugin is not trivial as it spills
over the code base (see :issue:`9886` for more details).
setup/teardown
^^^^^^^^^^^^^^
One thing that might catch users by surprise is that plain ``setup`` and ``teardown`` methods are not pytest native,
they are in fact part of the ``nose`` support.
.. code-block:: python
class Test:
def setup(self):
self.resource = make_resource()
def teardown(self):
self.resource.close()
def test_foo(self): ...
def test_bar(self): ...
Native pytest support uses ``setup_method`` and ``teardown_method`` (see :ref:`xunit-method-setup`), so the above should be changed to:
.. code-block:: python
class Test:
def setup_method(self):
self.resource = make_resource()
def teardown_method(self):
self.resource.close()
def test_foo(self): ...
def test_bar(self): ...
This is easy to do in an entire code base by doing a simple find/replace.
@with_setup
^^^^^^^^^^^
Code using `@with_setup <with-setup-nose>`_ such as this:
.. code-block:: python
from nose.tools import with_setup
def setup_some_resource(): ...
def teardown_some_resource(): ...
@with_setup(setup_some_resource, teardown_some_resource)
def test_foo(): ...
Will also need to be ported to a supported pytest style. One way to do it is using a fixture:
.. code-block:: python
import pytest
def setup_some_resource(): ...
def teardown_some_resource(): ...
@pytest.fixture
def some_resource():
setup_some_resource()
yield
teardown_some_resource()
def test_foo(some_resource): ...
.. _`with-setup-nose`: https://nose.readthedocs.io/en/latest/testing_tools.html?highlight=with_setup#nose.tools.with_setup
The ``compat_co_firstlineno`` attribute
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Nose inspects this attribute on function objects to allow overriding the function's inferred line number.
Pytest no longer respects this attribute.
Passing ``msg=`` to ``pytest.skip``, ``pytest.fail`` or ``pytest.exit``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 7.0
.. versionremoved:: 8.0
Passing the keyword argument ``msg`` to :func:`pytest.skip`, :func:`pytest.fail` or :func:`pytest.exit`
is now deprecated and ``reason`` should be used instead. This change is to bring consistency between these
functions and the ``@pytest.mark.skip`` and ``@pytest.mark.xfail`` markers which already accept a ``reason`` argument.
.. code-block:: python
def test_fail_example():
# old
pytest.fail(msg="foo")
# new
pytest.fail(reason="bar")
def test_skip_example():
# old
pytest.skip(msg="foo")
# new
pytest.skip(reason="bar")
def test_exit_example():
# old
pytest.exit(msg="foo")
# new
pytest.exit(reason="bar")
.. _instance-collector-deprecation:
The ``pytest.Instance`` collector
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. versionremoved:: 7.0
The ``pytest.Instance`` collector type has been removed.
Previously, Python test methods were collected as :class:`~pytest.Class` -> ``Instance`` -> :class:`~pytest.Function`.
Now :class:`~pytest.Class` collects the test methods directly.
Most plugins which reference ``Instance`` do so in order to ignore or skip it,
using a check such as ``if isinstance(node, Instance): return``.
Such plugins should simply remove consideration of ``Instance`` on pytest>=7.
However, to keep such uses working, a dummy type has been instanced in ``pytest.Instance`` and ``_pytest.python.Instance``,
and importing it emits a deprecation warning. This was removed in pytest 8.
Using ``pytest.warns(None)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 7.0
.. versionremoved:: 8.0
:func:`pytest.warns(None) <pytest.warns>` is now deprecated because it was frequently misused.
Its correct usage was checking that the code emits at least one warning of any type - like ``pytest.warns()``
or ``pytest.warns(Warning)``.
See :ref:`warns use cases` for examples.
Backward compatibilities in ``Parser.addoption``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 2.4
.. versionremoved:: 8.0
Several behaviors of :meth:`Parser.addoption <pytest.Parser.addoption>` are now
removed in pytest 8 (deprecated since pytest 2.4.0):
- ``parser.addoption(..., help=".. %default ..")`` - use ``%(default)s`` instead.
- ``parser.addoption(..., type="int/string/float/complex")`` - use ``type=int`` etc. instead.
The ``--strict`` command-line option
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 6.2
.. versionremoved:: 8.0
The ``--strict`` command-line option has been deprecated in favor of ``--strict-markers``, which
better conveys what the option does.
We have plans to maybe in the future to reintroduce ``--strict`` and make it an encompassing
flag for all strictness related options (``--strict-markers`` and ``--strict-config``
at the moment, more might be introduced in the future).
.. _cmdline-preparse-deprecated:
Implementing the ``pytest_cmdline_preparse`` hook
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 7.0
.. versionremoved:: 8.0
Implementing the ``pytest_cmdline_preparse`` hook has been officially deprecated.
Implement the :hook:`pytest_load_initial_conftests` hook instead.
.. code-block:: python
def pytest_cmdline_preparse(config: Config, args: List[str]) -> None: ...
# becomes:
def pytest_load_initial_conftests(
early_config: Config, parser: Parser, args: List[str]
) -> None: ...
Collection changes in pytest 8
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Added a new :class:`pytest.Directory` base collection node, which all collector nodes for filesystem directories are expected to subclass.
This is analogous to the existing :class:`pytest.File` for file nodes.
Changed :class:`pytest.Package` to be a subclass of :class:`pytest.Directory`.
A ``Package`` represents a filesystem directory which is a Python package,
i.e. contains an ``__init__.py`` file.
:class:`pytest.Package` now only collects files in its own directory; previously it collected recursively.
Sub-directories are collected as sub-collector nodes, thus creating a collection tree which mirrors the filesystem hierarchy.
:attr:`session.name <pytest.Session.name>` is now ``""``; previously it was the rootdir directory name.
This matches :attr:`session.nodeid <_pytest.nodes.Node.nodeid>` which has always been `""`.
Added a new :class:`pytest.Dir` concrete collection node, a subclass of :class:`pytest.Directory`.
This node represents a filesystem directory, which is not a :class:`pytest.Package`,
i.e. does not contain an ``__init__.py`` file.
Similarly to ``Package``, it only collects the files in its own directory,
while collecting sub-directories as sub-collector nodes.
Files and directories are now collected in alphabetical order jointly, unless changed by a plugin.
Previously, files were collected before directories.
The collection tree now contains directories/packages up to the :ref:`rootdir <rootdir>`,
for initial arguments that are found within the rootdir.
For files outside the rootdir, only the immediate directory/package is collected --
note however that collecting from outside the rootdir is discouraged.
As an example, given the following filesystem tree::
myroot/
pytest.ini
top/
├── aaa
│ └── test_aaa.py
├── test_a.py
├── test_b
│ ├── __init__.py
│ └── test_b.py
├── test_c.py
└── zzz
├── __init__.py
└── test_zzz.py
the collection tree, as shown by `pytest --collect-only top/` but with the otherwise-hidden :class:`~pytest.Session` node added for clarity,
is now the following::
<Session>
<Dir myroot>
<Dir top>
<Dir aaa>
<Module test_aaa.py>
<Function test_it>
<Module test_a.py>
<Function test_it>
<Package test_b>
<Module test_b.py>
<Function test_it>
<Module test_c.py>
<Function test_it>
<Package zzz>
<Module test_zzz.py>
<Function test_it>
Previously, it was::
<Session>
<Module top/test_a.py>
<Function test_it>
<Module top/test_c.py>
<Function test_it>
<Module top/aaa/test_aaa.py>
<Function test_it>
<Package test_b>
<Module test_b.py>
<Function test_it>
<Package zzz>
<Module test_zzz.py>
<Function test_it>
Code/plugins which rely on a specific shape of the collection tree might need to update.
:class:`pytest.Package` is no longer a :class:`pytest.Module` or :class:`pytest.File`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. versionchanged:: 8.0
The ``Package`` collector node designates a Python package, that is, a directory with an `__init__.py` file.
Previously ``Package`` was a subtype of ``pytest.Module`` (which represents a single Python module),
the module being the `__init__.py` file.
This has been deemed a design mistake (see :issue:`11137` and :issue:`7777` for details).
The ``path`` property of ``Package`` nodes now points to the package directory instead of the ``__init__.py`` file.
Note that a ``Module`` node for ``__init__.py`` (which is not a ``Package``) may still exist,
if it is picked up during collection (e.g. if you configured :confval:`python_files` to include ``__init__.py`` files).
Collecting ``__init__.py`` files no longer collects package
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. versionremoved:: 8.0
Running `pytest pkg/__init__.py` now collects the `pkg/__init__.py` file (module) only.
Previously, it collected the entire `pkg` package, including other test files in the directory, but excluding tests in the `__init__.py` file itself
(unless :confval:`python_files` was changed to allow `__init__.py` file).
To collect the entire package, specify just the directory: `pytest pkg`.
The ``pytest.collect`` module The ``pytest.collect`` module
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -938,7 +773,8 @@ Applying marks to values of a ``pytest.mark.parametrize`` call is now deprecated
(50, 500), (50, 500),
], ],
) )
def test_foo(a, b): ... def test_foo(a, b):
...
This code applies the ``pytest.mark.xfail(reason="flaky")`` mark to the ``(6, 36)`` value of the above parametrization This code applies the ``pytest.mark.xfail(reason="flaky")`` mark to the ``(6, 36)`` value of the above parametrization
call. call.
@ -961,7 +797,8 @@ To update the code, use ``pytest.param``:
(50, 500), (50, 500),
], ],
) )
def test_foo(a, b): ... def test_foo(a, b):
...
.. _pytest_funcarg__ prefix deprecated: .. _pytest_funcarg__ prefix deprecated:
@ -1112,13 +949,15 @@ This is just a matter of renaming the fixture as the API is the same:
.. code-block:: python .. code-block:: python
def test_foo(record_xml_property): ... def test_foo(record_xml_property):
...
Change to: Change to:
.. code-block:: python .. code-block:: python
def test_foo(record_property): ... def test_foo(record_property):
...
.. _passing command-line string to pytest.main deprecated: .. _passing command-line string to pytest.main deprecated:
@ -1280,7 +1119,8 @@ Example of usage:
.. code-block:: python .. code-block:: python
class MySymbol: ... class MySymbol:
...
def pytest_namespace(): def pytest_namespace():

View File

@ -1,5 +1,3 @@
from __future__ import annotations
import pytest import pytest
from pytest import raises from pytest import raises
@ -174,7 +172,7 @@ class TestRaises:
raise ValueError("demo error") raise ValueError("demo error")
def test_tupleerror(self): def test_tupleerror(self):
a, b = [1] # noqa: F841 a, b = [1] # NOQA
def test_reinterpret_fails_with_print_for_the_fun_of_it(self): def test_reinterpret_fails_with_print_for_the_fun_of_it(self):
items = [1, 2, 3] items = [1, 2, 3]
@ -182,7 +180,7 @@ class TestRaises:
a, b = items.pop() a, b = items.pop()
def test_some_error(self): def test_some_error(self):
if namenotexi: # noqa: F821 if namenotexi: # NOQA
pass pass
def func1(self): def func1(self):

View File

@ -1,10 +1,7 @@
from __future__ import annotations
import os.path import os.path
import pytest import pytest
mydir = os.path.dirname(__file__) mydir = os.path.dirname(__file__)

View File

@ -1,6 +1,3 @@
from __future__ import annotations
hello = "world" hello = "world"

View File

@ -1,9 +1,6 @@
from __future__ import annotations
import os.path import os.path
import shutil import shutil
failure_demo = os.path.join(os.path.dirname(__file__), "failure_demo.py") failure_demo = os.path.join(os.path.dirname(__file__), "failure_demo.py")
pytest_plugins = ("pytester",) pytest_plugins = ("pytester",)

View File

@ -1,6 +1,3 @@
from __future__ import annotations
def setup_module(module): def setup_module(module):
module.TestStateFullThing.classcount = 0 module.TestStateFullThing.classcount = 0

View File

@ -1,4 +1 @@
from __future__ import annotations collect_ignore = ["nonpython"]
collect_ignore = ["nonpython", "customdirectory"]

View File

@ -1,77 +0,0 @@
.. _`custom directory collectors`:
Using a custom directory collector
====================================================
By default, pytest collects directories using :class:`pytest.Package`, for directories with ``__init__.py`` files,
and :class:`pytest.Dir` for other directories.
If you want to customize how a directory is collected, you can write your own :class:`pytest.Directory` collector,
and use :hook:`pytest_collect_directory` to hook it up.
.. _`directory manifest plugin`:
A basic example for a directory manifest file
--------------------------------------------------------------
Suppose you want to customize how collection is done on a per-directory basis.
Here is an example ``conftest.py`` plugin that allows directories to contain a ``manifest.json`` file,
which defines how the collection should be done for the directory.
In this example, only a simple list of files is supported,
however you can imagine adding other keys, such as exclusions and globs.
.. include:: customdirectory/conftest.py
:literal:
You can create a ``manifest.json`` file and some test files:
.. include:: customdirectory/tests/manifest.json
:literal:
.. include:: customdirectory/tests/test_first.py
:literal:
.. include:: customdirectory/tests/test_second.py
:literal:
.. include:: customdirectory/tests/test_third.py
:literal:
An you can now execute the test specification:
.. code-block:: pytest
customdirectory $ pytest
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
rootdir: /home/sweet/project/customdirectory
configfile: pytest.ini
collected 2 items
tests/test_first.py . [ 50%]
tests/test_second.py . [100%]
============================ 2 passed in 0.12s =============================
.. regendoc:wipe
Notice how ``test_three.py`` was not executed, because it is not listed in the manifest.
You can verify that your custom collector appears in the collection tree:
.. code-block:: pytest
customdirectory $ pytest --collect-only
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
rootdir: /home/sweet/project/customdirectory
configfile: pytest.ini
collected 2 items
<Dir customdirectory>
<ManifestDirectory tests>
<Module test_first.py>
<Function test_1>
<Module test_second.py>
<Function test_2>
======================== 2 tests collected in 0.12s ========================

View File

@ -1,30 +0,0 @@
# content of conftest.py
from __future__ import annotations
import json
import pytest
class ManifestDirectory(pytest.Directory):
def collect(self):
# The standard pytest behavior is to loop over all `test_*.py` files and
# call `pytest_collect_file` on each file. This collector instead reads
# the `manifest.json` file and only calls `pytest_collect_file` for the
# files defined there.
manifest_path = self.path / "manifest.json"
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
ihook = self.ihook
for file in manifest["files"]:
yield from ihook.pytest_collect_file(
file_path=self.path / file, parent=self
)
@pytest.hookimpl
def pytest_collect_directory(path, parent):
# Use our custom collector for directories containing a `manifest.json` file.
if path.joinpath("manifest.json").is_file():
return ManifestDirectory.from_parent(parent=parent, path=path)
# Otherwise fallback to the standard behavior.
return None

Some files were not shown because too many files have changed in this diff Show More