resolve merge conflicts from main
|
@ -3,7 +3,7 @@ name: main
|
|||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
- "[0-9]+.[0-9]+.x"
|
||||
tags:
|
||||
- "[0-9]+.[0-9]+.[0-9]+"
|
||||
|
@ -11,7 +11,7 @@ on:
|
|||
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
- "[0-9]+.[0-9]+.x"
|
||||
|
||||
jobs:
|
||||
|
@ -56,7 +56,7 @@ jobs:
|
|||
- name: "windows-py37-pluggy"
|
||||
python: "3.7"
|
||||
os: windows-latest
|
||||
tox_env: "py37-pluggymaster-xdist"
|
||||
tox_env: "py37-pluggymain-xdist"
|
||||
- name: "windows-py38"
|
||||
python: "3.8"
|
||||
os: windows-latest
|
||||
|
@ -75,7 +75,7 @@ jobs:
|
|||
- name: "ubuntu-py37-pluggy"
|
||||
python: "3.7"
|
||||
os: ubuntu-latest
|
||||
tox_env: "py37-pluggymaster-xdist"
|
||||
tox_env: "py37-pluggymain-xdist"
|
||||
- name: "ubuntu-py37-freeze"
|
||||
python: "3.7"
|
||||
os: ubuntu-latest
|
||||
|
@ -89,7 +89,7 @@ jobs:
|
|||
os: ubuntu-latest
|
||||
tox_env: "py39-xdist"
|
||||
- name: "ubuntu-pypy3"
|
||||
python: "pypy3"
|
||||
python: "pypy-3.7"
|
||||
os: ubuntu-latest
|
||||
tox_env: "pypy3-xdist"
|
||||
|
||||
|
@ -137,22 +137,13 @@ jobs:
|
|||
|
||||
- name: Test with coverage
|
||||
if: "matrix.use_coverage"
|
||||
env:
|
||||
_PYTEST_TOX_COVERAGE_RUN: "coverage run -m"
|
||||
COVERAGE_PROCESS_START: ".coveragerc"
|
||||
_PYTEST_TOX_EXTRA_DEP: "coverage-enable-subprocess"
|
||||
run: "tox -e ${{ matrix.tox_env }}"
|
||||
run: "tox -e ${{ matrix.tox_env }}-coverage"
|
||||
|
||||
- name: Prepare coverage token
|
||||
if: (matrix.use_coverage && ( github.repository == 'pytest-dev/pytest' || github.event_name == 'pull_request' ))
|
||||
run: |
|
||||
python scripts/append_codecov_token.py
|
||||
|
||||
- name: Report coverage
|
||||
if: (matrix.use_coverage)
|
||||
- name: Upload coverage
|
||||
if: matrix.use_coverage && github.repository == 'pytest-dev/pytest'
|
||||
env:
|
||||
CODECOV_NAME: ${{ matrix.name }}
|
||||
run: bash scripts/report-coverage.sh -F GHA,${{ runner.os }}
|
||||
run: bash scripts/upload-coverage.sh -F GHA,${{ runner.os }}
|
||||
|
||||
linting:
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -165,7 +156,10 @@ jobs:
|
|||
with:
|
||||
path: ~/.cache/pre-commit
|
||||
key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }}
|
||||
- run: pip install tox
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install tox
|
||||
- run: tox -e linting
|
||||
|
||||
deploy:
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
name: prepare release pr
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
branch:
|
||||
description: 'Branch to base the release from'
|
||||
required: true
|
||||
default: ''
|
||||
major:
|
||||
description: 'Major release? (yes/no)'
|
||||
required: true
|
||||
default: 'no'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "3.8"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install --upgrade setuptools tox
|
||||
|
||||
- name: Prepare release PR (minor/patch release)
|
||||
if: github.event.inputs.major == 'no'
|
||||
run: |
|
||||
tox -e prepare-release-pr -- ${{ github.event.inputs.branch }} ${{ secrets.chatops }}
|
||||
|
||||
- name: Prepare release PR (major release)
|
||||
if: github.event.inputs.major == 'yes'
|
||||
run: |
|
||||
tox -e prepare-release-pr -- ${{ github.event.inputs.branch }} ${{ secrets.chatops }} --major
|
|
@ -0,0 +1,35 @@
|
|||
name: Update Plugin List
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# At 00:00 on Sunday.
|
||||
# https://crontab.guru
|
||||
- cron: '0 0 * * 0'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
createPullRequest:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install packaging requests tabulate[widechars]
|
||||
- name: Update Plugin List
|
||||
run: python scripts/update-plugin-list.py
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@2455e1596942c2902952003bbb574afbbe2ab2e6
|
||||
with:
|
||||
commit-message: '[automated] Update plugin list'
|
||||
author: 'pytest bot <pytestbot@users.noreply.github.com>'
|
||||
branch: update-plugin-list/patch
|
||||
delete-branch: true
|
||||
branch-suffix: short-commit-hash
|
||||
title: '[automated] Update plugin list'
|
||||
body: '[automated] Update plugin list'
|
|
@ -1,16 +1,16 @@
|
|||
repos:
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 19.10b0
|
||||
rev: 20.8b1
|
||||
hooks:
|
||||
- id: black
|
||||
args: [--safe, --quiet]
|
||||
- repo: https://github.com/asottile/blacken-docs
|
||||
rev: v1.8.0
|
||||
rev: v1.10.0
|
||||
hooks:
|
||||
- id: blacken-docs
|
||||
additional_dependencies: [black==19.10b0]
|
||||
additional_dependencies: [black==20.8b1]
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v3.2.0
|
||||
rev: v3.4.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
|
@ -21,7 +21,7 @@ repos:
|
|||
exclude: _pytest/(debugging|hookspec).py
|
||||
language_version: python3
|
||||
- repo: https://gitlab.com/pycqa/flake8
|
||||
rev: 3.8.3
|
||||
rev: 3.9.0
|
||||
hooks:
|
||||
- id: flake8
|
||||
language_version: python3
|
||||
|
@ -29,27 +29,25 @@ repos:
|
|||
- flake8-typing-imports==1.9.0
|
||||
- flake8-docstrings==1.5.0
|
||||
- repo: https://github.com/asottile/reorder_python_imports
|
||||
rev: v2.3.5
|
||||
rev: v2.4.0
|
||||
hooks:
|
||||
- id: reorder-python-imports
|
||||
args: ['--application-directories=.:src', --py36-plus]
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v2.7.2
|
||||
rev: v2.10.0
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: [--py36-plus]
|
||||
- repo: https://github.com/asottile/setup-cfg-fmt
|
||||
rev: v1.11.0
|
||||
rev: v1.17.0
|
||||
hooks:
|
||||
- id: setup-cfg-fmt
|
||||
# TODO: when upgrading setup-cfg-fmt this can be removed
|
||||
args: [--max-py-version=3.9]
|
||||
- repo: https://github.com/pre-commit/pygrep-hooks
|
||||
rev: v1.6.0
|
||||
rev: v1.8.0
|
||||
hooks:
|
||||
- id: python-use-type-annotations
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v0.790
|
||||
rev: v0.812
|
||||
hooks:
|
||||
- id: mypy
|
||||
files: ^(src/|testing/)
|
||||
|
@ -89,3 +87,9 @@ repos:
|
|||
xml\.
|
||||
)
|
||||
types: [python]
|
||||
- id: py-path-deprecated
|
||||
name: py.path usage is deprecated
|
||||
language: pygrep
|
||||
entry: \bpy\.path\.local
|
||||
exclude: docs
|
||||
types: [python]
|
||||
|
|
10
AUTHORS
|
@ -21,6 +21,7 @@ Anders Hovmöller
|
|||
Andras Mitzki
|
||||
Andras Tim
|
||||
Andrea Cimatoribus
|
||||
Andreas Motl
|
||||
Andreas Zeidler
|
||||
Andrey Paramonov
|
||||
Andrzej Klajnert
|
||||
|
@ -29,6 +30,7 @@ Andy Freeland
|
|||
Anthon van der Neut
|
||||
Anthony Shaw
|
||||
Anthony Sottile
|
||||
Anton Grinevich
|
||||
Anton Lodder
|
||||
Antony Lee
|
||||
Arel Cordero
|
||||
|
@ -39,6 +41,7 @@ Aron Curzon
|
|||
Aviral Verma
|
||||
Aviv Palivoda
|
||||
Barney Gale
|
||||
Ben Gartner
|
||||
Ben Webb
|
||||
Benjamin Peterson
|
||||
Bernard Pratz
|
||||
|
@ -56,6 +59,7 @@ Charles Cloud
|
|||
Charles Machalow
|
||||
Charnjit SiNGH (CCSJ)
|
||||
Chris Lamb
|
||||
Chris NeJame
|
||||
Christian Boelsen
|
||||
Christian Fetzer
|
||||
Christian Neumüller
|
||||
|
@ -74,6 +78,7 @@ Daniel Grana
|
|||
Daniel Hahler
|
||||
Daniel Nuri
|
||||
Daniel Wandschneider
|
||||
Daniele Procida
|
||||
Danielle Jenkins
|
||||
Daniil Galiev
|
||||
Dave Hunt
|
||||
|
@ -89,6 +94,7 @@ Dhiren Serai
|
|||
Diego Russo
|
||||
Dmitry Dygalo
|
||||
Dmitry Pribysh
|
||||
Dominic Mortlock
|
||||
Duncan Betts
|
||||
Edison Gustavo Muenz
|
||||
Edoardo Batini
|
||||
|
@ -200,6 +206,7 @@ Matthias Hafner
|
|||
Maxim Filipenko
|
||||
Maximilian Cosmo Sitter
|
||||
mbyt
|
||||
Mickey Pashov
|
||||
Michael Aquilina
|
||||
Michael Birtwell
|
||||
Michael Droettboom
|
||||
|
@ -232,10 +239,12 @@ Pauli Virtanen
|
|||
Pavel Karateev
|
||||
Paweł Adamczak
|
||||
Pedro Algarvio
|
||||
Petter Strandmark
|
||||
Philipp Loose
|
||||
Pieter Mulder
|
||||
Piotr Banaszkiewicz
|
||||
Piotr Helm
|
||||
Prakhar Gurunani
|
||||
Prashant Anand
|
||||
Prashant Sharma
|
||||
Pulkit Goyal
|
||||
|
@ -267,6 +276,7 @@ Sankt Petersbug
|
|||
Segev Finer
|
||||
Serhii Mozghovyi
|
||||
Seth Junot
|
||||
Shubham Adep
|
||||
Simon Gomizelj
|
||||
Simon Kerr
|
||||
Skylar Downes
|
||||
|
|
|
@ -236,7 +236,7 @@ Here is a simple overview, with pytest-specific bits:
|
|||
$ cd pytest
|
||||
# now, create your own branch off "master":
|
||||
|
||||
$ git checkout -b your-bugfix-branch-name master
|
||||
$ git checkout -b your-bugfix-branch-name main
|
||||
|
||||
Given we have "major.minor.micro" version numbers, bug fixes will usually
|
||||
be released in micro releases whereas features will be released in
|
||||
|
@ -318,26 +318,26 @@ Here is a simple overview, with pytest-specific bits:
|
|||
compare: your-branch-name
|
||||
|
||||
base-fork: pytest-dev/pytest
|
||||
base: master
|
||||
base: main
|
||||
|
||||
|
||||
Writing Tests
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Writing tests for plugins or for pytest itself is often done using the `testdir fixture <https://docs.pytest.org/en/stable/reference.html#testdir>`_, as a "black-box" test.
|
||||
Writing tests for plugins or for pytest itself is often done using the `pytester fixture <https://docs.pytest.org/en/stable/reference.html#pytester>`_, as a "black-box" test.
|
||||
|
||||
For example, to ensure a simple test passes you can write:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_true_assertion(testdir):
|
||||
testdir.makepyfile(
|
||||
def test_true_assertion(pytester):
|
||||
pytester.makepyfile(
|
||||
"""
|
||||
def test_foo():
|
||||
assert True
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result = pytester.runpytest()
|
||||
result.assert_outcomes(failed=0, passed=1)
|
||||
|
||||
|
||||
|
@ -346,14 +346,14 @@ Alternatively, it is possible to make checks based on the actual output of the t
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
def test_true_assertion(testdir):
|
||||
testdir.makepyfile(
|
||||
def test_true_assertion(pytester):
|
||||
pytester.makepyfile(
|
||||
"""
|
||||
def test_foo():
|
||||
assert False
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result = pytester.runpytest()
|
||||
result.stdout.fnmatch_lines(["*assert False*", "*1 failed*"])
|
||||
|
||||
When choosing a file where to write a new test, take a look at the existing files and see if there's
|
||||
|
|
18
README.rst
|
@ -1,6 +1,7 @@
|
|||
.. image:: https://docs.pytest.org/en/stable/_static/pytest1.png
|
||||
.. image:: https://github.com/pytest-dev/pytest/raw/main/doc/en/img/pytest_logo_curves.svg
|
||||
:target: https://docs.pytest.org/en/stable/
|
||||
:align: center
|
||||
:height: 200
|
||||
:alt: pytest
|
||||
|
||||
|
||||
|
@ -15,16 +16,17 @@
|
|||
.. image:: https://img.shields.io/pypi/pyversions/pytest.svg
|
||||
:target: https://pypi.org/project/pytest/
|
||||
|
||||
.. image:: https://codecov.io/gh/pytest-dev/pytest/branch/master/graph/badge.svg
|
||||
.. image:: https://codecov.io/gh/pytest-dev/pytest/branch/main/graph/badge.svg
|
||||
:target: https://codecov.io/gh/pytest-dev/pytest
|
||||
:alt: Code coverage Status
|
||||
|
||||
.. image:: https://travis-ci.org/pytest-dev/pytest.svg?branch=master
|
||||
:target: https://travis-ci.org/pytest-dev/pytest
|
||||
|
||||
.. image:: https://github.com/pytest-dev/pytest/workflows/main/badge.svg
|
||||
:target: https://github.com/pytest-dev/pytest/actions?query=workflow%3Amain
|
||||
|
||||
.. image:: https://results.pre-commit.ci/badge/github/pytest-dev/pytest/main.svg
|
||||
:target: https://results.pre-commit.ci/latest/github/pytest-dev/pytest/master
|
||||
:alt: pre-commit.ci status
|
||||
|
||||
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
||||
:target: https://github.com/psf/black
|
||||
|
||||
|
@ -91,7 +93,7 @@ Features
|
|||
|
||||
- Python 3.6+ and PyPy3
|
||||
|
||||
- Rich plugin architecture, with over 850+ `external plugins <http://plugincompat.herokuapp.com>`_ and thriving community
|
||||
- Rich plugin architecture, with over 850+ `external plugins <https://docs.pytest.org/en/stable/plugin_list.html>`_ and thriving community
|
||||
|
||||
|
||||
Documentation
|
||||
|
@ -149,8 +151,8 @@ Tidelift will coordinate the fix and disclosure.
|
|||
License
|
||||
-------
|
||||
|
||||
Copyright Holger Krekel and others, 2004-2020.
|
||||
Copyright Holger Krekel and others, 2004-2021.
|
||||
|
||||
Distributed under the terms of the `MIT`_ license, pytest is free and open source software.
|
||||
|
||||
.. _`MIT`: https://github.com/pytest-dev/pytest/blob/master/LICENSE
|
||||
.. _`MIT`: https://github.com/pytest-dev/pytest/blob/main/LICENSE
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
Fixed quadratic behavior and improved performance of collection of items using autouse fixtures and xunit fixtures.
|
|
@ -0,0 +1 @@
|
|||
Add automatically generated :ref:`plugin-list`. The list is updated on a periodic schedule.
|
|
@ -0,0 +1,2 @@
|
|||
Added :meth:`cache.mkdir() <pytest.Cache.mkdir>`, which is similar to the existing :meth:`cache.makedir() <pytest.Cache.makedir>`,
|
||||
but returns a :class:`pathlib.Path` instead of a legacy ``py.path.local``.
|
|
@ -1,5 +0,0 @@
|
|||
New :fixture:`pytester` fixture, which is identical to :fixture:`testdir` but its methods return :class:`pathlib.Path` when appropriate instead of ``py.path.local``.
|
||||
|
||||
This is part of the movement to use :class:`pathlib.Path` objects internally, in order to remove the dependency to ``py`` in the future.
|
||||
|
||||
Internally, the old :class:`Testdir` is now a thin wrapper around :class:`Pytester`, preserving the old interface.
|
|
@ -0,0 +1,10 @@
|
|||
Directly constructing the following classes is now deprecated:
|
||||
|
||||
- ``_pytest.mark.structures.Mark``
|
||||
- ``_pytest.mark.structures.MarkDecorator``
|
||||
- ``_pytest.mark.structures.MarkGenerator``
|
||||
- ``_pytest.python.Metafunc``
|
||||
- ``_pytest.runner.CallInfo``
|
||||
- ``_pytest._code.ExceptionInfo``
|
||||
|
||||
These have always been considered private, but now issue a deprecation warning, which may become a hard error in pytest 7.0.0.
|
|
@ -0,0 +1,15 @@
|
|||
The types of objects used in pytest's API are now exported so they may be used in type annotations.
|
||||
|
||||
The newly-exported types are:
|
||||
|
||||
- ``pytest.Mark`` for :class:`marks <pytest.Mark>`.
|
||||
- ``pytest.MarkDecorator`` for :class:`mark decorators <pytest.MarkDecorator>`.
|
||||
- ``pytest.MarkGenerator`` for the :class:`pytest.mark <pytest.MarkGenerator>` singleton.
|
||||
- ``pytest.Metafunc`` for the :class:`metafunc <pytest.MarkGenerator>` argument to the :func:`pytest_generate_tests <pytest.hookspec.pytest_generate_tests>` hook.
|
||||
- ``pytest.CallInfo`` for the :class:`CallInfo <pytest.CallInfo>` type passed to various hooks.
|
||||
- ``pytest.ExceptionInfo`` for the :class:`ExceptionInfo <pytest.ExceptionInfo>` type returned from :func:`pytest.raises` and passed to various hooks.
|
||||
|
||||
Constructing them directly is not supported; they are only meant for use in type annotations.
|
||||
Doing so will emit a deprecation warning, and may become a hard-error in pytest 7.0.
|
||||
|
||||
Subclassing them is also not supported. This is not currently enforced at runtime, but is detected by type-checkers such as mypy.
|
|
@ -1 +0,0 @@
|
|||
When a comparison between `namedtuple` instances of the same type fails, pytest now shows the differing field names (possibly nested) instead of their indexes.
|
|
@ -1,4 +0,0 @@
|
|||
The ``--strict`` command-line option has been deprecated, use ``--strict-markers`` instead.
|
||||
|
||||
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).
|
|
@ -1 +0,0 @@
|
|||
Improved reporting when using ``--collected-only``. It will now show the number of collected tests in the summary stats.
|
|
@ -1,3 +0,0 @@
|
|||
Use strict equality comparison for nonnumeric types in ``approx`` instead of
|
||||
raising ``TypeError``.
|
||||
This was the undocumented behavior before 3.7, but is now officially a supported feature.
|
|
@ -1 +0,0 @@
|
|||
Fixed an issue where some files in packages are getting lost from ``--lf`` even though they contain tests that failed. Regressed in pytest 5.4.0.
|
|
@ -1 +0,0 @@
|
|||
Classes which should not be inherited from are now marked ``final class`` in the API reference.
|
|
@ -1 +0,0 @@
|
|||
The ``attrs`` dependency requirement is now >=19.2.0 instead of >=17.4.0.
|
|
@ -1 +0,0 @@
|
|||
pytest now supports python3.6+ only.
|
|
@ -1 +0,0 @@
|
|||
``_pytest.config.argparsing.Parser.addini()`` accepts explicit ``None`` and ``"string"``.
|
|
@ -1 +0,0 @@
|
|||
In pull request section, ask to commit after editing changelog and authors file.
|
|
@ -1 +0,0 @@
|
|||
Directories created by `tmpdir` are now considered stale after 3 days without modification (previous value was 3 hours) to avoid deleting directories still in use in long running test suites.
|
|
@ -1 +0,0 @@
|
|||
Fixed a crash or hang in ``pytester.spawn`` when the ``readline`` module is involved.
|
|
@ -1 +0,0 @@
|
|||
New ``--sw-skip`` argument which is a shorthand for ``--stepwise-skip``.
|
|
@ -1 +0,0 @@
|
|||
Fixed handling of recursive symlinks when collecting tests.
|
|
@ -1 +0,0 @@
|
|||
Fixed symlinked directories not being followed during collection. Regressed in pytest 6.1.0.
|
|
@ -1,3 +0,0 @@
|
|||
The ``@pytest.yield_fixture`` decorator/function is now deprecated. Use :func:`pytest.fixture` instead.
|
||||
|
||||
``yield_fixture`` has been an alias for ``fixture`` for a very long time, so can be search/replaced safely.
|
|
@ -1,8 +0,0 @@
|
|||
It is now possible to construct a :class:`~pytest.MonkeyPatch` object directly as ``pytest.MonkeyPatch()``,
|
||||
in cases when the :fixture:`monkeypatch` fixture cannot be used. Previously some users imported it
|
||||
from the private `_pytest.monkeypatch.MonkeyPatch` namespace.
|
||||
|
||||
Additionally, :meth:`MonkeyPatch.context <pytest.MonkeyPatch.context>` is now a classmethod,
|
||||
and can be used as ``with MonkeyPatch.context() as mp: ...``. This is the recommended way to use
|
||||
``MonkeyPatch`` directly, since unlike the ``monkeypatch`` fixture, an instance created directly
|
||||
is not ``undo()``-ed automatically.
|
|
@ -1,2 +0,0 @@
|
|||
`.pyc` files created by pytest's assertion rewriting now conform to the newer PEP-552 format on Python>=3.7.
|
||||
(These files are internal and only interpreted by pytest itself.)
|
|
@ -1 +0,0 @@
|
|||
Fixed only one doctest being collected when using ``pytest --doctest-modules path/to/an/__init__.py``.
|
|
@ -1 +0,0 @@
|
|||
Added ``'node_modules'`` to default value for ``norecursedirs``.
|
|
@ -0,0 +1 @@
|
|||
Fixed failing staticmethod test cases if they are inherited from a parent test class.
|
|
@ -0,0 +1,7 @@
|
|||
The following hooks now receive an additional ``pathlib.Path`` argument, equivalent to an existing ``py.path.local`` argument:
|
||||
|
||||
- :func:`pytest_ignore_collect <_pytest.hookspec.pytest_ignore_collect>` - The ``fspath`` parameter (equivalent to existing ``path`` parameter).
|
||||
- :func:`pytest_collect_file <_pytest.hookspec.pytest_collect_file>` - The ``fspath`` parameter (equivalent to existing ``path`` parameter).
|
||||
- :func:`pytest_pycollect_makemodule <_pytest.hookspec.pytest_pycollect_makemodule>` - The ``fspath`` parameter (equivalent to existing ``path`` parameter).
|
||||
- :func:`pytest_report_header <_pytest.hookspec.pytest_report_header>` - The ``startpath`` parameter (equivalent to existing ``startdir`` parameter).
|
||||
- :func:`pytest_report_collectionfinish <_pytest.hookspec.pytest_report_collectionfinish>` - The ``startpath`` parameter (equivalent to existing ``startdir`` parameter).
|
|
@ -0,0 +1,6 @@
|
|||
The following changes have been made to internal pytest types/functions:
|
||||
|
||||
- The ``path`` property of ``_pytest.code.Code`` returns ``Path`` instead of ``py.path.local``.
|
||||
- The ``path`` property of ``_pytest.code.TracebackEntry`` returns ``Path`` instead of ``py.path.local``.
|
||||
- The ``_pytest.code.getfslineno()`` function returns ``Path`` instead of ``py.path.local``.
|
||||
- The ``_pytest.python.path_matches_patterns()`` function takes ``Path`` instead of ``py.path.local``.
|
|
@ -0,0 +1,3 @@
|
|||
``testdir.makefile`` now silently accepts values which don't start with ``.`` to maintain backward compatibility with older pytest versions.
|
||||
|
||||
``pytester.makefile`` now issues a clearer error if the ``.`` is missing in the ``ext`` argument.
|
|
@ -0,0 +1,7 @@
|
|||
Raising :class:`unittest.SkipTest` to skip collection of tests during the
|
||||
pytest collection phase is deprecated. Use :func:`pytest.skip` instead.
|
||||
|
||||
Note: This deprecation only relates to using `unittest.SkipTest` during test
|
||||
collection. You are probably not doing that. Ordinary usage of
|
||||
:class:`unittest.SkipTest` / :meth:`unittest.TestCase.skipTest` /
|
||||
:func:`unittest.skip` in unittest test cases is fully supported.
|
|
@ -0,0 +1 @@
|
|||
Internal Restructure: let python.PyObjMixing inherit from nodes.Node to carry over typing information.
|
|
@ -0,0 +1 @@
|
|||
Deprecate ``Node.fspath`` as we plan to move off `py.path.local <https://py.readthedocs.io/en/latest/path.html>`__ and switch to :mod:``pathlib``.
|
|
@ -0,0 +1 @@
|
|||
Implement ``Node.path`` as a ``pathlib.Path``.
|
|
@ -0,0 +1,3 @@
|
|||
Fixed issue where pytest's ``faulthandler`` support would not dump traceback on crashes
|
||||
if the :mod:`faulthandler` module was already enabled during pytest startup (using
|
||||
``python -X dev -m pytest`` for example).
|
|
@ -0,0 +1,5 @@
|
|||
Several behaviors of :meth:`Parser.addoption <_pytest.config.argparsing.Parser.addoption>` are now
|
||||
scheduled for removal in pytest 7 (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.
|
|
@ -0,0 +1 @@
|
|||
Fixed an issue where illegal directory characters derived from ``getpass.getuser()`` raised an ``OSError``.
|
|
@ -0,0 +1 @@
|
|||
Fix ``Class.from_parent`` so it forwards extra keyword arguments to the constructor.
|
|
@ -0,0 +1 @@
|
|||
The ``@pytest.mark.skip`` decorator now correctly handles its arguments. When the ``reason`` argument is accidentally given both positional and as a keyword (e.g. because it was confused with ``skipif``), a ``TypeError`` now occurs. Before, such tests were silently skipped, and the positional argument ignored. Additionally, ``reason`` is now documented correctly as positional or keyword (rather than keyword-only).
|
|
@ -0,0 +1 @@
|
|||
Use private names for internal fixtures that handle classic setup/teardown so that they don't show up with the default ``--fixtures`` invocation (but they still show up with ``--fixtures -v``).
|
|
@ -0,0 +1 @@
|
|||
Assert the outcomes for the issue 518 test and fix the test.
|
|
@ -0,0 +1 @@
|
|||
:func:`pytest.approx` now works on :class:`~decimal.Decimal` within mappings/dicts and sequences/lists.
|
|
@ -0,0 +1 @@
|
|||
The :confval:`required_plugins` config option now works correctly when pre-releases of plugins are installed, rather than falsely claiming that those plugins aren't installed at all.
|
|
@ -1,12 +1,19 @@
|
|||
<h3><a href="{{ pathto(master_doc) }}">{{ _('Table Of Contents') }}</a></h3>
|
||||
<h3>Contents</h3>
|
||||
|
||||
<ul>
|
||||
<li><a href="{{ pathto('index') }}">Home</a></li>
|
||||
<li><a href="{{ pathto('getting-started') }}">Install</a></li>
|
||||
<li><a href="{{ pathto('contents') }}">Contents</a></li>
|
||||
<li><a href="{{ pathto('reference') }}">API Reference</a></li>
|
||||
<li><a href="{{ pathto('example/index') }}">Examples</a></li>
|
||||
<li><a href="{{ pathto('customize') }}">Customize</a></li>
|
||||
|
||||
<li><a href="{{ pathto('getting-started') }}">Get started</a></li>
|
||||
<li><a href="{{ pathto('how-to/index') }}">How-to guides</a></li>
|
||||
<li><a href="{{ pathto('reference/index') }}">Reference guides</a></li>
|
||||
<li><a href="{{ pathto('explanation/index') }}">Explanation</a></li>
|
||||
<li><a href="{{ pathto('contents') }}">Complete table of contents</a></li>
|
||||
<li><a href="{{ pathto('example/index') }}">Library of examples</a></li>
|
||||
</ul>
|
||||
|
||||
<h3>About the project</h3>
|
||||
|
||||
<ul>
|
||||
<li><a href="{{ pathto('changelog') }}">Changelog</a></li>
|
||||
<li><a href="{{ pathto('contributing') }}">Contributing</a></li>
|
||||
<li><a href="{{ pathto('backwards-compatibility') }}">Backwards Compatibility</a></li>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<ul>
|
||||
<li><a href="https://pypi.org/project/pytest/">pytest @ PyPI</a></li>
|
||||
<li><a href="https://github.com/pytest-dev/pytest/">pytest @ GitHub</a></li>
|
||||
<li><a href="http://plugincompat.herokuapp.com/">3rd party plugins</a></li>
|
||||
<li><a href="https://github.com/pytest-dev/pytest/issues">Issue Tracker</a></li>
|
||||
<li><a href="https://media.readthedocs.org/pdf/pytest/latest/pytest.pdf">PDF Documentation</a>
|
||||
</ul>
|
||||
|
|
|
@ -6,6 +6,9 @@ Release announcements
|
|||
:maxdepth: 2
|
||||
|
||||
|
||||
release-6.2.2
|
||||
release-6.2.1
|
||||
release-6.2.0
|
||||
release-6.1.2
|
||||
release-6.1.1
|
||||
release-6.1.0
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
pytest-6.2.0
|
||||
=======================================
|
||||
|
||||
The pytest team is proud to announce the 6.2.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:
|
||||
|
||||
* Adam Johnson
|
||||
* Albert Villanova del Moral
|
||||
* Anthony Sottile
|
||||
* Anton
|
||||
* Ariel Pillemer
|
||||
* Bruno Oliveira
|
||||
* Charles Aracil
|
||||
* Christine M
|
||||
* Christine Mecklenborg
|
||||
* Cserna Zsolt
|
||||
* Dominic Mortlock
|
||||
* Emiel van de Laar
|
||||
* Florian Bruhin
|
||||
* Garvit Shubham
|
||||
* Gustavo Camargo
|
||||
* Hugo Martins
|
||||
* Hugo van Kemenade
|
||||
* Jakob van Santen
|
||||
* Josias Aurel
|
||||
* Jürgen Gmach
|
||||
* Karthikeyan Singaravelan
|
||||
* Katarzyna
|
||||
* Kyle Altendorf
|
||||
* Manuel Mariñez
|
||||
* Matthew Hughes
|
||||
* Matthias Gabriel
|
||||
* Max Voitko
|
||||
* Maximilian Cosmo Sitter
|
||||
* Mikhail Fesenko
|
||||
* Nimesh Vashistha
|
||||
* Pedro Algarvio
|
||||
* Petter Strandmark
|
||||
* Prakhar Gurunani
|
||||
* Prashant Sharma
|
||||
* Ran Benita
|
||||
* Ronny Pfannschmidt
|
||||
* Sanket Duthade
|
||||
* Shubham Adep
|
||||
* Simon K
|
||||
* Tanvi Mehta
|
||||
* Thomas Grainger
|
||||
* Tim Hoffmann
|
||||
* Vasilis Gerakaris
|
||||
* William Jamir Silva
|
||||
* Zac Hatfield-Dodds
|
||||
* crricks
|
||||
* dependabot[bot]
|
||||
* duthades
|
||||
* frankgerhardt
|
||||
* kwgchi
|
||||
* mickeypash
|
||||
* symonk
|
||||
|
||||
|
||||
Happy testing,
|
||||
The pytest Development Team
|
|
@ -0,0 +1,20 @@
|
|||
pytest-6.2.1
|
||||
=======================================
|
||||
|
||||
pytest 6.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
|
||||
* Jakob van Santen
|
||||
* Ran Benita
|
||||
|
||||
|
||||
Happy testing,
|
||||
The pytest Development Team
|
|
@ -0,0 +1,21 @@
|
|||
pytest-6.2.2
|
||||
=======================================
|
||||
|
||||
pytest 6.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:
|
||||
|
||||
* Adam Johnson
|
||||
* Bruno Oliveira
|
||||
* Chris NeJame
|
||||
* Ran Benita
|
||||
|
||||
|
||||
Happy testing,
|
||||
The pytest Development Team
|
|
@ -6,7 +6,7 @@ Pytest API and builtin fixtures
|
|||
================================================
|
||||
|
||||
|
||||
Most of the information of this page has been moved over to :ref:`reference`.
|
||||
Most of the information of this page has been moved over to :ref:`api-reference`.
|
||||
|
||||
For information on plugin hooks and objects, see :ref:`plugins`.
|
||||
|
||||
|
@ -148,16 +148,21 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
|
|||
on warning categories.
|
||||
|
||||
tmpdir_factory [session scope]
|
||||
Return a :class:`_pytest.tmpdir.TempdirFactory` instance for the test session.
|
||||
Return a :class:`pytest.TempdirFactory` instance for the test session.
|
||||
|
||||
tmp_path_factory [session scope]
|
||||
Return a :class:`_pytest.tmpdir.TempPathFactory` instance for the test session.
|
||||
Return a :class:`pytest.TempPathFactory` instance for the test session.
|
||||
|
||||
tmpdir
|
||||
Return a temporary directory path object which is unique to each test
|
||||
function invocation, created as a sub directory of the base temporary
|
||||
directory.
|
||||
|
||||
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
|
||||
``--basetemp`` is used then it is cleared each session. See :ref:`base
|
||||
temporary directory`.
|
||||
|
||||
The returned object is a `py.path.local`_ path object.
|
||||
|
||||
.. _`py.path.local`: https://py.readthedocs.io/en/latest/path.html
|
||||
|
@ -167,6 +172,11 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
|
|||
function invocation, created as a sub directory of the base temporary
|
||||
directory.
|
||||
|
||||
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
|
||||
``--basetemp`` is used then it is cleared each session. See :ref:`base
|
||||
temporary directory`.
|
||||
|
||||
The returned object is a :class:`pathlib.Path` object.
|
||||
|
||||
|
||||
|
|
|
@ -28,6 +28,237 @@ with advance notice in the **Deprecations** section of releases.
|
|||
|
||||
.. towncrier release notes start
|
||||
|
||||
pytest 6.2.2 (2021-01-25)
|
||||
=========================
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- `#8152 <https://github.com/pytest-dev/pytest/issues/8152>`_: Fixed "(<Skipped instance>)" being shown as a skip reason in the verbose test summary line when the reason is empty.
|
||||
|
||||
|
||||
- `#8249 <https://github.com/pytest-dev/pytest/issues/8249>`_: Fix the ``faulthandler`` plugin for occasions when running with ``twisted.logger`` and using ``pytest --capture=no``.
|
||||
|
||||
|
||||
pytest 6.2.1 (2020-12-15)
|
||||
=========================
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- `#7678 <https://github.com/pytest-dev/pytest/issues/7678>`_: Fixed bug where ``ImportPathMismatchError`` would be raised for files compiled in
|
||||
the host and loaded later from an UNC mounted path (Windows).
|
||||
|
||||
|
||||
- `#8132 <https://github.com/pytest-dev/pytest/issues/8132>`_: Fixed regression in ``approx``: in 6.2.0 ``approx`` no longer raises
|
||||
``TypeError`` when dealing with non-numeric types, falling back to normal comparison.
|
||||
Before 6.2.0, array types like tf.DeviceArray fell through to the scalar case,
|
||||
and happened to compare correctly to a scalar if they had only one element.
|
||||
After 6.2.0, these types began failing, because they inherited neither from
|
||||
standard Python number hierarchy nor from ``numpy.ndarray``.
|
||||
|
||||
``approx`` now converts arguments to ``numpy.ndarray`` if they expose the array
|
||||
protocol and are not scalars. This treats array-like objects like numpy arrays,
|
||||
regardless of size.
|
||||
|
||||
|
||||
pytest 6.2.0 (2020-12-12)
|
||||
=========================
|
||||
|
||||
Breaking Changes
|
||||
----------------
|
||||
|
||||
- `#7808 <https://github.com/pytest-dev/pytest/issues/7808>`_: pytest now supports python3.6+ only.
|
||||
|
||||
|
||||
|
||||
Deprecations
|
||||
------------
|
||||
|
||||
- `#7469 <https://github.com/pytest-dev/pytest/issues/7469>`_: Directly constructing/calling the following classes/functions is now deprecated:
|
||||
|
||||
- ``_pytest.cacheprovider.Cache``
|
||||
- ``_pytest.cacheprovider.Cache.for_config()``
|
||||
- ``_pytest.cacheprovider.Cache.clear_cache()``
|
||||
- ``_pytest.cacheprovider.Cache.cache_dir_from_config()``
|
||||
- ``_pytest.capture.CaptureFixture``
|
||||
- ``_pytest.fixtures.FixtureRequest``
|
||||
- ``_pytest.fixtures.SubRequest``
|
||||
- ``_pytest.logging.LogCaptureFixture``
|
||||
- ``_pytest.pytester.Pytester``
|
||||
- ``_pytest.pytester.Testdir``
|
||||
- ``_pytest.recwarn.WarningsRecorder``
|
||||
- ``_pytest.recwarn.WarningsChecker``
|
||||
- ``_pytest.tmpdir.TempPathFactory``
|
||||
- ``_pytest.tmpdir.TempdirFactory``
|
||||
|
||||
These have always been considered private, but now issue a deprecation warning, which may become a hard error in pytest 7.0.0.
|
||||
|
||||
|
||||
- `#7530 <https://github.com/pytest-dev/pytest/issues/7530>`_: The ``--strict`` command-line option has been deprecated, use ``--strict-markers`` instead.
|
||||
|
||||
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).
|
||||
|
||||
|
||||
- `#7988 <https://github.com/pytest-dev/pytest/issues/7988>`_: The ``@pytest.yield_fixture`` decorator/function is now deprecated. Use :func:`pytest.fixture` instead.
|
||||
|
||||
``yield_fixture`` has been an alias for ``fixture`` for a very long time, so can be search/replaced safely.
|
||||
|
||||
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- `#5299 <https://github.com/pytest-dev/pytest/issues/5299>`_: pytest now warns about unraisable exceptions and unhandled thread exceptions that occur in tests on Python>=3.8.
|
||||
See :ref:`unraisable` for more information.
|
||||
|
||||
|
||||
- `#7425 <https://github.com/pytest-dev/pytest/issues/7425>`_: New :fixture:`pytester` fixture, which is identical to :fixture:`testdir` but its methods return :class:`pathlib.Path` when appropriate instead of ``py.path.local``.
|
||||
|
||||
This is part of the movement to use :class:`pathlib.Path` objects internally, in order to remove the dependency to ``py`` in the future.
|
||||
|
||||
Internally, the old :class:`Testdir <_pytest.pytester.Testdir>` is now a thin wrapper around :class:`Pytester <_pytest.pytester.Pytester>`, preserving the old interface.
|
||||
|
||||
|
||||
- `#7695 <https://github.com/pytest-dev/pytest/issues/7695>`_: A new hook was added, `pytest_markeval_namespace` which should return a dictionary.
|
||||
This dictionary will be used to augment the "global" variables available to evaluate skipif/xfail/xpass markers.
|
||||
|
||||
Pseudo example
|
||||
|
||||
``conftest.py``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def pytest_markeval_namespace():
|
||||
return {"color": "red"}
|
||||
|
||||
``test_func.py``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@pytest.mark.skipif("color == 'blue'", reason="Color is not red")
|
||||
def test_func():
|
||||
assert False
|
||||
|
||||
|
||||
- `#8006 <https://github.com/pytest-dev/pytest/issues/8006>`_: It is now possible to construct a :class:`~pytest.MonkeyPatch` object directly as ``pytest.MonkeyPatch()``,
|
||||
in cases when the :fixture:`monkeypatch` fixture cannot be used. Previously some users imported it
|
||||
from the private `_pytest.monkeypatch.MonkeyPatch` namespace.
|
||||
|
||||
Additionally, :meth:`MonkeyPatch.context <pytest.MonkeyPatch.context>` is now a classmethod,
|
||||
and can be used as ``with MonkeyPatch.context() as mp: ...``. This is the recommended way to use
|
||||
``MonkeyPatch`` directly, since unlike the ``monkeypatch`` fixture, an instance created directly
|
||||
is not ``undo()``-ed automatically.
|
||||
|
||||
|
||||
|
||||
Improvements
|
||||
------------
|
||||
|
||||
- `#1265 <https://github.com/pytest-dev/pytest/issues/1265>`_: Added an ``__str__`` implementation to the :class:`~pytest.pytester.LineMatcher` class which is returned from ``pytester.run_pytest().stdout`` and similar. It returns the entire output, like the existing ``str()`` method.
|
||||
|
||||
|
||||
- `#2044 <https://github.com/pytest-dev/pytest/issues/2044>`_: Verbose mode now shows the reason that a test was skipped in the test's terminal line after the "SKIPPED", "XFAIL" or "XPASS".
|
||||
|
||||
|
||||
- `#7469 <https://github.com/pytest-dev/pytest/issues/7469>`_ The types of builtin pytest fixtures are now exported so they may be used in type annotations of test functions.
|
||||
The newly-exported types are:
|
||||
|
||||
- ``pytest.FixtureRequest`` for the :fixture:`request` fixture.
|
||||
- ``pytest.Cache`` for the :fixture:`cache` fixture.
|
||||
- ``pytest.CaptureFixture[str]`` for the :fixture:`capfd` and :fixture:`capsys` fixtures.
|
||||
- ``pytest.CaptureFixture[bytes]`` for the :fixture:`capfdbinary` and :fixture:`capsysbinary` fixtures.
|
||||
- ``pytest.LogCaptureFixture`` for the :fixture:`caplog` fixture.
|
||||
- ``pytest.Pytester`` for the :fixture:`pytester` fixture.
|
||||
- ``pytest.Testdir`` for the :fixture:`testdir` fixture.
|
||||
- ``pytest.TempdirFactory`` for the :fixture:`tmpdir_factory` fixture.
|
||||
- ``pytest.TempPathFactory`` for the :fixture:`tmp_path_factory` fixture.
|
||||
- ``pytest.MonkeyPatch`` for the :fixture:`monkeypatch` fixture.
|
||||
- ``pytest.WarningsRecorder`` for the :fixture:`recwarn` fixture.
|
||||
|
||||
Constructing them is not supported (except for `MonkeyPatch`); they are only meant for use in type annotations.
|
||||
Doing so will emit a deprecation warning, and may become a hard-error in pytest 7.0.
|
||||
|
||||
Subclassing them is also not supported. This is not currently enforced at runtime, but is detected by type-checkers such as mypy.
|
||||
|
||||
|
||||
- `#7527 <https://github.com/pytest-dev/pytest/issues/7527>`_: When a comparison between :func:`namedtuple <collections.namedtuple>` instances of the same type fails, pytest now shows the differing field names (possibly nested) instead of their indexes.
|
||||
|
||||
|
||||
- `#7615 <https://github.com/pytest-dev/pytest/issues/7615>`_: :meth:`Node.warn <_pytest.nodes.Node.warn>` now permits any subclass of :class:`Warning`, not just :class:`PytestWarning <pytest.PytestWarning>`.
|
||||
|
||||
|
||||
- `#7701 <https://github.com/pytest-dev/pytest/issues/7701>`_: Improved reporting when using ``--collected-only``. It will now show the number of collected tests in the summary stats.
|
||||
|
||||
|
||||
- `#7710 <https://github.com/pytest-dev/pytest/issues/7710>`_: Use strict equality comparison for non-numeric types in :func:`pytest.approx` instead of
|
||||
raising :class:`TypeError`.
|
||||
|
||||
This was the undocumented behavior before 3.7, but is now officially a supported feature.
|
||||
|
||||
|
||||
- `#7938 <https://github.com/pytest-dev/pytest/issues/7938>`_: New ``--sw-skip`` argument which is a shorthand for ``--stepwise-skip``.
|
||||
|
||||
|
||||
- `#8023 <https://github.com/pytest-dev/pytest/issues/8023>`_: Added ``'node_modules'`` to default value for :confval:`norecursedirs`.
|
||||
|
||||
|
||||
- `#8032 <https://github.com/pytest-dev/pytest/issues/8032>`_: :meth:`doClassCleanups <unittest.TestCase.doClassCleanups>` (introduced in :mod:`unittest` in Python and 3.8) is now called appropriately.
|
||||
|
||||
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- `#4824 <https://github.com/pytest-dev/pytest/issues/4824>`_: Fixed quadratic behavior and improved performance of collection of items using autouse fixtures and xunit fixtures.
|
||||
|
||||
|
||||
- `#7758 <https://github.com/pytest-dev/pytest/issues/7758>`_: Fixed an issue where some files in packages are getting lost from ``--lf`` even though they contain tests that failed. Regressed in pytest 5.4.0.
|
||||
|
||||
|
||||
- `#7911 <https://github.com/pytest-dev/pytest/issues/7911>`_: Directories created by by :fixture:`tmp_path` and :fixture:`tmpdir` are now considered stale after 3 days without modification (previous value was 3 hours) to avoid deleting directories still in use in long running test suites.
|
||||
|
||||
|
||||
- `#7913 <https://github.com/pytest-dev/pytest/issues/7913>`_: Fixed a crash or hang in :meth:`pytester.spawn <_pytest.pytester.Pytester.spawn>` when the :mod:`readline` module is involved.
|
||||
|
||||
|
||||
- `#7951 <https://github.com/pytest-dev/pytest/issues/7951>`_: Fixed handling of recursive symlinks when collecting tests.
|
||||
|
||||
|
||||
- `#7981 <https://github.com/pytest-dev/pytest/issues/7981>`_: Fixed symlinked directories not being followed during collection. Regressed in pytest 6.1.0.
|
||||
|
||||
|
||||
- `#8016 <https://github.com/pytest-dev/pytest/issues/8016>`_: Fixed only one doctest being collected when using ``pytest --doctest-modules path/to/an/__init__.py``.
|
||||
|
||||
|
||||
|
||||
Improved Documentation
|
||||
----------------------
|
||||
|
||||
- `#7429 <https://github.com/pytest-dev/pytest/issues/7429>`_: Add more information and use cases about skipping doctests.
|
||||
|
||||
|
||||
- `#7780 <https://github.com/pytest-dev/pytest/issues/7780>`_: Classes which should not be inherited from are now marked ``final class`` in the API reference.
|
||||
|
||||
|
||||
- `#7872 <https://github.com/pytest-dev/pytest/issues/7872>`_: ``_pytest.config.argparsing.Parser.addini()`` accepts explicit ``None`` and ``"string"``.
|
||||
|
||||
|
||||
- `#7878 <https://github.com/pytest-dev/pytest/issues/7878>`_: In pull request section, ask to commit after editing changelog and authors file.
|
||||
|
||||
|
||||
|
||||
Trivial/Internal Changes
|
||||
------------------------
|
||||
|
||||
- `#7802 <https://github.com/pytest-dev/pytest/issues/7802>`_: The ``attrs`` dependency requirement is now >=19.2.0 instead of >=17.4.0.
|
||||
|
||||
|
||||
- `#8014 <https://github.com/pytest-dev/pytest/issues/8014>`_: `.pyc` files created by pytest's assertion rewriting now conform to the newer PEP-552 format on Python>=3.7.
|
||||
(These files are internal and only interpreted by pytest itself.)
|
||||
|
||||
|
||||
pytest 6.1.2 (2020-10-28)
|
||||
=========================
|
||||
|
||||
|
@ -797,7 +1028,7 @@ Bug Fixes
|
|||
- `#7110 <https://github.com/pytest-dev/pytest/issues/7110>`_: Fixed regression: ``asyncbase.TestCase`` tests are executed correctly again.
|
||||
|
||||
|
||||
- `#7143 <https://github.com/pytest-dev/pytest/issues/7143>`_: Fix ``File.from_constructor`` so it forwards extra keyword arguments to the constructor.
|
||||
- `#7143 <https://github.com/pytest-dev/pytest/issues/7143>`_: Fix ``File.from_parent`` so it forwards extra keyword arguments to the constructor.
|
||||
|
||||
|
||||
- `#7145 <https://github.com/pytest-dev/pytest/issues/7145>`_: Classes with broken ``__getattribute__`` methods are displayed correctly during failures.
|
||||
|
|
|
@ -35,6 +35,7 @@ release = ".".join(version.split(".")[:2])
|
|||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
autodoc_member_order = "bysource"
|
||||
autodoc_typehints = "description"
|
||||
todo_include_todos = 1
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
@ -159,7 +160,7 @@ html_short_title = "pytest-%s" % release
|
|||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
html_logo = "img/pytest1.png"
|
||||
html_logo = "img/pytest_logo_curves.svg"
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
|
|
|
@ -7,37 +7,81 @@ Full pytest documentation
|
|||
|
||||
.. `Download latest version as EPUB <http://media.readthedocs.org/epub/pytest/latest/pytest.epub>`_
|
||||
|
||||
|
||||
Start here
|
||||
-----------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
getting-started
|
||||
usage
|
||||
existingtestsuite
|
||||
assert
|
||||
fixture
|
||||
mark
|
||||
monkeypatch
|
||||
tmpdir
|
||||
capture
|
||||
warnings
|
||||
doctest
|
||||
skipping
|
||||
parametrize
|
||||
cache
|
||||
unittest
|
||||
nose
|
||||
xunit_setup
|
||||
plugins
|
||||
writing_plugins
|
||||
logging
|
||||
reference
|
||||
|
||||
goodpractices
|
||||
flaky
|
||||
pythonpath
|
||||
customize
|
||||
|
||||
How-to guides
|
||||
-------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
how-to/usage
|
||||
how-to/assert
|
||||
how-to/fixtures
|
||||
how-to/mark
|
||||
how-to/parametrize
|
||||
how-to/tmpdir
|
||||
how-to/monkeypatch
|
||||
how-to/doctest
|
||||
how-to/cache
|
||||
|
||||
how-to/logging
|
||||
how-to/capture-stdout-stderr
|
||||
how-to/capture-warnings
|
||||
how-to/skipping
|
||||
|
||||
how-to/plugins
|
||||
how-to/writing_plugins
|
||||
how-to/writing_hook_functions
|
||||
|
||||
how-to/existingtestsuite
|
||||
how-to/unittest
|
||||
how-to/nose
|
||||
how-to/xunit_setup
|
||||
|
||||
how-to/bash-completion
|
||||
|
||||
|
||||
Reference guides
|
||||
-----------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
reference/fixtures
|
||||
reference/plugin_list
|
||||
reference/customize
|
||||
reference/reference
|
||||
|
||||
|
||||
Explanation
|
||||
-----------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
explanation/anatomy
|
||||
explanation/fixtures
|
||||
explanation/goodpractices
|
||||
explanation/flaky
|
||||
explanation/pythonpath
|
||||
|
||||
|
||||
Further topics
|
||||
-----------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
example/index
|
||||
bash-completion
|
||||
|
||||
backwards-compatibility
|
||||
deprecations
|
||||
|
|
|
@ -18,6 +18,43 @@ Deprecated Features
|
|||
Below is a complete list of all pytest features which are considered deprecated. Using those features will issue
|
||||
:class:`PytestWarning` or subclasses, which can be filtered using :ref:`standard warning filters <warnings>`.
|
||||
|
||||
|
||||
``Node.fspath`` in favor of ``pathlib`` and ``Node.path``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. deprecated:: 6.3
|
||||
|
||||
As pytest tries to move off `py.path.local <https://py.readthedocs.io/en/latest/path.html>`__ we ported most of the node internals to :mod:`pathlib`.
|
||||
|
||||
Pytest will provide compatibility for quite a while.
|
||||
|
||||
|
||||
Backward compatibilities in ``Parser.addoption``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. deprecated:: 2.4
|
||||
|
||||
Several behaviors of :meth:`Parser.addoption <_pytest.config.argparsing.Parser.addoption>` are now
|
||||
scheduled for removal in pytest 7 (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.
|
||||
|
||||
|
||||
Raising ``unittest.SkipTest`` during collection
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. deprecated:: 6.3
|
||||
|
||||
Raising :class:`unittest.SkipTest` to skip collection of tests during the
|
||||
pytest collection phase is deprecated. Use :func:`pytest.skip` instead.
|
||||
|
||||
Note: This deprecation only relates to using `unittest.SkipTest` during test
|
||||
collection. You are probably not doing that. Ordinary usage of
|
||||
:class:`unittest.SkipTest` / :meth:`unittest.TestCase.skipTest` /
|
||||
:func:`unittest.skip` in unittest test cases is fully supported.
|
||||
|
||||
|
||||
The ``--strict`` command-line option
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -397,8 +434,8 @@ Metafunc.addcall
|
|||
|
||||
.. versionremoved:: 4.0
|
||||
|
||||
``_pytest.python.Metafunc.addcall`` was a precursor to the current parametrized mechanism. Users should use
|
||||
:meth:`_pytest.python.Metafunc.parametrize` instead.
|
||||
``Metafunc.addcall`` was a precursor to the current parametrized mechanism. Users should use
|
||||
:meth:`pytest.Metafunc.parametrize` instead.
|
||||
|
||||
Example:
|
||||
|
||||
|
|
|
@ -4,4 +4,4 @@ Development Guide
|
|||
|
||||
The contributing guidelines are to be found :ref:`here <contributing>`.
|
||||
The release procedure for pytest is documented on
|
||||
`GitHub <https://github.com/pytest-dev/pytest/blob/master/RELEASING.rst>`_.
|
||||
`GitHub <https://github.com/pytest-dev/pytest/blob/main/RELEASING.rst>`_.
|
||||
|
|
|
@ -5,9 +5,9 @@ failure_demo = os.path.join(os.path.dirname(__file__), "failure_demo.py")
|
|||
pytest_plugins = ("pytester",)
|
||||
|
||||
|
||||
def test_failure_demo_fails_properly(testdir):
|
||||
target = testdir.tmpdir.join(os.path.basename(failure_demo))
|
||||
def test_failure_demo_fails_properly(pytester):
|
||||
target = pytester.path.joinpath(os.path.basename(failure_demo))
|
||||
shutil.copy(failure_demo, target)
|
||||
result = testdir.runpytest(target, syspathinsert=True)
|
||||
result = pytester.runpytest(target, syspathinsert=True)
|
||||
result.stdout.fnmatch_lines(["*44 failed*"])
|
||||
assert result.ret != 0
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="572" height="542">
|
||||
<style>
|
||||
text {
|
||||
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||
dominant-baseline: middle;
|
||||
text-anchor: middle;
|
||||
fill: #062886;
|
||||
font-size: medium;
|
||||
}
|
||||
ellipse.fixture, rect.test {
|
||||
fill: #eeffcc;
|
||||
stroke: #007020;
|
||||
stroke-width: 2;
|
||||
}
|
||||
text.fixture {
|
||||
color: #06287e;
|
||||
}
|
||||
circle.class, circle.module, circle.package {
|
||||
fill: #c3e0ec;
|
||||
stroke: #0e84b5;
|
||||
stroke-width: 2;
|
||||
}
|
||||
text.class, text.module, text.package {
|
||||
fill: #0e84b5;
|
||||
}
|
||||
line, path {
|
||||
stroke: black;
|
||||
stroke-width: 2;
|
||||
fill: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- main scope -->
|
||||
<circle class="package" r="270" cx="286" cy="271" />
|
||||
<!-- scope name -->
|
||||
<defs>
|
||||
<path d="M 26,271 A 260 260 0 0 1 546 271" id="testp"/>
|
||||
</defs>
|
||||
<text class="package">
|
||||
<textPath href="#testp" startOffset="50%">tests</textPath>
|
||||
</text>
|
||||
|
||||
<!-- subpackage -->
|
||||
<circle class="package" r="140" cx="186" cy="271" />
|
||||
<!-- scope name -->
|
||||
<defs>
|
||||
<path d="M 56,271 A 130 130 0 0 1 316 271" id="subpackage"/>
|
||||
</defs>
|
||||
<text class="package">
|
||||
<textPath href="#subpackage" startOffset="50%">subpackage</textPath>
|
||||
</text>
|
||||
|
||||
<!-- test_subpackage.py -->
|
||||
<circle class="module" r="90" cx="186" cy="311" />
|
||||
<!-- scope name -->
|
||||
<defs>
|
||||
<path d="M 106,311 A 80 80 0 0 1 266 311" id="testSubpackage"/>
|
||||
</defs>
|
||||
<text class="module">
|
||||
<textPath href="#testSubpackage" startOffset="50%">test_subpackage.py</textPath>
|
||||
</text>
|
||||
<!-- innermost -->
|
||||
<line x1="186" x2="186" y1="271" y2="351"/>
|
||||
<!-- mid -->
|
||||
<path d="M 186 351 L 136 351 L 106 331 L 106 196" />
|
||||
<!-- order -->
|
||||
<path d="M 186 351 L 256 351 L 316 291 L 316 136" />
|
||||
<!-- top -->
|
||||
<path d="M 186 351 L 186 391 L 231 436 L 331 436" />
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="186" cy="271" />
|
||||
<text x="186" y="271">innermost</text>
|
||||
<rect class="test" width="110" height="50" x="131" y="326" />
|
||||
<text x="186" y="351">test_order</text>
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="126" cy="196" />
|
||||
<text x="126" y="196">mid</text>
|
||||
<!-- scope order number -->
|
||||
<mask id="testSubpackageOrderMask">
|
||||
<rect x="0" y="0" width="100%" height="100%" fill="white"/>
|
||||
<circle fill="black" stroke="white" stroke-width="2" r="90" cx="186" cy="311" />
|
||||
</mask>
|
||||
<circle class="module" r="15" cx="96" cy="311" mask="url(#testSubpackageOrderMask)"/>
|
||||
<text class="module" x="96" y="311">1</text>
|
||||
<!-- scope order number -->
|
||||
<mask id="subpackageOrderMask">
|
||||
<rect x="0" y="0" width="100%" height="100%" fill="white"/>
|
||||
<circle fill="black" stroke="white" stroke-width="2" r="140" cx="186" cy="271" />
|
||||
</mask>
|
||||
<circle class="module" r="15" cx="46" cy="271" mask="url(#subpackageOrderMask)"/>
|
||||
<text class="module" x="46" y="271">2</text>
|
||||
<!-- scope order number -->
|
||||
<mask id="testsOrderMask">
|
||||
<rect x="0" y="0" width="100%" height="100%" fill="white"/>
|
||||
<circle fill="black" stroke="white" stroke-width="2" r="270" cx="286" cy="271" />
|
||||
</mask>
|
||||
<circle class="module" r="15" cx="16" cy="271" mask="url(#testsOrderMask)"/>
|
||||
<text class="module" x="16" y="271">3</text>
|
||||
|
||||
<!-- test_top.py -->
|
||||
<circle class="module" r="85" cx="441" cy="271" />
|
||||
<!-- scope name -->
|
||||
<defs>
|
||||
<path d="M 366,271 A 75 75 0 0 1 516 271" id="testTop"/>
|
||||
</defs>
|
||||
<text class="module">
|
||||
<textPath href="#testTop" startOffset="50%">test_top.py</textPath>
|
||||
</text>
|
||||
<!-- innermost -->
|
||||
<line x1="441" x2="441" y1="306" y2="236"/>
|
||||
<!-- order -->
|
||||
<path d="M 441 306 L 376 306 L 346 276 L 346 136" />
|
||||
<!-- top -->
|
||||
<path d="M 441 306 L 441 411 L 411 436 L 331 436" />
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="441" cy="236" />
|
||||
<text x="441" y="236">innermost</text>
|
||||
<rect class="test" width="110" height="50" x="386" y="281" />
|
||||
<text x="441" y="306">test_order</text>
|
||||
<!-- scope order number -->
|
||||
<mask id="testTopOrderMask">
|
||||
<rect x="0" y="0" width="100%" height="100%" fill="white"/>
|
||||
<circle fill="black" stroke="white" stroke-width="2" r="85" cx="441" cy="271" />
|
||||
</mask>
|
||||
<circle class="module" r="15" cx="526" cy="271" mask="url(#testTopOrderMask)"/>
|
||||
<text class="module" x="526" y="271">1</text>
|
||||
<!-- scope order number -->
|
||||
<circle class="module" r="15" cx="556" cy="271" mask="url(#testsOrderMask)"/>
|
||||
<text class="module" x="556" y="271">2</text>
|
||||
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="331" cy="436" />
|
||||
<text x="331" y="436">top</text>
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="331" cy="136" />
|
||||
<text x="331" y="136">order</text>
|
||||
</svg>
|
After Width: | Height: | Size: 4.9 KiB |
|
@ -0,0 +1,142 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="587" height="382">
|
||||
<style>
|
||||
text {
|
||||
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||
dominant-baseline: middle;
|
||||
text-anchor: middle;
|
||||
fill: #062886;
|
||||
font-size: medium;
|
||||
alignment-baseline: center;
|
||||
}
|
||||
ellipse.fixture, rect.test {
|
||||
fill: #eeffcc;
|
||||
stroke: #007020;
|
||||
stroke-width: 2;
|
||||
}
|
||||
text.fixture {
|
||||
color: #06287e;
|
||||
}
|
||||
circle.class, circle.module, circle.package, circle.plugin {
|
||||
fill: #c3e0ec;
|
||||
stroke: #0e84b5;
|
||||
stroke-width: 2;
|
||||
}
|
||||
text.class, text.module, text.package, text.plugin {
|
||||
fill: #0e84b5;
|
||||
}
|
||||
line, path {
|
||||
stroke: black;
|
||||
stroke-width: 2;
|
||||
fill: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- plugin_a.py scope -->
|
||||
<circle class="plugin" r="85" cx="486" cy="86" />
|
||||
<!-- plugin name -->
|
||||
<defs>
|
||||
<path d="M 411,86 A 75 75 0 0 1 561 86" id="pluginA"/>
|
||||
</defs>
|
||||
<text class="plugin">
|
||||
<textPath href="#pluginA" startOffset="50%">plugin_a</textPath>
|
||||
</text>
|
||||
<!-- scope order number -->
|
||||
<mask id="pluginAOrderMask">
|
||||
<rect x="0" y="0" width="100%" height="100%" fill="white"/>
|
||||
<circle fill="black" stroke="white" stroke-width="2" r="85" cx="486" cy="86" />
|
||||
</mask>
|
||||
<circle class="module" r="15" cx="571" cy="86" mask="url(#pluginAOrderMask)"/>
|
||||
<text class="module" x="571" y="86">4</text>
|
||||
|
||||
<!-- plugin_b.py scope -->
|
||||
<circle class="plugin" r="85" cx="486" cy="296" />
|
||||
<!-- plugin name -->
|
||||
<defs>
|
||||
<path d="M 411,296 A 75 75 0 0 1 561 296" id="pluginB"/>
|
||||
</defs>
|
||||
<text class="plugin">
|
||||
<textPath href="#pluginB" startOffset="50%">plugin_b</textPath>
|
||||
</text>
|
||||
<!-- scope order number -->
|
||||
<mask id="pluginBOrderMask">
|
||||
<rect x="0" y="0" width="100%" height="100%" fill="white"/>
|
||||
<circle fill="black" stroke="white" stroke-width="2" r="85" cx="486" cy="296" />
|
||||
</mask>
|
||||
<circle class="module" r="15" cx="571" cy="296" mask="url(#pluginBOrderMask)"/>
|
||||
<text class="module" x="571" y="296">4</text>
|
||||
|
||||
<!-- main scope -->
|
||||
<circle class="package" r="190" cx="191" cy="191" />
|
||||
<!-- scope name -->
|
||||
<defs>
|
||||
<path d="M 11,191 A 180 180 0 0 1 371 191" id="testp"/>
|
||||
</defs>
|
||||
<text class="package">
|
||||
<textPath href="#testp" startOffset="50%">tests</textPath>
|
||||
</text>
|
||||
<!-- scope order number -->
|
||||
<mask id="mainOrderMask">
|
||||
<rect x="0" y="0" width="100%" height="100%" fill="white"/>
|
||||
<circle fill="black" stroke="white" stroke-width="2" r="190" cx="191" cy="191" />
|
||||
</mask>
|
||||
<circle class="module" r="15" cx="381" cy="191" mask="url(#mainOrderMask)"/>
|
||||
<text class="module" x="381" y="191">3</text>
|
||||
|
||||
<!-- subpackage -->
|
||||
<circle class="package" r="140" cx="191" cy="231" />
|
||||
<!-- scope name -->
|
||||
<defs>
|
||||
<path d="M 61,231 A 130 130 0 0 1 321 231" id="subpackage"/>
|
||||
</defs>
|
||||
<text class="package">
|
||||
<textPath href="#subpackage" startOffset="50%">subpackage</textPath>
|
||||
</text>
|
||||
<!-- scope order number -->
|
||||
<mask id="subpackageOrderMask">
|
||||
<rect x="0" y="0" width="100%" height="100%" fill="white"/>
|
||||
<circle fill="black" stroke="white" stroke-width="2" r="140" cx="191" cy="231" />
|
||||
</mask>
|
||||
<circle class="module" r="15" cx="331" cy="231" mask="url(#subpackageOrderMask)"/>
|
||||
<text class="module" x="331" y="231">2</text>
|
||||
|
||||
<!-- test_subpackage.py -->
|
||||
<circle class="module" r="90" cx="191" cy="271" />
|
||||
<!-- scope name -->
|
||||
<defs>
|
||||
<path d="M 111,271 A 80 80 0 0 1 271 271" id="testSubpackage"/>
|
||||
</defs>
|
||||
<text class="module">
|
||||
<textPath href="#testSubpackage" startOffset="50%">test_subpackage.py</textPath>
|
||||
</text>
|
||||
<!-- scope order number -->
|
||||
<mask id="testSubpackageOrderMask">
|
||||
<rect x="0" y="0" width="100%" height="100%" fill="white"/>
|
||||
<circle fill="black" stroke="white" stroke-width="2" r="90" cx="191" cy="271" />
|
||||
</mask>
|
||||
<circle class="module" r="15" cx="281" cy="271" mask="url(#testSubpackageOrderMask)"/>
|
||||
<text class="module" x="281" y="271">1</text>
|
||||
|
||||
<!-- innermost -->
|
||||
<line x1="191" x2="191" y1="231" y2="311"/>
|
||||
<!-- mid -->
|
||||
<path d="M 191 306 L 101 306 L 91 296 L 91 156 L 101 146 L 191 146" />
|
||||
<!-- order -->
|
||||
<path d="M 191 316 L 91 316 L 81 306 L 81 61 L 91 51 L 191 51" />
|
||||
<!-- a_fix -->
|
||||
<path d="M 191 306 L 291 306 L 301 296 L 301 96 L 311 86 L 486 86" />
|
||||
<!-- b_fix -->
|
||||
<path d="M 191 316 L 316 316 L 336 296 L 486 296" />
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="191" cy="231" />
|
||||
<text x="191" y="231">inner</text>
|
||||
<rect class="test" width="110" height="50" x="136" y="286" />
|
||||
<text x="191" y="311">test_order</text>
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="191" cy="146" />
|
||||
<text x="191" y="146">mid</text>
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="191" cy="51" />
|
||||
<text x="191" y="51">order</text>
|
||||
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="486" cy="86" />
|
||||
<text x="486" y="86">a_fix</text>
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="486" cy="296" />
|
||||
<text x="486" y="296">b_fix</text>
|
||||
</svg>
|
After Width: | Height: | Size: 5.3 KiB |
|
@ -1,38 +0,0 @@
|
|||
import pytest
|
||||
|
||||
# fixtures documentation order example
|
||||
order = []
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def s1():
|
||||
order.append("s1")
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def m1():
|
||||
order.append("m1")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def f1(f3):
|
||||
order.append("f1")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def f3():
|
||||
order.append("f3")
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def a1():
|
||||
order.append("a1")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def f2():
|
||||
order.append("f2")
|
||||
|
||||
|
||||
def test_order(f1, m1, f2, s1):
|
||||
assert order == ["s1", "m1", "a1", "f3", "f1", "f2"]
|
|
@ -0,0 +1,45 @@
|
|||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def order():
|
||||
return []
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def a(order):
|
||||
order.append("a")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def b(a, order):
|
||||
order.append("b")
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def c(b, order):
|
||||
order.append("c")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def d(b, order):
|
||||
order.append("d")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def e(d, order):
|
||||
order.append("e")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def f(e, order):
|
||||
order.append("f")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def g(f, c, order):
|
||||
order.append("g")
|
||||
|
||||
|
||||
def test_order_and_g(g, order):
|
||||
assert order == ["a", "b", "c", "d", "e", "f", "g"]
|
|
@ -0,0 +1,64 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="252" height="682">
|
||||
<style>
|
||||
text {
|
||||
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||
dominant-baseline: middle;
|
||||
text-anchor: middle;
|
||||
fill: #062886;
|
||||
font-size: medium;
|
||||
}
|
||||
ellipse.fixture, rect.test {
|
||||
fill: #eeffcc;
|
||||
stroke: #007020;
|
||||
stroke-width: 2;
|
||||
}
|
||||
text.fixture {
|
||||
color: #06287e;
|
||||
}
|
||||
circle.class {
|
||||
fill: #c3e0ec;
|
||||
stroke: #0e84b5;
|
||||
stroke-width: 2;
|
||||
}
|
||||
text.class {
|
||||
fill: #0e84b5;
|
||||
}
|
||||
path, line {
|
||||
stroke: black;
|
||||
stroke-width: 2;
|
||||
fill: none;
|
||||
}
|
||||
rect.autouse {
|
||||
fill: #ca7f3d;
|
||||
}
|
||||
</style>
|
||||
<path d="M126,586 L26,506 L26,236" />
|
||||
<path d="M226,446 L226,236 L126,166" />
|
||||
<line x1="126" x2="126" y1="656" y2="516" />
|
||||
<line x1="126" x2="226" y1="516" y2="446" />
|
||||
<line x1="226" x2="126" y1="446" y2="376" />
|
||||
<line x1="126" x2="126" y1="376" y2="166" />
|
||||
<line x1="26" x2="126" y1="236" y2="166" />
|
||||
<line x1="126" x2="126" y1="166" y2="26" />
|
||||
<line x1="126" x2="126" y1="96" y2="26" />
|
||||
<rect class="autouse" width="251" height="40" x="0" y="286" />
|
||||
<text x="126" y="306">autouse</text>
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="126" cy="26" />
|
||||
<text x="126" y="26">order</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="126" cy="96" />
|
||||
<text x="126" y="96">a</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="126" cy="166" />
|
||||
<text x="126" y="166">b</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="26" cy="236" />
|
||||
<text x="26" y="236">c</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="126" cy="376" />
|
||||
<text x="126" y="376">d</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="226" cy="446" />
|
||||
<text x="226" y="446">e</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="126" cy="516" />
|
||||
<text x="126" y="516">f</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="126" cy="586" />
|
||||
<text x="126" y="586">g</text>
|
||||
<rect class="test" width="110" height="50" x="71" y="631" />
|
||||
<text x="126" y="656">test_order</text>
|
||||
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
|
@ -0,0 +1,31 @@
|
|||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def order():
|
||||
return []
|
||||
|
||||
|
||||
@pytest.fixture(scope="class", autouse=True)
|
||||
def c1(order):
|
||||
order.append("c1")
|
||||
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def c2(order):
|
||||
order.append("c2")
|
||||
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def c3(order, c1):
|
||||
order.append("c3")
|
||||
|
||||
|
||||
class TestClassWithC1Request:
|
||||
def test_order(self, order, c1, c3):
|
||||
assert order == ["c1", "c3"]
|
||||
|
||||
|
||||
class TestClassWithoutC1Request:
|
||||
def test_order(self, order, c2):
|
||||
assert order == ["c1", "c2"]
|
|
@ -0,0 +1,76 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="862" height="402">
|
||||
<style>
|
||||
text {
|
||||
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||
dominant-baseline: middle;
|
||||
text-anchor: middle;
|
||||
fill: #062886;
|
||||
font-size: medium;
|
||||
}
|
||||
ellipse.fixture, rect.test {
|
||||
fill: #eeffcc;
|
||||
stroke: #007020;
|
||||
stroke-width: 2;
|
||||
}
|
||||
text.fixture {
|
||||
color: #06287e;
|
||||
}
|
||||
circle.class {
|
||||
fill: #c3e0ec;
|
||||
stroke: #0e84b5;
|
||||
stroke-width: 2;
|
||||
}
|
||||
text.class {
|
||||
fill: #0e84b5;
|
||||
}
|
||||
line {
|
||||
stroke: black;
|
||||
stroke-width: 2;
|
||||
}
|
||||
rect.autouse {
|
||||
fill: #ca7f3d;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- TestWithC1Request -->
|
||||
<circle class="class" r="200" cx="221" cy="201" />
|
||||
<line x1="221" x2="221" y1="61" y2="316"/>
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="221" cy="61" />
|
||||
<text x="221" y="61">order</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="221" cy="131" />
|
||||
<text x="221" y="131">c1</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="221" cy="271" />
|
||||
<text x="221" y="271">c3</text>
|
||||
<rect class="test" width="110" height="50" x="166" y="316" />
|
||||
<text x="221" y="341">test_order</text>
|
||||
<!-- scope name -->
|
||||
<defs>
|
||||
<path d="M31,201 A 190 190 0 0 1 411 201" id="testClassWith"/>
|
||||
</defs>
|
||||
<text class="class">
|
||||
<textPath href="#testClassWith" startOffset="50%">TestWithC1Request</textPath>
|
||||
</text>
|
||||
|
||||
<!-- TestWithoutC1Request -->
|
||||
<circle class="class" r="200" cx="641" cy="201" />
|
||||
<line x1="641" x2="641" y1="61" y2="316"/>
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="641" cy="61" />
|
||||
<text x="641" y="61">order</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="641" cy="131" />
|
||||
<text x="641" y="131">c1</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="641" cy="271" />
|
||||
<text x="641" y="271">c2</text>
|
||||
<rect class="test" width="110" height="50" x="586" y="316" />
|
||||
<text x="641" y="341">test_order</text>
|
||||
<!-- scope name -->
|
||||
<defs>
|
||||
<path d="M451,201 A 190 190 0 0 1 831 201" id="testClassWithout"/>
|
||||
</defs>
|
||||
<text class="class">
|
||||
<textPath href="#testClassWithout" startOffset="50%">TestWithoutC1Request</textPath>
|
||||
</text>
|
||||
|
||||
<rect class="autouse" width="862" height="40" x="1" y="181" />
|
||||
<rect width="10" height="100" class="autouse" x="426" y="151" />
|
||||
<text x="431" y="201">autouse</text>
|
||||
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
|
@ -0,0 +1,36 @@
|
|||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def order():
|
||||
return []
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def c1(order):
|
||||
order.append("c1")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def c2(order):
|
||||
order.append("c2")
|
||||
|
||||
|
||||
class TestClassWithAutouse:
|
||||
@pytest.fixture(autouse=True)
|
||||
def c3(self, order, c2):
|
||||
order.append("c3")
|
||||
|
||||
def test_req(self, order, c1):
|
||||
assert order == ["c2", "c3", "c1"]
|
||||
|
||||
def test_no_req(self, order):
|
||||
assert order == ["c2", "c3"]
|
||||
|
||||
|
||||
class TestClassWithoutAutouse:
|
||||
def test_req(self, order, c1):
|
||||
assert order == ["c1"]
|
||||
|
||||
def test_no_req(self, order):
|
||||
assert order == []
|
|
@ -0,0 +1,100 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="862" height="502">
|
||||
<style>
|
||||
text {
|
||||
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||
dominant-baseline: middle;
|
||||
text-anchor: middle;
|
||||
fill: #062886;
|
||||
font-size: medium;
|
||||
}
|
||||
ellipse.fixture, rect.test {
|
||||
fill: #eeffcc;
|
||||
stroke: #007020;
|
||||
stroke-width: 2;
|
||||
}
|
||||
text.fixture {
|
||||
color: #06287e;
|
||||
}
|
||||
circle.class {
|
||||
fill: #c3e0ec;
|
||||
stroke: #0e84b5;
|
||||
stroke-width: 2;
|
||||
}
|
||||
text.class {
|
||||
fill: #0e84b5;
|
||||
}
|
||||
line {
|
||||
stroke: black;
|
||||
stroke-width: 2;
|
||||
}
|
||||
rect.autouse {
|
||||
fill: #ca7f3d;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- TestWithAutouse -->
|
||||
<circle class="class" r="250" cx="251" cy="251" />
|
||||
<!-- scope name -->
|
||||
<defs>
|
||||
<path d="M11,251 A 240 240 0 0 1 491 251" id="testClassWith"/>
|
||||
</defs>
|
||||
<text class="class">
|
||||
<textPath href="#testClassWith" startOffset="50%">TestWithAutouse</textPath>
|
||||
</text>
|
||||
<mask id="autouseScope">
|
||||
<circle fill="white" r="249" cx="251" cy="251" />
|
||||
</mask>
|
||||
|
||||
<!-- TestWithAutouse.test_req -->
|
||||
<line x1="176" x2="176" y1="76" y2="426"/>
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="176" cy="76" />
|
||||
<text x="176" y="76">order</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="176" cy="146" />
|
||||
<text x="176" y="146">c2</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="176" cy="216" />
|
||||
<text x="176" y="216">c3</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="176" cy="356" />
|
||||
<text x="176" y="356">c1</text>
|
||||
<rect class="test" width="100" height="50" x="126" y="401" />
|
||||
<text x="176" y="426">test_req</text>
|
||||
|
||||
<!-- TestWithAutouse.test_no_req -->
|
||||
<line x1="326" x2="326" y1="76" y2="346"/>
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="326" cy="76" />
|
||||
<text x="326" y="76">order</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="326" cy="146" />
|
||||
<text x="326" y="146">c2</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="326" cy="216" />
|
||||
<text x="326" y="216">c3</text>
|
||||
<rect class="test" width="120" height="50" x="266" y="331" />
|
||||
<text x="326" y="356">test_no_req</text>
|
||||
|
||||
<rect class="autouse" width="500" height="40" x="1" y="266" mask="url(#autouseScope)"/>
|
||||
<text x="261" y="286">autouse</text>
|
||||
|
||||
<!-- TestWithoutAutouse -->
|
||||
<circle class="class" r="170" cx="691" cy="251" />
|
||||
<!-- scope name -->
|
||||
<defs>
|
||||
<path d="M 531,251 A 160 160 0 0 1 851 251" id="testClassWithout"/>
|
||||
</defs>
|
||||
<text class="class">
|
||||
<textPath href="#testClassWithout" startOffset="50%">TestWithoutAutouse</textPath>
|
||||
</text>
|
||||
|
||||
<!-- TestWithoutAutouse.test_req -->
|
||||
<line x1="616" x2="616" y1="181" y2="321"/>
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="616" cy="181" />
|
||||
<text x="616" y="181">order</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="616" cy="251" />
|
||||
<text x="616" y="251">c1</text>
|
||||
<rect class="test" width="100" height="50" x="566" y="296" />
|
||||
<text x="616" y="321">test_req</text>
|
||||
|
||||
<!-- TestWithoutAutouse.test_no_req -->
|
||||
<line x1="766" x2="766" y1="181" y2="251"/>
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="766" cy="181" />
|
||||
<text x="766" y="181">order</text>
|
||||
<rect class="test" width="120" height="50" x="706" y="226" />
|
||||
<text x="766" y="251">test_no_req</text>
|
||||
</svg>
|
After Width: | Height: | Size: 3.5 KiB |
|
@ -0,0 +1,45 @@
|
|||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def order():
|
||||
return []
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def a(order):
|
||||
order.append("a")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def b(a, order):
|
||||
order.append("b")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def c(a, b, order):
|
||||
order.append("c")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def d(c, b, order):
|
||||
order.append("d")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def e(d, b, order):
|
||||
order.append("e")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def f(e, order):
|
||||
order.append("f")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def g(f, c, order):
|
||||
order.append("g")
|
||||
|
||||
|
||||
def test_order(g, order):
|
||||
assert order == ["a", "b", "c", "d", "e", "f", "g"]
|
|
@ -0,0 +1,60 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="252" height="612">
|
||||
<style>
|
||||
text {
|
||||
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||
dominant-baseline: middle;
|
||||
text-anchor: middle;
|
||||
fill: #062886;
|
||||
font-size: medium;
|
||||
}
|
||||
ellipse.fixture, rect.test {
|
||||
fill: #eeffcc;
|
||||
stroke: #007020;
|
||||
stroke-width: 2;
|
||||
}
|
||||
text.fixture {
|
||||
color: #06287e;
|
||||
}
|
||||
circle.class {
|
||||
fill: #c3e0ec;
|
||||
stroke: #0e84b5;
|
||||
stroke-width: 2;
|
||||
}
|
||||
text.class {
|
||||
fill: #0e84b5;
|
||||
}
|
||||
path, line {
|
||||
stroke: black;
|
||||
stroke-width: 2;
|
||||
fill: none;
|
||||
}
|
||||
</style>
|
||||
<path d="M126,516 L26,436 L26,236" />
|
||||
<path d="M226,376 L226,236 L126,166" />
|
||||
<line x1="126" x2="126" y1="586" y2="446" />
|
||||
<line x1="126" x2="226" y1="446" y2="376" />
|
||||
<line x1="226" x2="126" y1="376" y2="306" />
|
||||
<line x1="126" x2="26" y1="306" y2="236" />
|
||||
<line x1="126" x2="126" y1="306" y2="166" />
|
||||
<line x1="26" x2="126" y1="236" y2="166" />
|
||||
<line x1="126" x2="126" y1="166" y2="26" />
|
||||
<line x1="126" x2="126" y1="96" y2="26" />
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="126" cy="26" />
|
||||
<text x="126" y="26">order</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="126" cy="96" />
|
||||
<text x="126" y="96">a</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="126" cy="166" />
|
||||
<text x="126" y="166">b</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="26" cy="236" />
|
||||
<text x="26" y="236">c</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="126" cy="306" />
|
||||
<text x="126" y="306">d</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="226" cy="376" />
|
||||
<text x="226" y="376">e</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="126" cy="446" />
|
||||
<text x="126" y="446">f</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="126" cy="516" />
|
||||
<text x="126" y="516">g</text>
|
||||
<rect class="test" width="110" height="50" x="71" y="561" />
|
||||
<text x="126" y="586">test_order</text>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
|
@ -0,0 +1,51 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="112" height="612">
|
||||
<style>
|
||||
text {
|
||||
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||
dominant-baseline: middle;
|
||||
text-anchor: middle;
|
||||
fill: #062886;
|
||||
font-size: medium;
|
||||
}
|
||||
ellipse.fixture, rect.test {
|
||||
fill: #eeffcc;
|
||||
stroke: #007020;
|
||||
stroke-width: 2;
|
||||
}
|
||||
text.fixture {
|
||||
color: #06287e;
|
||||
}
|
||||
circle.class {
|
||||
fill: #c3e0ec;
|
||||
stroke: #0e84b5;
|
||||
stroke-width: 2;
|
||||
}
|
||||
text.class {
|
||||
fill: #0e84b5;
|
||||
}
|
||||
path, line {
|
||||
stroke: black;
|
||||
stroke-width: 2;
|
||||
fill: none;
|
||||
}
|
||||
</style>
|
||||
<line x1="56" x2="56" y1="611" y2="26" />
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="56" cy="26" />
|
||||
<text x="56" y="26">order</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="56" cy="96" />
|
||||
<text x="56" y="96">a</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="56" cy="166" />
|
||||
<text x="56" y="166">b</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="56" cy="236" />
|
||||
<text x="56" y="236">c</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="56" cy="306" />
|
||||
<text x="56" y="306">d</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="56" cy="376" />
|
||||
<text x="56" y="376">e</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="56" cy="446" />
|
||||
<text x="56" y="446">f</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="56" cy="516" />
|
||||
<text x="56" y="516">g</text>
|
||||
<rect class="test" width="110" height="50" x="1" y="561" />
|
||||
<text x="56" y="586">test_order</text>
|
||||
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
|
@ -0,0 +1,60 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="252" height="542">
|
||||
<style>
|
||||
text {
|
||||
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||
dominant-baseline: middle;
|
||||
text-anchor: middle;
|
||||
fill: #062886;
|
||||
font-size: medium;
|
||||
}
|
||||
ellipse.fixture, rect.test {
|
||||
fill: #eeffcc;
|
||||
stroke: #007020;
|
||||
stroke-width: 2;
|
||||
}
|
||||
text.fixture {
|
||||
color: #06287e;
|
||||
}
|
||||
circle.class {
|
||||
fill: #c3e0ec;
|
||||
stroke: #0e84b5;
|
||||
stroke-width: 2;
|
||||
}
|
||||
text.class {
|
||||
fill: #0e84b5;
|
||||
}
|
||||
path, line {
|
||||
stroke: black;
|
||||
stroke-width: 2;
|
||||
fill: none;
|
||||
}
|
||||
</style>
|
||||
<path d="M126,446 L26,376 L26,236" />
|
||||
<path d="M226,306 L126,236 L126,166" />
|
||||
<line x1="126" x2="126" y1="516" y2="446" />
|
||||
<line x1="226" x2="226" y1="376" y2="306" />
|
||||
<line x1="226" x2="226" y1="306" y2="236" />
|
||||
<line x1="226" x2="126" y1="236" y2="166" />
|
||||
<line x1="126" x2="226" y1="446" y2="376" />
|
||||
<line x1="26" x2="126" y1="236" y2="166" />
|
||||
<line x1="126" x2="126" y1="166" y2="96" />
|
||||
<line x1="126" x2="126" y1="96" y2="26" />
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="126" cy="26" />
|
||||
<text x="126" y="26">order</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="126" cy="96" />
|
||||
<text x="126" y="96">a</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="126" cy="166" />
|
||||
<text x="126" y="166">b</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="26" cy="236" />
|
||||
<text x="26" y="236">c</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="226" cy="236" />
|
||||
<text x="226" y="236">d</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="226" cy="306" />
|
||||
<text x="226" y="306">e</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="226" cy="376" />
|
||||
<text x="226" y="376">f</text>
|
||||
<ellipse class="fixture" rx="25" ry="25" cx="126" cy="446" />
|
||||
<text x="126" y="446">g</text>
|
||||
<rect class="test" width="110" height="50" x="71" y="491" />
|
||||
<text x="126" y="516">test_order</text>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
|
@ -0,0 +1,36 @@
|
|||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def order():
|
||||
return []
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def func(order):
|
||||
order.append("function")
|
||||
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def cls(order):
|
||||
order.append("class")
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def mod(order):
|
||||
order.append("module")
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def pack(order):
|
||||
order.append("package")
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def sess(order):
|
||||
order.append("session")
|
||||
|
||||
|
||||
class TestClass:
|
||||
def test_order(self, func, cls, mod, pack, sess, order):
|
||||
assert order == ["session", "package", "module", "class", "function"]
|
|
@ -0,0 +1,55 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="262" height="537">
|
||||
<style>
|
||||
text {
|
||||
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||
dominant-baseline: middle;
|
||||
text-anchor: middle;
|
||||
fill: #062886;
|
||||
font-size: medium;
|
||||
}
|
||||
ellipse.fixture, rect.test {
|
||||
fill: #eeffcc;
|
||||
stroke: #007020;
|
||||
stroke-width: 2;
|
||||
}
|
||||
text.fixture {
|
||||
color: #06287e;
|
||||
}
|
||||
circle.class {
|
||||
fill: #c3e0ec;
|
||||
stroke: #0e84b5;
|
||||
stroke-width: 2;
|
||||
}
|
||||
text.class {
|
||||
fill: #0e84b5;
|
||||
}
|
||||
line {
|
||||
stroke: black;
|
||||
stroke-width: 2;
|
||||
}
|
||||
</style>
|
||||
<!-- TestClass -->
|
||||
<circle class="class" r="130" cx="131" cy="406" />
|
||||
<line x1="131" x2="131" y1="21" y2="446"/>
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="131" cy="26" />
|
||||
<text x="131" y="26">order</text>
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="131" cy="96" />
|
||||
<text x="131" y="96">sess</text>
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="131" cy="166" />
|
||||
<text x="131" y="166">pack</text>
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="131" cy="236" />
|
||||
<text x="131" y="236">mod</text>
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="131" cy="306" />
|
||||
<text x="131" y="306">cls</text>
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="131" cy="376" />
|
||||
<text x="131" y="376">func</text>
|
||||
<rect class="test" width="110" height="50" x="76" y="421" />
|
||||
<text x="131" y="446">test_order</text>
|
||||
<!-- scope name -->
|
||||
<defs>
|
||||
<path d="M131,526 A 120 120 0 0 1 136 286" id="testClass"/>
|
||||
</defs>
|
||||
<text class="class">
|
||||
<textPath href="#testClass" startOffset="50%">TestClass</textPath>
|
||||
</text>
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
|
@ -0,0 +1,29 @@
|
|||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def order():
|
||||
return []
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def outer(order, inner):
|
||||
order.append("outer")
|
||||
|
||||
|
||||
class TestOne:
|
||||
@pytest.fixture
|
||||
def inner(self, order):
|
||||
order.append("one")
|
||||
|
||||
def test_order(self, order, outer):
|
||||
assert order == ["one", "outer"]
|
||||
|
||||
|
||||
class TestTwo:
|
||||
@pytest.fixture
|
||||
def inner(self, order):
|
||||
order.append("two")
|
||||
|
||||
def test_order(self, order, outer):
|
||||
assert order == ["two", "outer"]
|
|
@ -0,0 +1,115 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="562" height="532">
|
||||
<style>
|
||||
text {
|
||||
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||
dominant-baseline: middle;
|
||||
text-anchor: middle;
|
||||
fill: #062886;
|
||||
font-size: medium;
|
||||
}
|
||||
ellipse.fixture, rect.test {
|
||||
fill: #eeffcc;
|
||||
stroke: #007020;
|
||||
stroke-width: 2;
|
||||
}
|
||||
text.fixture {
|
||||
color: #06287e;
|
||||
}
|
||||
circle.class {
|
||||
fill: #c3e0ec;
|
||||
stroke: #0e84b5;
|
||||
stroke-width: 2;
|
||||
}
|
||||
circle.module {
|
||||
fill: #c3e0ec;
|
||||
stroke: #0e84b5;
|
||||
stroke-width: 2;
|
||||
}
|
||||
text.class, text.module {
|
||||
fill: #0e84b5;
|
||||
}
|
||||
line, path {
|
||||
stroke: black;
|
||||
stroke-width: 2;
|
||||
fill: none;
|
||||
}
|
||||
</style>
|
||||
<!-- main scope -->
|
||||
<circle class="module" r="265" cx="281" cy="266" />
|
||||
<!-- scope name -->
|
||||
<defs>
|
||||
<path d="M 26,266 A 255 255 0 0 1 536 266" id="testModule"/>
|
||||
</defs>
|
||||
<text class="module">
|
||||
<textPath href="#testModule" startOffset="50%">test_fixtures_request_different_scope.py</textPath>
|
||||
</text>
|
||||
|
||||
<!-- TestOne -->
|
||||
<circle class="class" r="100" cx="141" cy="266" />
|
||||
<!-- inner -->
|
||||
<line x1="141" x2="141" y1="231" y2="301"/>
|
||||
<!-- order -->
|
||||
<path d="M 141 296 L 201 296 L 211 286 L 211 146 L 221 136 L 281 136" />
|
||||
<!-- outer -->
|
||||
<path d="M 141 306 L 201 306 L 211 316 L 211 386 L 221 396 L 281 396" />
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="141" cy="231" />
|
||||
<text x="141" y="231">inner</text>
|
||||
<rect class="test" width="110" height="50" x="86" y="276" />
|
||||
<text x="141" y="301">test_order</text>
|
||||
<!-- scope name -->
|
||||
<defs>
|
||||
<path d="M 51,266 A 90 90 0 0 1 231 266" id="testOne"/>
|
||||
</defs>
|
||||
<text class="class">
|
||||
<textPath href="#testOne" startOffset="50%">TestOne</textPath>
|
||||
</text>
|
||||
<!-- scope order number -->
|
||||
<mask id="testOneOrderMask">
|
||||
<rect x="0" y="0" width="100%" height="100%" fill="white"/>
|
||||
<circle fill="black" stroke="white" stroke-width="2" r="100" cx="141" cy="266" />
|
||||
</mask>
|
||||
<circle class="module" r="15" cx="41" cy="266" mask="url(#testOneOrderMask)"/>
|
||||
<text class="module" x="41" y="266">1</text>
|
||||
<!-- scope order number -->
|
||||
<mask id="testMainOrderMask">
|
||||
<rect x="0" y="0" width="100%" height="100%" fill="white"/>
|
||||
<circle fill="black" stroke="white" stroke-width="2" r="265" cx="281" cy="266" />
|
||||
</mask>
|
||||
<circle class="module" r="15" cx="16" cy="266" mask="url(#testMainOrderMask)"/>
|
||||
<text class="module" x="16" y="266">2</text>
|
||||
|
||||
<!-- TestTwo -->
|
||||
<circle class="class" r="100" cx="421" cy="266" />
|
||||
<!-- inner -->
|
||||
<line x1="421" x2="421" y1="231" y2="301"/>
|
||||
<!-- order -->
|
||||
<path d="M 421 296 L 361 296 L 351 286 L 351 146 L 341 136 L 281 136" />
|
||||
<!-- outer -->
|
||||
<path d="M 421 306 L 361 306 L 351 316 L 351 386 L 341 396 L 281 396" />
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="421" cy="231" />
|
||||
<text x="421" y="231">inner</text>
|
||||
<rect class="test" width="110" height="50" x="366" y="276" />
|
||||
<text x="421" y="301">test_order</text>
|
||||
<!-- scope name -->
|
||||
<defs>
|
||||
<path d="M 331,266 A 90 90 0 0 1 511 266" id="testTwo"/>
|
||||
</defs>
|
||||
<text class="class">
|
||||
<textPath href="#testTwo" startOffset="50%">TestTwo</textPath>
|
||||
</text>
|
||||
<!-- scope order number -->
|
||||
<mask id="testTwoOrderMask">
|
||||
<rect x="0" y="0" width="100%" height="100%" fill="white"/>
|
||||
<circle fill="black" stroke="white" stroke-width="2" r="100" cx="421" cy="266" />
|
||||
</mask>
|
||||
<circle class="module" r="15" cx="521" cy="266" mask="url(#testTwoOrderMask)"/>
|
||||
<text class="module" x="521" y="266">1</text>
|
||||
<!-- scope order number -->
|
||||
<circle class="module" r="15" cx="546" cy="266" mask="url(#testMainOrderMask)"/>
|
||||
<text class="module" x="546" y="266">2</text>
|
||||
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="281" cy="396" />
|
||||
<text x="281" y="396">outer</text>
|
||||
<ellipse class="fixture" rx="50" ry="25" cx="281" cy="136" />
|
||||
<text x="281" y="136">order</text>
|
||||
</svg>
|
After Width: | Height: | Size: 4.2 KiB |
|
@ -13,12 +13,12 @@ answers.
|
|||
|
||||
For basic examples, see
|
||||
|
||||
- :doc:`../getting-started` for basic introductory examples
|
||||
- :ref:`get-started` for basic introductory examples
|
||||
- :ref:`assert` for basic assertion examples
|
||||
- :ref:`Fixtures <fixtures>` for basic fixture/setup examples
|
||||
- :ref:`parametrize` for basic test function parametrization
|
||||
- :doc:`../unittest` for basic unittest integration
|
||||
- :doc:`../nose` for basic nosetests integration
|
||||
- :ref:`unittest` for basic unittest integration
|
||||
- :ref:`noseintegration` for basic nosetests integration
|
||||
|
||||
The following examples aim at various use cases you might encounter.
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@ pythonlist = ["python3.5", "python3.6", "python3.7"]
|
|||
|
||||
|
||||
@pytest.fixture(params=pythonlist)
|
||||
def python1(request, tmpdir):
|
||||
picklefile = tmpdir.join("data.pickle")
|
||||
def python1(request, tmp_path):
|
||||
picklefile = tmp_path / "data.pickle"
|
||||
return Python(request.param, picklefile)
|
||||
|
||||
|
||||
|
@ -30,8 +30,8 @@ class Python:
|
|||
self.picklefile = picklefile
|
||||
|
||||
def dumps(self, obj):
|
||||
dumpfile = self.picklefile.dirpath("dump.py")
|
||||
dumpfile.write(
|
||||
dumpfile = self.picklefile.with_name("dump.py")
|
||||
dumpfile.write_text(
|
||||
textwrap.dedent(
|
||||
r"""
|
||||
import pickle
|
||||
|
@ -46,8 +46,8 @@ class Python:
|
|||
subprocess.check_call((self.pythonpath, str(dumpfile)))
|
||||
|
||||
def load_and_is_true(self, expression):
|
||||
loadfile = self.picklefile.dirpath("load.py")
|
||||
loadfile.write(
|
||||
loadfile = self.picklefile.with_name("load.py")
|
||||
loadfile.write_text(
|
||||
textwrap.dedent(
|
||||
r"""
|
||||
import pickle
|
||||
|
|
|
@ -102,4 +102,4 @@ interesting to just look at the collection tree:
|
|||
<YamlItem hello>
|
||||
<YamlItem ok>
|
||||
|
||||
========================== 2 tests found in 0.12s ===========================
|
||||
======================== 2 tests collected in 0.12s ========================
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
import pytest
|
||||
|
||||
|
||||
def pytest_collect_file(parent, path):
|
||||
if path.ext == ".yaml" and path.basename.startswith("test"):
|
||||
return YamlFile.from_parent(parent, fspath=path)
|
||||
def pytest_collect_file(parent, fspath):
|
||||
if fspath.suffix == ".yaml" and fspath.name.startswith("test"):
|
||||
return YamlFile.from_parent(parent, path=fspath)
|
||||
|
||||
|
||||
class YamlFile(pytest.File):
|
||||
|
@ -12,7 +12,7 @@ class YamlFile(pytest.File):
|
|||
# We need a yaml parser, e.g. PyYAML.
|
||||
import yaml
|
||||
|
||||
raw = yaml.safe_load(self.fspath.open())
|
||||
raw = yaml.safe_load(self.path.open())
|
||||
for name, spec in sorted(raw.items()):
|
||||
yield YamlItem.from_parent(self, name=name, spec=spec)
|
||||
|
||||
|
|
|
@ -97,10 +97,10 @@ the argument name:
|
|||
|
||||
# content of test_time.py
|
||||
|
||||
import pytest
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import pytest
|
||||
|
||||
testdata = [
|
||||
(datetime(2001, 12, 12), datetime(2001, 12, 11), timedelta(1)),
|
||||
(datetime(2001, 12, 11), datetime(2001, 12, 12), timedelta(-1)),
|
||||
|
@ -175,7 +175,7 @@ objects, they are still using the default pytest representation:
|
|||
<Function test_timedistance_v3[forward]>
|
||||
<Function test_timedistance_v3[backward]>
|
||||
|
||||
========================== 8 tests found in 0.12s ===========================
|
||||
======================== 8 tests collected in 0.12s ========================
|
||||
|
||||
In ``test_timedistance_v3``, we used ``pytest.param`` to specify the test IDs
|
||||
together with the actual data, instead of listing them separately.
|
||||
|
@ -252,7 +252,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia
|
|||
<Function test_demo1[advanced]>
|
||||
<Function test_demo2[advanced]>
|
||||
|
||||
========================== 4 tests found in 0.12s ===========================
|
||||
======================== 4 tests collected in 0.12s ========================
|
||||
|
||||
Note that we told ``metafunc.parametrize()`` that your scenario values
|
||||
should be considered class-scoped. With pytest-2.3 this leads to a
|
||||
|
@ -328,7 +328,7 @@ Let's first see how it looks like at collection time:
|
|||
<Function test_db_initialized[d1]>
|
||||
<Function test_db_initialized[d2]>
|
||||
|
||||
========================== 2/2 tests found in 0.12s ===========================
|
||||
======================== 2 tests collected in 0.12s ========================
|
||||
|
||||
And then when we run the test:
|
||||
|
||||
|
@ -637,13 +637,13 @@ Then run ``pytest`` with verbose mode and with only the ``basic`` marker:
|
|||
platform linux -- Python 3.x.y, pytest-6.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collecting ... collected 14 items / 11 deselected / 3 selected
|
||||
collecting ... collected 24 items / 21 deselected / 3 selected
|
||||
|
||||
test_pytest_param_example.py::test_eval[1+7-8] PASSED [ 33%]
|
||||
test_pytest_param_example.py::test_eval[basic_2+4] PASSED [ 66%]
|
||||
test_pytest_param_example.py::test_eval[basic_6*9] XFAIL [100%]
|
||||
|
||||
=============== 2 passed, 11 deselected, 1 xfailed in 0.12s ================
|
||||
=============== 2 passed, 21 deselected, 1 xfailed in 0.12s ================
|
||||
|
||||
As the result:
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ The test collection would look like this:
|
|||
<Function simple_check>
|
||||
<Function complex_check>
|
||||
|
||||
========================== 2 tests found in 0.12s ===========================
|
||||
======================== 2 tests collected in 0.12s ========================
|
||||
|
||||
You can check for multiple glob patterns by adding a space between the patterns:
|
||||
|
||||
|
@ -220,7 +220,7 @@ You can always peek at the collection tree without running tests like this:
|
|||
<Function test_method>
|
||||
<Function test_anothermethod>
|
||||
|
||||
========================== 3 tests found in 0.12s ===========================
|
||||
======================== 3 tests collected in 0.12s ========================
|
||||
|
||||
.. _customizing-test-collection:
|
||||
|
||||
|
@ -296,7 +296,7 @@ file will be left out:
|
|||
rootdir: $REGENDOC_TMPDIR, configfile: pytest.ini
|
||||
collected 0 items
|
||||
|
||||
========================== no tests found in 0.12s ===========================
|
||||
======================= no tests collected in 0.12s ========================
|
||||
|
||||
It's also possible to ignore files based on Unix shell-style wildcards by adding
|
||||
patterns to :globalvar:`collect_ignore_glob`.
|
||||
|
|
|
@ -446,7 +446,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
|
|||
|
||||
def test_reinterpret_fails_with_print_for_the_fun_of_it(self):
|
||||
items = [1, 2, 3]
|
||||
print("items is {!r}".format(items))
|
||||
print(f"items is {items!r}")
|
||||
> a, b = items.pop()
|
||||
E TypeError: cannot unpack non-iterable int object
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ Here is a basic pattern to achieve this:
|
|||
|
||||
|
||||
For this to work we need to add a command line option and
|
||||
provide the ``cmdopt`` through a :ref:`fixture function <fixture function>`:
|
||||
provide the ``cmdopt`` through a :ref:`fixture function <fixture>`:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -768,8 +768,8 @@ case we just write some information out to a ``failures`` file:
|
|||
mode = "a" if os.path.exists("failures") else "w"
|
||||
with open("failures", mode) as f:
|
||||
# let's also access a fixture for the fun of it
|
||||
if "tmpdir" in item.fixturenames:
|
||||
extra = " ({})".format(item.funcargs["tmpdir"])
|
||||
if "tmp_path" in item.fixturenames:
|
||||
extra = " ({})".format(item.funcargs["tmp_path"])
|
||||
else:
|
||||
extra = ""
|
||||
|
||||
|
@ -781,7 +781,7 @@ if you then have failing tests:
|
|||
.. code-block:: python
|
||||
|
||||
# content of test_module.py
|
||||
def test_fail1(tmpdir):
|
||||
def test_fail1(tmp_path):
|
||||
assert 0
|
||||
|
||||
|
||||
|
@ -804,9 +804,9 @@ and run them:
|
|||
================================= FAILURES =================================
|
||||
________________________________ test_fail1 ________________________________
|
||||
|
||||
tmpdir = local('PYTEST_TMPDIR/test_fail10')
|
||||
tmp_path = Path('PYTEST_TMPDIR/test_fail10')
|
||||
|
||||
def test_fail1(tmpdir):
|
||||
def test_fail1(tmp_path):
|
||||
> assert 0
|
||||
E assert 0
|
||||
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
.. _test-anatomy:
|
||||
|
||||
Anatomy of a test
|
||||
=================
|
||||
|
||||
In the simplest terms, a test is meant to look at the result of a particular
|
||||
behavior, and make sure that result aligns with what you would expect.
|
||||
Behavior is not something that can be empirically measured, which is why writing
|
||||
tests can be challenging.
|
||||
|
||||
"Behavior" is the way in which some system **acts in response** to a particular
|
||||
situation and/or stimuli. But exactly *how* or *why* something is done is not
|
||||
quite as important as *what* was done.
|
||||
|
||||
You can think of a test as being broken down into four steps:
|
||||
|
||||
1. **Arrange**
|
||||
2. **Act**
|
||||
3. **Assert**
|
||||
4. **Cleanup**
|
||||
|
||||
**Arrange** is where we prepare everything for our test. This means pretty
|
||||
much everything except for the "**act**". It's lining up the dominoes so that
|
||||
the **act** can do its thing in one, state-changing step. This can mean
|
||||
preparing objects, starting/killing services, entering records into a database,
|
||||
or even things like defining a URL to query, generating some credentials for a
|
||||
user that doesn't exist yet, or just waiting for some process to finish.
|
||||
|
||||
**Act** is the singular, state-changing action that kicks off the **behavior**
|
||||
we want to test. This behavior is what carries out the changing of the state of
|
||||
the system under test (SUT), and it's the resulting changed state that we can
|
||||
look at to make a judgement about the behavior. This typically takes the form of
|
||||
a function/method call.
|
||||
|
||||
**Assert** is where we look at that resulting state and check if it looks how
|
||||
we'd expect after the dust has settled. It's where we gather evidence to say the
|
||||
behavior does or does not aligns with what we expect. The ``assert`` in our test
|
||||
is where we take that measurement/observation and apply our judgement to it. If
|
||||
something should be green, we'd say ``assert thing == "green"``.
|
||||
|
||||
**Cleanup** is where the test picks up after itself, so other tests aren't being
|
||||
accidentally influenced by it.
|
||||
|
||||
At its core, the test is ultimately the **act** and **assert** steps, with the
|
||||
**arrange** step only providing the context. **Behavior** exists between **act**
|
||||
and **assert**.
|
|
@ -0,0 +1,158 @@
|
|||
.. _about-fixtures:
|
||||
|
||||
About fixtures
|
||||
===============
|
||||
|
||||
.. seealso:: :ref:`how-to-fixtures`
|
||||
.. seealso:: :ref:`Fixtures reference <reference-fixtures>`
|
||||
|
||||
pytest fixtures are designed to be explicit, modular and scalable.
|
||||
|
||||
What fixtures are
|
||||
-----------------
|
||||
|
||||
In testing, a `fixture <https://en.wikipedia.org/wiki/Test_fixture#Software>`_
|
||||
provides a defined, reliable and consistent context for the tests. This could
|
||||
include environment (for example a database configured with known parameters)
|
||||
or content (such as a dataset).
|
||||
|
||||
Fixtures define the steps and data that constitute the *arrange* phase of a
|
||||
test (see :ref:`test-anatomy`). In pytest, they are functions you define that
|
||||
serve this purpose. They can also be used to define a test's *act* phase; this
|
||||
is a powerful technique for designing more complex tests.
|
||||
|
||||
The services, state, or other operating environments set up by fixtures are
|
||||
accessed by test functions through arguments. For each fixture used by a test
|
||||
function there is typically a parameter (named after the fixture) in the test
|
||||
function's definition.
|
||||
|
||||
We can tell pytest that a particular function is a fixture by decorating it with
|
||||
:py:func:`@pytest.fixture <pytest.fixture>`. Here's a simple example of
|
||||
what a fixture in pytest might look like:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
class Fruit:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.name == other.name
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def my_fruit():
|
||||
return Fruit("apple")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fruit_basket(my_fruit):
|
||||
return [Fruit("banana"), my_fruit]
|
||||
|
||||
|
||||
def test_my_fruit_in_basket(my_fruit, fruit_basket):
|
||||
assert my_fruit in fruit_basket
|
||||
|
||||
Tests don't have to be limited to a single fixture, either. They can depend on
|
||||
as many fixtures as you want, and fixtures can use other fixtures, as well. This
|
||||
is where pytest's fixture system really shines.
|
||||
|
||||
|
||||
Improvements over xUnit-style setup/teardown functions
|
||||
-----------------------------------------------------------
|
||||
|
||||
pytest fixtures offer dramatic improvements over the classic xUnit
|
||||
style of setup/teardown functions:
|
||||
|
||||
* fixtures have explicit names and are activated by declaring their use
|
||||
from test functions, modules, classes or whole projects.
|
||||
|
||||
* fixtures are implemented in a modular manner, as each fixture name
|
||||
triggers a *fixture function* which can itself use other fixtures.
|
||||
|
||||
* fixture management scales from simple unit to complex
|
||||
functional testing, allowing to parametrize fixtures and tests according
|
||||
to configuration and component options, or to re-use fixtures
|
||||
across function, class, module or whole test session scopes.
|
||||
|
||||
* teardown logic can be easily, and safely managed, no matter how many fixtures
|
||||
are used, without the need to carefully handle errors by hand or micromanage
|
||||
the order that cleanup steps are added.
|
||||
|
||||
In addition, pytest continues to support :ref:`xunitsetup`. You can mix
|
||||
both styles, moving incrementally from classic to new style, as you
|
||||
prefer. You can also start out from existing :ref:`unittest.TestCase
|
||||
style <unittest.TestCase>` or :ref:`nose based <nosestyle>` projects.
|
||||
|
||||
|
||||
|
||||
Fixture errors
|
||||
--------------
|
||||
|
||||
pytest does its best to put all the fixtures for a given test in a linear order
|
||||
so that it can see which fixture happens first, second, third, and so on. If an
|
||||
earlier fixture has a problem, though, and raises an exception, pytest will stop
|
||||
executing fixtures for that test and mark the test as having an error.
|
||||
|
||||
When a test is marked as having an error, it doesn't mean the test failed,
|
||||
though. It just means the test couldn't even be attempted because one of the
|
||||
things it depends on had a problem.
|
||||
|
||||
This is one reason why it's a good idea to cut out as many unnecessary
|
||||
dependencies as possible for a given test. That way a problem in something
|
||||
unrelated isn't causing us to have an incomplete picture of what may or may not
|
||||
have issues.
|
||||
|
||||
Here's a quick example to help explain:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def order():
|
||||
return []
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def append_first(order):
|
||||
order.append(1)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def append_second(order, append_first):
|
||||
order.extend([2])
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def append_third(order, append_second):
|
||||
order += [3]
|
||||
|
||||
|
||||
def test_order(order):
|
||||
assert order == [1, 2, 3]
|
||||
|
||||
|
||||
If, for whatever reason, ``order.append(1)`` had a bug and it raises an exception,
|
||||
we wouldn't be able to know if ``order.extend([2])`` or ``order += [3]`` would
|
||||
also have problems. After ``append_first`` throws an exception, pytest won't run
|
||||
any more fixtures for ``test_order``, and it won't even try to run
|
||||
``test_order`` itself. The only things that would've run would be ``order`` and
|
||||
``append_first``.
|
||||
|
||||
|
||||
Sharing test data
|
||||
-----------------
|
||||
|
||||
If you want to make test data from files available to your tests, a good way
|
||||
to do this is by loading these data in a fixture for use by your tests.
|
||||
This makes use of the automatic caching mechanisms of pytest.
|
||||
|
||||
Another good approach is by adding the data files in the ``tests`` folder.
|
||||
There are also community plugins available to help managing this aspect of
|
||||
testing, e.g. `pytest-datadir <https://pypi.org/project/pytest-datadir/>`__
|
||||
and `pytest-datafiles <https://pypi.org/project/pytest-datafiles/>`__.
|
|
@ -48,7 +48,7 @@ Conventions for Python test discovery
|
|||
* ``test`` prefixed test functions or methods outside of class
|
||||
* ``test`` prefixed test functions or methods inside ``Test`` prefixed test classes (without an ``__init__`` method)
|
||||
|
||||
For examples of how to customize your test discovery :doc:`example/pythoncollection`.
|
||||
For examples of how to customize your test discovery :doc:`/example/pythoncollection`.
|
||||
|
||||
Within Python modules, ``pytest`` also discovers tests using the standard
|
||||
:ref:`unittest.TestCase <unittest.TestCase>` subclassing technique.
|
|
@ -0,0 +1,15 @@
|
|||
:orphan:
|
||||
|
||||
.. _explanation:
|
||||
|
||||
Explanation
|
||||
================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
anatomy
|
||||
fixtures
|
||||
goodpractices
|
||||
flaky
|
||||
pythonpath
|
|
@ -47,7 +47,7 @@ There are several limitations and difficulties with this approach:
|
|||
2. parametrizing the "db" resource is not straight forward:
|
||||
you need to apply a "parametrize" decorator or implement a
|
||||
:py:func:`~hookspec.pytest_generate_tests` hook
|
||||
calling :py:func:`~python.Metafunc.parametrize` which
|
||||
calling :py:func:`~pytest.Metafunc.parametrize` which
|
||||
performs parametrization at the places where the resource
|
||||
is used. Moreover, you need to modify the factory to use an
|
||||
``extrakey`` parameter containing ``request.param`` to the
|
||||
|
@ -113,7 +113,7 @@ This new way of parametrizing funcarg factories should in many cases
|
|||
allow to re-use already written factories because effectively
|
||||
``request.param`` was already used when test functions/classes were
|
||||
parametrized via
|
||||
:py:func:`metafunc.parametrize(indirect=True) <_pytest.python.Metafunc.parametrize>` calls.
|
||||
:py:func:`metafunc.parametrize(indirect=True) <pytest.Metafunc.parametrize>` calls.
|
||||
|
||||
Of course it's perfectly fine to combine parametrization and scoping:
|
||||
|
||||
|
@ -168,7 +168,7 @@ pytest for a long time offered a pytest_configure and a pytest_sessionstart
|
|||
hook which are often used to setup global resources. This suffers from
|
||||
several problems:
|
||||
|
||||
1. in distributed testing the master process would setup test resources
|
||||
1. in distributed testing the managing process would setup test resources
|
||||
that are never needed because it only co-ordinates the test run
|
||||
activities of the worker processes.
|
||||
|
||||
|
|
|
@ -1,22 +1,16 @@
|
|||
Installation and Getting Started
|
||||
.. _get-started:
|
||||
|
||||
Get Started
|
||||
===================================
|
||||
|
||||
**Pythons**: Python 3.6, 3.7, 3.8, 3.9, PyPy3
|
||||
|
||||
**Platforms**: Linux and Windows
|
||||
|
||||
**PyPI package name**: `pytest <https://pypi.org/project/pytest/>`_
|
||||
|
||||
**Documentation as PDF**: `download latest <https://media.readthedocs.org/pdf/pytest/latest/pytest.pdf>`_
|
||||
|
||||
``pytest`` is a framework that makes building simple and scalable tests easy. Tests are expressive and readable—no boilerplate code required. Get started in minutes with a small unit test or complex functional test for your application or library.
|
||||
|
||||
.. _`getstarted`:
|
||||
.. _`installation`:
|
||||
|
||||
Install ``pytest``
|
||||
----------------------------------------
|
||||
|
||||
``pytest`` requires: Python 3.6, 3.7, 3.8, 3.9, or PyPy3.
|
||||
|
||||
1. Run the following command in your command line:
|
||||
|
||||
.. code-block:: bash
|
||||
|
@ -28,14 +22,14 @@ Install ``pytest``
|
|||
.. code-block:: bash
|
||||
|
||||
$ pytest --version
|
||||
pytest 6.1.2
|
||||
pytest 6.2.2
|
||||
|
||||
.. _`simpletest`:
|
||||
|
||||
Create your first test
|
||||
----------------------------------------------------------
|
||||
|
||||
Create a simple test function with just four lines of code:
|
||||
Create a new file called ``test_sample.py``, containing a function, and a test:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -47,7 +41,7 @@ Create a simple test function with just four lines of code:
|
|||
def test_answer():
|
||||
assert func(3) == 5
|
||||
|
||||
That’s it. You can now execute the test function:
|
||||
The test
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
|
@ -210,6 +204,8 @@ This is outlined below:
|
|||
FAILED test_class_demo.py::TestClassDemoInstance::test_two - assert 0
|
||||
2 failed in 0.12s
|
||||
|
||||
Note that attributes added at class level are *class attributes*, so they will be shared between tests.
|
||||
|
||||
Request a unique temporary directory for functional tests
|
||||
--------------------------------------------------------------
|
||||
|
||||
|
@ -217,24 +213,24 @@ Request a unique temporary directory for functional tests
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
# content of test_tmpdir.py
|
||||
def test_needsfiles(tmpdir):
|
||||
print(tmpdir)
|
||||
# content of test_tmp_path.py
|
||||
def test_needsfiles(tmp_path):
|
||||
print(tmp_path)
|
||||
assert 0
|
||||
|
||||
List the name ``tmpdir`` in the test function signature and ``pytest`` will lookup and call a fixture factory to create the resource before performing the test function call. Before the test runs, ``pytest`` creates a unique-per-test-invocation temporary directory:
|
||||
List the name ``tmp_path`` in the test function signature and ``pytest`` will lookup and call a fixture factory to create the resource before performing the test function call. Before the test runs, ``pytest`` creates a unique-per-test-invocation temporary directory:
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
$ pytest -q test_tmpdir.py
|
||||
$ pytest -q test_tmp_path.py
|
||||
F [100%]
|
||||
================================= FAILURES =================================
|
||||
_____________________________ test_needsfiles ______________________________
|
||||
|
||||
tmpdir = local('PYTEST_TMPDIR/test_needsfiles0')
|
||||
tmp_path = Path('PYTEST_TMPDIR/test_needsfiles0')
|
||||
|
||||
def test_needsfiles(tmpdir):
|
||||
print(tmpdir)
|
||||
def test_needsfiles(tmp_path):
|
||||
print(tmp_path)
|
||||
> assert 0
|
||||
E assert 0
|
||||
|
||||
|
@ -242,10 +238,10 @@ List the name ``tmpdir`` in the test function signature and ``pytest`` will look
|
|||
--------------------------- Captured stdout call ---------------------------
|
||||
PYTEST_TMPDIR/test_needsfiles0
|
||||
========================= short test summary info ==========================
|
||||
FAILED test_tmpdir.py::test_needsfiles - assert 0
|
||||
FAILED test_tmp_path.py::test_needsfiles - assert 0
|
||||
1 failed in 0.12s
|
||||
|
||||
More info on tmpdir handling is available at :ref:`Temporary directories and files <tmpdir handling>`.
|
||||
More info on temporary directory handling is available at :ref:`Temporary directories and files <tmpdir handling>`.
|
||||
|
||||
Find out what kind of builtin :ref:`pytest fixtures <fixtures>` exist with the command:
|
||||
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
|
||||
The writing and reporting of assertions in tests
|
||||
==================================================
|
||||
|
||||
.. _`assertfeedback`:
|
||||
.. _`assert with the assert statement`:
|
||||
.. _`assert`:
|
||||
|
||||
How to write and report assertions in tests
|
||||
==================================================
|
||||
|
||||
.. _`assert with the assert statement`:
|
||||
|
||||
Asserting with the ``assert`` statement
|
||||
---------------------------------------------------------
|
||||
|
||||
``pytest`` allows you to use the standard python ``assert`` for verifying
|
||||
``pytest`` allows you to use the standard Python ``assert`` for verifying
|
||||
expectations and values in Python tests. For example, you can write the
|
||||
following:
|
||||
|
||||
|
@ -74,7 +72,7 @@ Assertions about expected exceptions
|
|||
------------------------------------------
|
||||
|
||||
In order to write assertions about raised exceptions, you can use
|
||||
``pytest.raises`` as a context manager like this:
|
||||
:func:`pytest.raises` as a context manager like this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -98,7 +96,7 @@ and if you need to have access to the actual exception info you may use:
|
|||
f()
|
||||
assert "maximum recursion" in str(excinfo.value)
|
||||
|
||||
``excinfo`` is an ``ExceptionInfo`` instance, which is a wrapper around
|
||||
``excinfo`` is an :class:`~pytest.ExceptionInfo` instance, which is a wrapper around
|
||||
the actual exception raised. The main attributes of interest are
|
||||
``.type``, ``.value`` and ``.traceback``.
|
||||
|
||||
|
@ -123,7 +121,7 @@ The regexp parameter of the ``match`` method is matched with the ``re.search``
|
|||
function, so in the above example ``match='123'`` would have worked as
|
||||
well.
|
||||
|
||||
There's an alternate form of the ``pytest.raises`` function where you pass
|
||||
There's an alternate form of the :func:`pytest.raises` function where you pass
|
||||
a function that will be executed with the given ``*args`` and ``**kwargs`` and
|
||||
assert that the given exception is raised:
|
||||
|
||||
|
@ -144,8 +142,8 @@ specific way than just having any exception raised:
|
|||
def test_f():
|
||||
f()
|
||||
|
||||
Using ``pytest.raises`` is likely to be better for cases where you are testing
|
||||
exceptions your own code is deliberately raising, whereas using
|
||||
Using :func:`pytest.raises` is likely to be better for cases where you are
|
||||
testing exceptions your own code is deliberately raising, whereas using
|
||||
``@pytest.mark.xfail`` with a check function is probably better for something
|
||||
like documenting unfixed bugs (where the test describes what "should" happen)
|
||||
or bugs in dependencies.
|
||||
|
@ -175,8 +173,6 @@ when it encounters comparisons. For example:
|
|||
.. code-block:: python
|
||||
|
||||
# content of test_assert2.py
|
||||
|
||||
|
||||
def test_set_comparison():
|
||||
set1 = set("1308")
|
||||
set2 = set("8035")
|
|
@ -1,8 +1,8 @@
|
|||
|
||||
.. _bash_completion:
|
||||
|
||||
Setting up bash completion
|
||||
==========================
|
||||
How to set up bash completion
|
||||
=============================
|
||||
|
||||
When using bash as your shell, ``pytest`` can use argcomplete
|
||||
(https://argcomplete.readthedocs.io/) for auto-completion.
|
|
@ -2,8 +2,8 @@
|
|||
.. _cache:
|
||||
|
||||
|
||||
Cache: working with cross-testrun state
|
||||
=======================================
|
||||
How to re-run failed tests and maintain state between test runs
|
||||
===============================================================
|
||||
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
.. _`captures`:
|
||||
|
||||
Capturing of the stdout/stderr output
|
||||
How to capture stdout/stderr output
|
||||
=========================================================
|
||||
|
||||
Default stdout/stderr/stdin capturing behaviour
|