Compare commits
71 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b27ba97721 | ||
|
|
2b56c7e1ce | ||
|
|
2bee7d7c3e | ||
|
|
713b9e54c3 | ||
|
|
ba4b8c869c | ||
|
|
82e9013e73 | ||
|
|
14142b9113 | ||
|
|
0123b29ed7 | ||
|
|
16efa1bfef | ||
|
|
5624e366c1 | ||
|
|
b88f5df4ce | ||
|
|
3a402811de | ||
|
|
e05b33ed16 | ||
|
|
2e11ea6108 | ||
|
|
18786992bb | ||
|
|
3173a26388 | ||
|
|
5e7b8d813b | ||
|
|
afac1f0021 | ||
|
|
0783030357 | ||
|
|
d910175b9f | ||
|
|
6b2bae9392 | ||
|
|
7ef44913a1 | ||
|
|
813ef9e88f | ||
|
|
f2dd9cc63e | ||
|
|
ce8b1dfa04 | ||
|
|
a73d0151a6 | ||
|
|
3cb1457e6d | ||
|
|
90dfee5da5 | ||
|
|
77a995ffad | ||
|
|
0383d43645 | ||
|
|
76c2a8ebbe | ||
|
|
71a7fd02a5 | ||
|
|
7bc8cb8e2b | ||
|
|
dee8d94876 | ||
|
|
a20880cca2 | ||
|
|
ae9465215e | ||
|
|
1555973487 | ||
|
|
3322c1e033 | ||
|
|
7678f891f9 | ||
|
|
4f2abd7ae0 | ||
|
|
122cf60b27 | ||
|
|
63e3d89647 | ||
|
|
122748a6cf | ||
|
|
1f639e2c22 | ||
|
|
83ba5eb58a | ||
|
|
d07c5ba4ae | ||
|
|
b162ab6a45 | ||
|
|
57141dc708 | ||
|
|
bad4ffc3a7 | ||
|
|
71ad5b0fbb | ||
|
|
3fada8c8ee | ||
|
|
271dc7f17a | ||
|
|
19eb0590f1 | ||
|
|
eaa05531ed | ||
|
|
74aed6ea4c | ||
|
|
cfa9ebc91f | ||
|
|
b0fd8742da | ||
|
|
12cc729f6b | ||
|
|
1c5efffd90 | ||
|
|
8c9ea5e055 | ||
|
|
c58b0fb4ac | ||
|
|
4011af68cd | ||
|
|
9637b3e376 | ||
|
|
33c3ec66b7 | ||
|
|
a79acf279a | ||
|
|
9a4c0b991b | ||
|
|
b490f5f979 | ||
|
|
acfd0fd9d6 | ||
|
|
88434f1f42 | ||
|
|
4d01740be3 | ||
|
|
07792c7113 |
10
.travis.yml
10
.travis.yml
@@ -35,7 +35,9 @@ jobs:
|
||||
- test $(python -c 'import sys; print("%d%d" % sys.version_info[0:2])') = 37
|
||||
|
||||
# Full run of latest supported version, without xdist.
|
||||
- env: TOXENV=py37
|
||||
# Coverage for:
|
||||
# - test_sys_breakpoint_interception (via pexpect).
|
||||
- env: TOXENV=py37-pexpect PYTEST_COVERAGE=1
|
||||
python: '3.7'
|
||||
|
||||
# Coverage tracking is slow with pypy, skip it.
|
||||
@@ -49,13 +51,11 @@ jobs:
|
||||
# - pytester's LsofFdLeakChecker
|
||||
# - TestArgComplete (linux only)
|
||||
# - numpy
|
||||
# - old attrs
|
||||
# Empty PYTEST_ADDOPTS to run this non-verbose.
|
||||
- env: TOXENV=py37-lsof-numpy-twisted-xdist PYTEST_COVERAGE=1 PYTEST_ADDOPTS=
|
||||
- env: TOXENV=py37-lsof-oldattrs-numpy-twisted-xdist PYTEST_COVERAGE=1 PYTEST_ADDOPTS=
|
||||
|
||||
# Specialized factors for py37.
|
||||
# Coverage for:
|
||||
# - test_sys_breakpoint_interception (via pexpect).
|
||||
- env: TOXENV=py37-pexpect PYTEST_COVERAGE=1
|
||||
- env: TOXENV=py37-pluggymaster-xdist
|
||||
- env: TOXENV=py37-freeze
|
||||
|
||||
|
||||
1
AUTHORS
1
AUTHORS
@@ -267,5 +267,6 @@ Wouter van Ackooy
|
||||
Xixi Zhao
|
||||
Xuan Luong
|
||||
Xuecong Liao
|
||||
Yoav Caspi
|
||||
Zac Hatfield-Dodds
|
||||
Zoltán Máté
|
||||
|
||||
@@ -18,6 +18,62 @@ with advance notice in the **Deprecations** section of releases.
|
||||
|
||||
.. towncrier release notes start
|
||||
|
||||
pytest 5.2.2 (2019-10-24)
|
||||
=========================
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- `#5206 <https://github.com/pytest-dev/pytest/issues/5206>`_: Fix ``--nf`` to not forget about known nodeids with partial test selection.
|
||||
|
||||
|
||||
- `#5906 <https://github.com/pytest-dev/pytest/issues/5906>`_: Fix crash with ``KeyboardInterrupt`` during ``--setup-show``.
|
||||
|
||||
|
||||
- `#5946 <https://github.com/pytest-dev/pytest/issues/5946>`_: Fixed issue when parametrizing fixtures with numpy arrays (and possibly other sequence-like types).
|
||||
|
||||
|
||||
- `#6044 <https://github.com/pytest-dev/pytest/issues/6044>`_: Properly ignore ``FileNotFoundError`` exceptions when trying to remove old temporary directories,
|
||||
for instance when multiple processes try to remove the same directory (common with ``pytest-xdist``
|
||||
for example).
|
||||
|
||||
|
||||
pytest 5.2.1 (2019-10-06)
|
||||
=========================
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- `#5902 <https://github.com/pytest-dev/pytest/issues/5902>`_: Fix warnings about deprecated ``cmp`` attribute in ``attrs>=19.2``.
|
||||
|
||||
|
||||
pytest 4.6.6 (2019-10-11)
|
||||
=========================
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- `#5523 <https://github.com/pytest-dev/pytest/issues/5523>`_: Fixed using multiple short options together in the command-line (for example ``-vs``) in Python 3.8+.
|
||||
|
||||
|
||||
- `#5537 <https://github.com/pytest-dev/pytest/issues/5537>`_: Replace ``importlib_metadata`` backport with ``importlib.metadata`` from the
|
||||
standard library on Python 3.8+.
|
||||
|
||||
|
||||
- `#5806 <https://github.com/pytest-dev/pytest/issues/5806>`_: Fix "lexer" being used when uploading to bpaste.net from ``--pastebin`` to "text".
|
||||
|
||||
|
||||
- `#5902 <https://github.com/pytest-dev/pytest/issues/5902>`_: Fix warnings about deprecated ``cmp`` attribute in ``attrs>=19.2``.
|
||||
|
||||
|
||||
|
||||
Trivial/Internal Changes
|
||||
------------------------
|
||||
|
||||
- `#5801 <https://github.com/pytest-dev/pytest/issues/5801>`_: Fixes python version checks (detected by ``flake8-2020``) in case python4 becomes a thing.
|
||||
|
||||
|
||||
|
||||
pytest 5.2.0 (2019-09-28)
|
||||
=========================
|
||||
|
||||
@@ -34,7 +90,7 @@ Features
|
||||
|
||||
- `#1682 <https://github.com/pytest-dev/pytest/issues/1682>`_: The ``scope`` parameter of ``@pytest.fixture`` can now be a callable that receives
|
||||
the fixture name and the ``config`` object as keyword-only parameters.
|
||||
See `the docs <https://docs.pytest.org/en/fixture.html#dynamic-scope>`__ for more information.
|
||||
See `the docs <https://docs.pytest.org/en/latest/fixture.html#dynamic-scope>`__ for more information.
|
||||
|
||||
|
||||
- `#5764 <https://github.com/pytest-dev/pytest/issues/5764>`_: New behavior of the ``--pastebin`` option: failures to connect to the pastebin server are reported, without failing the pytest run
|
||||
@@ -205,9 +261,6 @@ Bug Fixes
|
||||
- `#5477 <https://github.com/pytest-dev/pytest/issues/5477>`_: The XML file produced by ``--junitxml`` now correctly contain a ``<testsuites>`` root element.
|
||||
|
||||
|
||||
- `#5523 <https://github.com/pytest-dev/pytest/issues/5523>`_: Fixed using multiple short options together in the command-line (for example ``-vs``) in Python 3.8+.
|
||||
|
||||
|
||||
- `#5524 <https://github.com/pytest-dev/pytest/issues/5524>`_: Fix issue where ``tmp_path`` and ``tmpdir`` would not remove directories containing files marked as read-only,
|
||||
which could lead to pytest crashing when executed a second time with the ``--basetemp`` option.
|
||||
|
||||
|
||||
22
README.rst
22
README.rst
@@ -111,14 +111,28 @@ Consult the `Changelog <https://docs.pytest.org/en/latest/changelog.html>`__ pag
|
||||
Support pytest
|
||||
--------------
|
||||
|
||||
You can support pytest by obtaining a `Tidelift subscription`_.
|
||||
`Open Collective`_ is an online funding platform for open and transparent communities.
|
||||
It provide tools to raise money and share your finances in full transparency.
|
||||
|
||||
Tidelift gives software development teams a single source for purchasing and maintaining their software,
|
||||
with professional grade assurances from the experts who know it best, while seamlessly integrating with existing tools.
|
||||
It is the platform of choice for individuals and companies that want to make one-time or
|
||||
monthly donations directly to the project.
|
||||
|
||||
See more datails in the `pytest collective`_.
|
||||
|
||||
.. _Open Collective: https://opencollective.com
|
||||
.. _pytest collective: https://opencollective.com/pytest
|
||||
|
||||
|
||||
.. _`Tidelift subscription`: https://tidelift.com/subscription/pkg/pypi-pytest?utm_source=pypi-pytest&utm_medium=referral&utm_campaign=readme
|
||||
pytest for enterprise
|
||||
---------------------
|
||||
|
||||
Available as part of the Tidelift Subscription.
|
||||
|
||||
The maintainers of pytest and thousands of other packages are working with Tidelift to deliver commercial support and
|
||||
maintenance for the open source dependencies you use to build your applications.
|
||||
Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use.
|
||||
|
||||
`Learn more. <https://tidelift.com/subscription/pkg/pypi-pytest?utm_source=pypi-pytest&utm_medium=referral&utm_campaign=enterprise&utm_term=repo>`_
|
||||
|
||||
Security
|
||||
^^^^^^^^
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
<li><a href="{{ pathto('backwards-compatibility') }}">Backwards Compatibility</a></li>
|
||||
<li><a href="{{ pathto('py27-py34-deprecation') }}">Python 2.7 and 3.4 Support</a></li>
|
||||
<li><a href="{{ pathto('sponsor') }}">Sponsor</a></li>
|
||||
<li><a href="{{ pathto('tidelift') }}">pytest for Enterprise</a></li>
|
||||
<li><a href="{{ pathto('license') }}">License</a></li>
|
||||
<li><a href="{{ pathto('contact') }}">Contact Channels</a></li>
|
||||
</ul>
|
||||
|
||||
@@ -6,6 +6,8 @@ Release announcements
|
||||
:maxdepth: 2
|
||||
|
||||
|
||||
release-5.2.2
|
||||
release-5.2.1
|
||||
release-5.2.0
|
||||
release-5.1.3
|
||||
release-5.1.2
|
||||
|
||||
@@ -29,7 +29,6 @@ Thanks to all who contributed to this release, among them:
|
||||
* Michael Goerz
|
||||
* Ran Benita
|
||||
* Tomáš Chvátal
|
||||
* aklajnert
|
||||
|
||||
|
||||
Happy testing,
|
||||
|
||||
23
doc/en/announce/release-5.2.1.rst
Normal file
23
doc/en/announce/release-5.2.1.rst
Normal file
@@ -0,0 +1,23 @@
|
||||
pytest-5.2.1
|
||||
=======================================
|
||||
|
||||
pytest 5.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/latest/changelog.html.
|
||||
|
||||
Thanks to all who contributed to this release, among them:
|
||||
|
||||
* Anthony Sottile
|
||||
* Bruno Oliveira
|
||||
* Florian Bruhin
|
||||
* Hynek Schlawack
|
||||
* Kevin J. Foley
|
||||
* tadashigaki
|
||||
|
||||
|
||||
Happy testing,
|
||||
The pytest Development Team
|
||||
29
doc/en/announce/release-5.2.2.rst
Normal file
29
doc/en/announce/release-5.2.2.rst
Normal file
@@ -0,0 +1,29 @@
|
||||
pytest-5.2.2
|
||||
=======================================
|
||||
|
||||
pytest 5.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/latest/changelog.html.
|
||||
|
||||
Thanks to all who contributed to this release, among them:
|
||||
|
||||
* Albert Tugushev
|
||||
* Andrzej Klajnert
|
||||
* Anthony Sottile
|
||||
* Bruno Oliveira
|
||||
* Daniel Hahler
|
||||
* Florian Bruhin
|
||||
* Nattaphoom Chaipreecha
|
||||
* Oliver Bestwalter
|
||||
* Philipp Loose
|
||||
* Ran Benita
|
||||
* Victor Maryama
|
||||
* Yoav Caspi
|
||||
|
||||
|
||||
Happy testing,
|
||||
The pytest Development Team
|
||||
@@ -104,6 +104,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
|
||||
|
||||
Captured logs are available through the following properties/methods::
|
||||
|
||||
* caplog.messages -> list of format-interpolated log messages
|
||||
* caplog.text -> string containing formatted log output
|
||||
* caplog.records -> list of logging.LogRecord instances
|
||||
* caplog.record_tuples -> list of (logger_name, level, message) tuples
|
||||
|
||||
@@ -277,7 +277,60 @@ You can always peek at the content of the cache using the
|
||||
'test_caching.py::test_function': True,
|
||||
'test_foocompare.py::test_compare': True}
|
||||
cache/nodeids contains:
|
||||
['test_caching.py::test_function']
|
||||
['test_assert1.py::test_function',
|
||||
'test_assert2.py::test_set_comparison',
|
||||
'test_foocompare.py::test_compare',
|
||||
'test_50.py::test_num[0]',
|
||||
'test_50.py::test_num[1]',
|
||||
'test_50.py::test_num[2]',
|
||||
'test_50.py::test_num[3]',
|
||||
'test_50.py::test_num[4]',
|
||||
'test_50.py::test_num[5]',
|
||||
'test_50.py::test_num[6]',
|
||||
'test_50.py::test_num[7]',
|
||||
'test_50.py::test_num[8]',
|
||||
'test_50.py::test_num[9]',
|
||||
'test_50.py::test_num[10]',
|
||||
'test_50.py::test_num[11]',
|
||||
'test_50.py::test_num[12]',
|
||||
'test_50.py::test_num[13]',
|
||||
'test_50.py::test_num[14]',
|
||||
'test_50.py::test_num[15]',
|
||||
'test_50.py::test_num[16]',
|
||||
'test_50.py::test_num[17]',
|
||||
'test_50.py::test_num[18]',
|
||||
'test_50.py::test_num[19]',
|
||||
'test_50.py::test_num[20]',
|
||||
'test_50.py::test_num[21]',
|
||||
'test_50.py::test_num[22]',
|
||||
'test_50.py::test_num[23]',
|
||||
'test_50.py::test_num[24]',
|
||||
'test_50.py::test_num[25]',
|
||||
'test_50.py::test_num[26]',
|
||||
'test_50.py::test_num[27]',
|
||||
'test_50.py::test_num[28]',
|
||||
'test_50.py::test_num[29]',
|
||||
'test_50.py::test_num[30]',
|
||||
'test_50.py::test_num[31]',
|
||||
'test_50.py::test_num[32]',
|
||||
'test_50.py::test_num[33]',
|
||||
'test_50.py::test_num[34]',
|
||||
'test_50.py::test_num[35]',
|
||||
'test_50.py::test_num[36]',
|
||||
'test_50.py::test_num[37]',
|
||||
'test_50.py::test_num[38]',
|
||||
'test_50.py::test_num[39]',
|
||||
'test_50.py::test_num[40]',
|
||||
'test_50.py::test_num[41]',
|
||||
'test_50.py::test_num[42]',
|
||||
'test_50.py::test_num[43]',
|
||||
'test_50.py::test_num[44]',
|
||||
'test_50.py::test_num[45]',
|
||||
'test_50.py::test_num[46]',
|
||||
'test_50.py::test_num[47]',
|
||||
'test_50.py::test_num[48]',
|
||||
'test_50.py::test_num[49]',
|
||||
'test_caching.py::test_function']
|
||||
cache/stepwise contains:
|
||||
[]
|
||||
example/value contains:
|
||||
|
||||
@@ -38,19 +38,24 @@ Full pytest documentation
|
||||
customize
|
||||
example/index
|
||||
bash-completion
|
||||
faq
|
||||
|
||||
backwards-compatibility
|
||||
deprecations
|
||||
py27-py34-deprecation
|
||||
historical-notes
|
||||
license
|
||||
|
||||
contributing
|
||||
development_guide
|
||||
|
||||
sponsor
|
||||
tidelift
|
||||
license
|
||||
contact
|
||||
|
||||
historical-notes
|
||||
talks
|
||||
projects
|
||||
faq
|
||||
contact
|
||||
sponsor
|
||||
|
||||
|
||||
.. only:: html
|
||||
|
||||
|
||||
@@ -134,10 +134,13 @@ progress output, you can write it into a configuration file:
|
||||
.. code-block:: ini
|
||||
|
||||
# content of pytest.ini or tox.ini
|
||||
# setup.cfg files should use [tool:pytest] section instead
|
||||
[pytest]
|
||||
addopts = -ra -q
|
||||
|
||||
# content of setup.cfg
|
||||
[tool:pytest]
|
||||
addopts = -ra -q
|
||||
|
||||
Alternatively, you can set a ``PYTEST_ADDOPTS`` environment variable to add command
|
||||
line options while the environment is in use:
|
||||
|
||||
|
||||
@@ -156,6 +156,8 @@ pytest also introduces new options:
|
||||
a string! This means that it may not be appropriate to enable globally in
|
||||
``doctest_optionflags`` in your configuration file.
|
||||
|
||||
.. versionadded:: 5.1
|
||||
|
||||
|
||||
Continue on failure
|
||||
-------------------
|
||||
|
||||
@@ -678,4 +678,4 @@ Or, if desired, you can ``pip install contextlib2`` and use:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from contextlib2 import ExitStack as does_not_raise
|
||||
from contextlib2 import nullcontext as does_not_raise
|
||||
|
||||
@@ -301,9 +301,13 @@ are finalized when the last test of a *package* finishes.
|
||||
Use this new feature sparingly and please make sure to report any issues you find.
|
||||
|
||||
|
||||
.. _dynamic scope:
|
||||
|
||||
Dynamic scope
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
.. versionadded:: 5.2
|
||||
|
||||
In some cases, you might want to change the scope of the fixture without changing the code.
|
||||
To do that, pass a callable to ``scope``. The callable must return a string with a valid scope
|
||||
and will be executed only once - during the fixture definition. It will be called with two
|
||||
|
||||
@@ -83,6 +83,39 @@ Changelog
|
||||
|
||||
Consult the :ref:`Changelog <changelog>` page for fixes and enhancements of each version.
|
||||
|
||||
Support pytest
|
||||
--------------
|
||||
|
||||
`Open Collective`_ is an online funding platform for open and transparent communities.
|
||||
It provide tools to raise money and share your finances in full transparency.
|
||||
|
||||
It is the platform of choice for individuals and companies that want to make one-time or
|
||||
monthly donations directly to the project.
|
||||
|
||||
See more datails in the `pytest collective`_.
|
||||
|
||||
.. _Open Collective: https://opencollective.com
|
||||
.. _pytest collective: https://opencollective.com/pytest
|
||||
|
||||
|
||||
pytest for enterprise
|
||||
---------------------
|
||||
|
||||
Available as part of the Tidelift Subscription.
|
||||
|
||||
The maintainers of pytest and thousands of other packages are working with Tidelift to deliver commercial support and
|
||||
maintenance for the open source dependencies you use to build your applications.
|
||||
Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use.
|
||||
|
||||
`Learn more. <https://tidelift.com/subscription/pkg/pypi-pytest?utm_source=pypi-pytest&utm_medium=referral&utm_campaign=enterprise&utm_term=repo>`_
|
||||
|
||||
Security
|
||||
^^^^^^^^
|
||||
|
||||
pytest has never been associated with a security vunerability, but in any case, to report a
|
||||
security vulnerability please use the `Tidelift security contact <https://tidelift.com/security>`_.
|
||||
Tidelift will coordinate the fix and disclosure.
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
@@ -38,7 +38,8 @@ Here are some examples of projects using ``pytest`` (please send notes via :ref:
|
||||
* `execnet <http://codespeak.net/execnet>`_ rapid multi-Python deployment
|
||||
* `pylib <https://pylib.readthedocs.io/en/stable/>`_ cross-platform path, IO, dynamic code library
|
||||
* `bbfreeze <https://pypi.org/project/bbfreeze/>`_ create standalone executables from Python scripts
|
||||
* `pdb++ <http://bitbucket.org/antocuni/pdb>`_ a fancier version of PDB
|
||||
* `pdb++ <https://github.com/pdbpp/pdbpp>`_ a fancier version of PDB
|
||||
* `pudb <https://github.com/inducer/pudb>`_ full-screen console debugger for python
|
||||
* `py-s3fuse <http://code.google.com/p/py-s3fuse/>`_ Amazon S3 FUSE based filesystem
|
||||
* `waskr <http://code.google.com/p/waskr/>`_ WSGI Stats Middleware
|
||||
* `guachi <http://code.google.com/p/guachi/>`_ global persistent configs for Python modules
|
||||
|
||||
@@ -24,3 +24,8 @@ branch will continue to exist so the community itself can contribute patches. Th
|
||||
be happy to accept those patches and make new ``4.6`` releases **until mid-2020**.
|
||||
|
||||
.. _`python_requires`: https://packaging.python.org/guides/distributing-packages-using-setuptools/#python-requires
|
||||
|
||||
Technical Aspects
|
||||
-----------------
|
||||
|
||||
The technical aspects of the Python 2.7 and 3.4 support plan (such as when releases will occurr, how to backport fixes, etc) is described in issue `#5275 <https://github.com/pytest-dev/pytest/issues/5275>`__.
|
||||
|
||||
@@ -1003,7 +1003,7 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||
[pytest]
|
||||
addopts = --maxfail=2 -rf # exit after 2 failures, report fail info
|
||||
|
||||
issuing ``pytest test_hello.py`` actually means::
|
||||
issuing ``pytest test_hello.py`` actually means:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
|
||||
@@ -8,18 +8,6 @@ compensation when possible is welcome to justify time away from friends, family
|
||||
Money is also used to fund local sprints, merchandising (stickers to distribute in conferences for example)
|
||||
and every few years a large sprint involving all members.
|
||||
|
||||
If you or your company benefit from pytest and would like to contribute to the project financially,
|
||||
we are members of two online donation platforms to better suit your needs.
|
||||
|
||||
Tidelift
|
||||
--------
|
||||
|
||||
`Tidelift`_ aims to make Open Source sustainable by offering subscriptions to companies which rely
|
||||
on Open Source packages. This subscription allows it to pay maintainers of those Open Source
|
||||
packages to aid sustainability of the work.
|
||||
|
||||
You can help pytest and the ecosystem by obtaining a `Tidelift subscription`_.
|
||||
|
||||
OpenCollective
|
||||
--------------
|
||||
|
||||
@@ -32,7 +20,6 @@ monthly donations directly to the project.
|
||||
See more datails in the `pytest collective`_.
|
||||
|
||||
|
||||
|
||||
.. _Tidelift: https://tidelift.com
|
||||
.. _Tidelift subscription: https://tidelift.com/subscription/pkg/pypi-pytest
|
||||
.. _Open Collective: https://opencollective.com
|
||||
|
||||
@@ -2,10 +2,6 @@
|
||||
Talks and Tutorials
|
||||
==========================
|
||||
|
||||
.. sidebar:: Next Open Trainings
|
||||
|
||||
- `3 day hands-on workshop covering pytest, tox and devpi: "Professional Testing with Python" <https://python-academy.com/courses/specialtopics/python_course_testing.html>`_ (English), October 21 - 23, 2019, Leipzig, Germany.
|
||||
|
||||
.. _`funcargs`: funcargs.html
|
||||
|
||||
Books
|
||||
|
||||
45
doc/en/tidelift.rst
Normal file
45
doc/en/tidelift.rst
Normal file
@@ -0,0 +1,45 @@
|
||||
pytest for enterprise
|
||||
=====================
|
||||
|
||||
`Tidelift`_ is working with the maintainers of pytest and thousands of other
|
||||
open source projects to deliver commercial support and maintenance for the open source dependencies you use
|
||||
to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the
|
||||
exact dependencies you use.
|
||||
|
||||
`Get more details <https://tidelift.com/subscription/pkg/pypi-pytest?utm_source=pypi-pytest&utm_medium=referral&utm_campaign=enterprise>`_
|
||||
|
||||
The Tidelift Subscription is a managed open source subscription for application dependencies covering millions of open source projects across JavaScript, Python, Java, PHP, Ruby, .NET, and more.
|
||||
|
||||
Your subscription includes:
|
||||
|
||||
* **Security updates**
|
||||
|
||||
- Tidelift's security response team coordinates patches for new breaking security vulnerabilities and alerts immediately through a private channel, so your software supply chain is always secure.
|
||||
|
||||
* **Licensing verification and indemnification**
|
||||
|
||||
- Tidelift verifies license information to enable easy policy enforcement and adds intellectual property indemnification to cover creators and users in case something goes wrong. You always have a 100% up-to-date bill of materials for your dependencies to share with your legal team, customers, or partners.
|
||||
|
||||
* **Maintenance and code improvement**
|
||||
|
||||
- Tidelift ensures the software you rely on keeps working as long as you need it to work. Your managed dependencies are actively maintained and we recruit additional maintainers where required.
|
||||
|
||||
* **Package selection and version guidance**
|
||||
|
||||
- Tidelift helps you choose the best open source packages from the start—and then guide you through updates to stay on the best releases as new issues arise.
|
||||
|
||||
* **Roadmap input**
|
||||
|
||||
- Take a seat at the table with the creators behind the software you use. Tidelift's participating maintainers earn more income as their software is used by more subscribers, so they're interested in knowing what you need.
|
||||
|
||||
* **Tooling and cloud integration**
|
||||
|
||||
- Tidelift works with GitHub, GitLab, BitBucket, and every cloud platform (and other deployment targets, too).
|
||||
|
||||
The end result? All of the capabilities you expect from commercial-grade software, for the full breadth of open
|
||||
source you use. That means less time grappling with esoteric open source trivia, and more time building your own
|
||||
applications—and your business.
|
||||
|
||||
`Request a demo <https://tidelift.com/subscription/request-a-demo?utm_source=pypi-pytest&utm_medium=referral&utm_campaign=enterprise>`_
|
||||
|
||||
.. _Tidelift: https://tidelift.com
|
||||
@@ -718,6 +718,11 @@ for example ``-x`` if you only want to send one particular failure.
|
||||
|
||||
Currently only pasting to the http://bpaste.net service is implemented.
|
||||
|
||||
.. versionchanged:: 5.2
|
||||
|
||||
If creating the URL fails for any reason, a warning is generated instead of failing the
|
||||
entire test suite.
|
||||
|
||||
Early loading plugins
|
||||
---------------------
|
||||
|
||||
|
||||
@@ -13,5 +13,6 @@ fi
|
||||
python -m coverage combine
|
||||
python -m coverage xml
|
||||
python -m coverage report -m
|
||||
curl -S -L --retry 6 -s https://codecov.io/bash -o codecov-upload.sh
|
||||
# Set --connect-timeout to work around https://github.com/curl/curl/issues/4461
|
||||
curl -S -L --connect-timeout 5 --retry 6 -s https://codecov.io/bash -o codecov-upload.sh
|
||||
bash codecov-upload.sh -Z -X fix -f coverage.xml
|
||||
|
||||
2
setup.py
2
setup.py
@@ -5,7 +5,7 @@ from setuptools import setup
|
||||
INSTALL_REQUIRES = [
|
||||
"py>=1.5.0",
|
||||
"packaging",
|
||||
"attrs>=17.4.0",
|
||||
"attrs>=17.4.0", # should match oldattrs tox env.
|
||||
"more-itertools>=4.0.0",
|
||||
"atomicwrites>=1.0",
|
||||
'pathlib2>=2.2.0;python_version<"3.6"',
|
||||
|
||||
@@ -8,6 +8,7 @@ from typing import Optional
|
||||
import _pytest._code
|
||||
from _pytest import outcomes
|
||||
from _pytest._io.saferepr import saferepr
|
||||
from _pytest.compat import ATTRS_EQ_FIELD
|
||||
|
||||
# The _reprcompare attribute on the util module is used by the new assertion
|
||||
# interpretation code and assertion rewriter to detect this plugin was
|
||||
@@ -375,7 +376,9 @@ def _compare_eq_cls(left, right, verbose, type_fns):
|
||||
fields_to_check = [field for field, info in all_fields.items() if info.compare]
|
||||
elif isattrs(left):
|
||||
all_fields = left.__attrs_attrs__
|
||||
fields_to_check = [field.name for field in all_fields if field.cmp]
|
||||
fields_to_check = [
|
||||
field.name for field in all_fields if getattr(field, ATTRS_EQ_FIELD)
|
||||
]
|
||||
|
||||
same = []
|
||||
diff = []
|
||||
|
||||
@@ -135,7 +135,7 @@ class Cache:
|
||||
readme_path.write_text(README_CONTENT)
|
||||
|
||||
gitignore_path = self._cachedir.joinpath(".gitignore")
|
||||
msg = "# Created by pytest automatically.\n*"
|
||||
msg = "# Created by pytest automatically.\n*\n"
|
||||
gitignore_path.write_text(msg, encoding="UTF-8")
|
||||
|
||||
cachedir_tag_path = self._cachedir.joinpath("CACHEDIR.TAG")
|
||||
@@ -264,8 +264,8 @@ class NFPlugin:
|
||||
self.cached_nodeids = config.cache.get("cache/nodeids", [])
|
||||
|
||||
def pytest_collection_modifyitems(self, session, config, items):
|
||||
new_items = OrderedDict()
|
||||
if self.active:
|
||||
new_items = OrderedDict()
|
||||
other_items = OrderedDict()
|
||||
for item in items:
|
||||
if item.nodeid not in self.cached_nodeids:
|
||||
@@ -276,7 +276,11 @@ class NFPlugin:
|
||||
items[:] = self._get_increasing_order(
|
||||
new_items.values()
|
||||
) + self._get_increasing_order(other_items.values())
|
||||
self.cached_nodeids = [x.nodeid for x in items if isinstance(x, pytest.Item)]
|
||||
else:
|
||||
for item in items:
|
||||
if item.nodeid not in self.cached_nodeids:
|
||||
new_items[item.nodeid] = item
|
||||
self.cached_nodeids.extend(new_items)
|
||||
|
||||
def _get_increasing_order(self, items):
|
||||
return sorted(items, key=lambda item: item.fspath.mtime(), reverse=True)
|
||||
|
||||
@@ -354,3 +354,9 @@ if sys.version_info < (3, 5, 2): # pragma: no cover
|
||||
|
||||
def overload(f): # noqa: F811
|
||||
return f
|
||||
|
||||
|
||||
if getattr(attr, "__version_info__", ()) >= (19, 2):
|
||||
ATTRS_EQ_FIELD = "eq"
|
||||
else:
|
||||
ATTRS_EQ_FIELD = "cmp"
|
||||
|
||||
@@ -195,7 +195,6 @@ def get_plugin_manager():
|
||||
|
||||
|
||||
def _prepareconfig(args=None, plugins=None):
|
||||
warning = None
|
||||
if args is None:
|
||||
args = sys.argv[1:]
|
||||
elif isinstance(args, py.path.local):
|
||||
@@ -213,10 +212,6 @@ def _prepareconfig(args=None, plugins=None):
|
||||
pluginmanager.consider_pluginarg(plugin)
|
||||
else:
|
||||
pluginmanager.register(plugin)
|
||||
if warning:
|
||||
from _pytest.warnings import _issue_warning_captured
|
||||
|
||||
_issue_warning_captured(warning, hook=config.hook, stacklevel=4)
|
||||
return pluginmanager.hook.pytest_cmdline_parse(
|
||||
pluginmanager=pluginmanager, args=args
|
||||
)
|
||||
@@ -663,6 +658,8 @@ class Config:
|
||||
class InvocationParams:
|
||||
"""Holds parameters passed during ``pytest.main()``
|
||||
|
||||
.. versionadded:: 5.1
|
||||
|
||||
.. note::
|
||||
|
||||
Currently the environment variable PYTEST_ADDOPTS is also handled by
|
||||
|
||||
@@ -1088,9 +1088,13 @@ def fixture(
|
||||
|
||||
:arg scope: the scope for which this fixture is shared, one of
|
||||
``"function"`` (default), ``"class"``, ``"module"``,
|
||||
``"package"`` or ``"session"``.
|
||||
``"package"`` or ``"session"`` (``"package"`` is considered **experimental**
|
||||
at this time).
|
||||
|
||||
``"package"`` is considered **experimental** at this time.
|
||||
This parameter may also be a callable which receives ``(fixture_name, config)``
|
||||
as parameters, and must return a ``str`` with one of the values mentioned above.
|
||||
|
||||
See :ref:`dynamic scope` in the docs for more information.
|
||||
|
||||
:arg params: an optional list of parameters which will cause multiple
|
||||
invocations of the fixture function and all of the tests
|
||||
@@ -1113,6 +1117,9 @@ def fixture(
|
||||
``fixture_<fixturename>`` and then use
|
||||
``@pytest.fixture(name='<fixturename>')``.
|
||||
"""
|
||||
if params is not None:
|
||||
params = list(params)
|
||||
|
||||
fixture_function, arguments = _parse_fixture_args(
|
||||
callable_or_scope,
|
||||
*args,
|
||||
@@ -1134,8 +1141,6 @@ def fixture(
|
||||
fixture_function
|
||||
)
|
||||
|
||||
if params is not None and not isinstance(params, (list, tuple)):
|
||||
params = list(params)
|
||||
return FixtureFunctionMarker(scope, params, autouse, ids=ids, name=name)
|
||||
|
||||
|
||||
|
||||
@@ -488,6 +488,8 @@ def pytest_assertion_pass(item, lineno, orig, expl):
|
||||
"""
|
||||
**(Experimental)**
|
||||
|
||||
.. versionadded:: 5.0
|
||||
|
||||
Hook called whenever an assertion *passes*.
|
||||
|
||||
Use this hook to do some processing after a passing assertion.
|
||||
|
||||
@@ -356,6 +356,7 @@ def caplog(request):
|
||||
|
||||
Captured logs are available through the following properties/methods::
|
||||
|
||||
* caplog.messages -> list of format-interpolated log messages
|
||||
* caplog.text -> string containing formatted log output
|
||||
* caplog.records -> list of logging.LogRecord instances
|
||||
* caplog.record_tuples -> list of (logger_name, level, message) tuples
|
||||
|
||||
@@ -20,6 +20,8 @@ from _pytest.runner import collect_one_node
|
||||
|
||||
class ExitCode(enum.IntEnum):
|
||||
"""
|
||||
.. versionadded:: 5.0
|
||||
|
||||
Encodes the valid exit codes by pytest.
|
||||
|
||||
Currently users and plugins may supply other exit codes as well.
|
||||
|
||||
@@ -8,6 +8,7 @@ from typing import Set
|
||||
import attr
|
||||
|
||||
from ..compat import ascii_escaped
|
||||
from ..compat import ATTRS_EQ_FIELD
|
||||
from ..compat import getfslineno
|
||||
from ..compat import NOTSET
|
||||
from _pytest.outcomes import fail
|
||||
@@ -367,7 +368,8 @@ class NodeKeywords(MutableMapping):
|
||||
return "<NodeKeywords for node {}>".format(self.node)
|
||||
|
||||
|
||||
@attr.s(cmp=False, hash=False)
|
||||
# mypy cannot find this overload, remove when on attrs>=19.2
|
||||
@attr.s(hash=False, **{ATTRS_EQ_FIELD: False}) # type: ignore
|
||||
class NodeMarkers:
|
||||
"""
|
||||
internal structure for storing marks belonging to a node
|
||||
|
||||
@@ -38,21 +38,35 @@ def ensure_reset_dir(path):
|
||||
path.mkdir()
|
||||
|
||||
|
||||
def on_rm_rf_error(func, path: str, exc, *, start_path):
|
||||
"""Handles known read-only errors during rmtree."""
|
||||
excvalue = exc[1]
|
||||
def on_rm_rf_error(func, path: str, exc, *, start_path) -> bool:
|
||||
"""Handles known read-only errors during rmtree.
|
||||
|
||||
The returned value is used only by our own tests.
|
||||
"""
|
||||
exctype, excvalue = exc[:2]
|
||||
|
||||
# another process removed the file in the middle of the "rm_rf" (xdist for example)
|
||||
# more context: https://github.com/pytest-dev/pytest/issues/5974#issuecomment-543799018
|
||||
if isinstance(excvalue, FileNotFoundError):
|
||||
return False
|
||||
|
||||
if not isinstance(excvalue, PermissionError):
|
||||
warnings.warn(
|
||||
PytestWarning("(rm_rf) error removing {}: {}".format(path, excvalue))
|
||||
PytestWarning(
|
||||
"(rm_rf) error removing {}\n{}: {}".format(path, exctype, excvalue)
|
||||
)
|
||||
)
|
||||
return
|
||||
return False
|
||||
|
||||
if func not in (os.rmdir, os.remove, os.unlink):
|
||||
warnings.warn(
|
||||
PytestWarning("(rm_rf) error removing {}: {}".format(path, excvalue))
|
||||
PytestWarning(
|
||||
"(rm_rf) unknown function {} when removing {}:\n{}: {}".format(
|
||||
path, func, exctype, excvalue
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
return False
|
||||
|
||||
# Chmod + retry.
|
||||
import stat
|
||||
@@ -73,6 +87,7 @@ def on_rm_rf_error(func, path: str, exc, *, start_path):
|
||||
chmod_rw(str(path))
|
||||
|
||||
func(path)
|
||||
return True
|
||||
|
||||
|
||||
def rm_rf(path: Path):
|
||||
|
||||
@@ -351,15 +351,14 @@ class RunResult:
|
||||
|
||||
Attributes:
|
||||
|
||||
:ret: the return value
|
||||
:outlines: list of lines captured from stdout
|
||||
:errlines: list of lines captures from stderr
|
||||
:stdout: :py:class:`LineMatcher` of stdout, use ``stdout.str()`` to
|
||||
:ivar ret: the return value
|
||||
:ivar outlines: list of lines captured from stdout
|
||||
:ivar errlines: list of lines captured from stderr
|
||||
:ivar stdout: :py:class:`LineMatcher` of stdout, use ``stdout.str()`` to
|
||||
reconstruct stdout or the commonly used ``stdout.fnmatch_lines()``
|
||||
method
|
||||
:stderr: :py:class:`LineMatcher` of stderr
|
||||
:duration: duration in seconds
|
||||
|
||||
:ivar stderr: :py:class:`LineMatcher` of stderr
|
||||
:ivar duration: duration in seconds
|
||||
"""
|
||||
|
||||
def __init__(self, ret, outlines, errlines, duration):
|
||||
@@ -454,9 +453,9 @@ class Testdir:
|
||||
|
||||
Attributes:
|
||||
|
||||
:tmpdir: The :py:class:`py.path.local` instance of the temporary directory.
|
||||
:ivar tmpdir: The :py:class:`py.path.local` instance of the temporary directory.
|
||||
|
||||
:plugins: A list of plugins to use with :py:meth:`parseconfig` and
|
||||
:ivar plugins: A list of plugins to use with :py:meth:`parseconfig` and
|
||||
:py:meth:`runpytest`. Initially this is an empty list but plugins can
|
||||
be added to the list. The type of items to add to the list depends on
|
||||
the method using them so refer to them for details.
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@@ -51,7 +49,6 @@ def _show_fixture_action(fixturedef, msg):
|
||||
capman = config.pluginmanager.getplugin("capturemanager")
|
||||
if capman:
|
||||
capman.suspend_global_capture()
|
||||
out, err = capman.read_global_capture()
|
||||
|
||||
tw = config.get_terminal_writer()
|
||||
tw.line()
|
||||
@@ -74,8 +71,6 @@ def _show_fixture_action(fixturedef, msg):
|
||||
|
||||
if capman:
|
||||
capman.resume_global_capture()
|
||||
sys.stdout.write(out)
|
||||
sys.stderr.write(err)
|
||||
|
||||
|
||||
@pytest.hookimpl(tryfirst=True)
|
||||
|
||||
@@ -4187,3 +4187,23 @@ def test_indirect_fixture_does_not_break_scope(testdir):
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.assert_outcomes(passed=7)
|
||||
|
||||
|
||||
def test_fixture_parametrization_nparray(testdir):
|
||||
pytest.importorskip("numpy")
|
||||
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
from numpy import linspace
|
||||
from pytest import fixture
|
||||
|
||||
@fixture(params=linspace(1, 10, 10))
|
||||
def value(request):
|
||||
return request.param
|
||||
|
||||
def test_bug(value):
|
||||
assert value == value
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.assert_outcomes(passed=10)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import pytest
|
||||
from _pytest.main import ExitCode
|
||||
|
||||
|
||||
@pytest.fixture(params=["--setup-only", "--setup-plan", "--setup-show"], scope="module")
|
||||
@@ -267,3 +268,27 @@ def test_show_fixtures_and_execute_test(testdir):
|
||||
result.stdout.fnmatch_lines(
|
||||
["*SETUP F arg*", "*test_arg (fixtures used: arg)F*", "*TEARDOWN F arg*"]
|
||||
)
|
||||
|
||||
|
||||
def test_setup_show_with_KeyboardInterrupt_in_test(testdir):
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
@pytest.fixture
|
||||
def arg():
|
||||
pass
|
||||
def test_arg(arg):
|
||||
raise KeyboardInterrupt()
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest("--setup-show", p, no_reraise_ctrlc=True)
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*SETUP F arg*",
|
||||
"*test_arg (fixtures used: arg)*",
|
||||
"*TEARDOWN F arg*",
|
||||
"*! KeyboardInterrupt !*",
|
||||
"*= no tests ran in *",
|
||||
]
|
||||
)
|
||||
assert result.ret == ExitCode.INTERRUPTED
|
||||
|
||||
@@ -9,6 +9,7 @@ import pytest
|
||||
from _pytest import outcomes
|
||||
from _pytest.assertion import truncate
|
||||
from _pytest.assertion import util
|
||||
from _pytest.compat import ATTRS_EQ_FIELD
|
||||
|
||||
|
||||
def mock_config():
|
||||
@@ -687,7 +688,7 @@ class TestAssert_reprcompare_attrsclass:
|
||||
@attr.s
|
||||
class SimpleDataObject:
|
||||
field_a = attr.ib()
|
||||
field_b = attr.ib(cmp=False)
|
||||
field_b = attr.ib(**{ATTRS_EQ_FIELD: False})
|
||||
|
||||
left = SimpleDataObject(1, "b")
|
||||
right = SimpleDataObject(1, "b")
|
||||
|
||||
@@ -982,8 +982,13 @@ class TestNewFirst:
|
||||
)
|
||||
testdir.tmpdir.join("test_1/test_1.py").setmtime(1)
|
||||
|
||||
result = testdir.runpytest("-v", "--nf")
|
||||
# Running only a subset does not forget about existing ones.
|
||||
result = testdir.runpytest("-v", "--nf", "test_2/test_2.py")
|
||||
result.stdout.fnmatch_lines(
|
||||
["*test_2/test_2.py::test_1[1*", "*test_2/test_2.py::test_1[2*"]
|
||||
)
|
||||
|
||||
result = testdir.runpytest("-v", "--nf")
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*test_1/test_1.py::test_1[3*",
|
||||
@@ -1029,7 +1034,7 @@ def test_gitignore(testdir):
|
||||
config = testdir.parseconfig()
|
||||
cache = Cache.for_config(config)
|
||||
cache.set("foo", "bar")
|
||||
msg = "# Created by pytest automatically.\n*"
|
||||
msg = "# Created by pytest automatically.\n*\n"
|
||||
gitignore_path = cache._cachedir.joinpath(".gitignore")
|
||||
assert gitignore_path.read_text(encoding="UTF-8") == msg
|
||||
|
||||
|
||||
28
testing/test_meta.py
Normal file
28
testing/test_meta.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import pkgutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import _pytest
|
||||
import pytest
|
||||
|
||||
|
||||
def _modules():
|
||||
return sorted(
|
||||
n
|
||||
for _, n, _ in pkgutil.walk_packages(
|
||||
_pytest.__path__, prefix=_pytest.__name__ + "."
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("module", _modules())
|
||||
def test_no_warnings(module):
|
||||
# fmt: off
|
||||
subprocess.check_call((
|
||||
sys.executable,
|
||||
"-W", "error",
|
||||
# https://github.com/pytest-dev/pytest/issues/5901
|
||||
"-W", "ignore:The usage of `cmp` is deprecated and will be removed on or after 2021-06-01. Please use `eq` and `order` instead.:DeprecationWarning", # noqa: E501
|
||||
"-c", "import {}".format(module),
|
||||
))
|
||||
# fmt: on
|
||||
@@ -17,6 +17,14 @@ else:
|
||||
_ENVIRON_PYTHONBREAKPOINT = os.environ.get("PYTHONBREAKPOINT", "")
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def pdb_env(request):
|
||||
if "testdir" in request.fixturenames:
|
||||
# Disable pdb++ with inner tests.
|
||||
testdir = request.getfixturevalue("testdir")
|
||||
testdir._env_run_update["PDBPP_HIJACK_PDB"] = "0"
|
||||
|
||||
|
||||
def runpdb_and_get_report(testdir, source):
|
||||
p = testdir.makepyfile(source)
|
||||
result = testdir.runpytest_inprocess("--pdb", p)
|
||||
|
||||
@@ -567,9 +567,19 @@ def test_pytest_exit_msg(testdir):
|
||||
result.stderr.fnmatch_lines(["Exit: oh noes"])
|
||||
|
||||
|
||||
def _strip_resource_warnings(lines):
|
||||
# Assert no output on stderr, except for unreliable ResourceWarnings.
|
||||
# (https://github.com/pytest-dev/pytest/issues/5088)
|
||||
return [
|
||||
x
|
||||
for x in lines
|
||||
if not x.startswith(("Exception ignored in:", "ResourceWarning"))
|
||||
]
|
||||
|
||||
|
||||
def test_pytest_exit_returncode(testdir):
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
"""\
|
||||
import pytest
|
||||
def test_foo():
|
||||
pytest.exit("some exit msg", 99)
|
||||
@@ -577,19 +587,13 @@ def test_pytest_exit_returncode(testdir):
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(["*! *Exit: some exit msg !*"])
|
||||
# Assert no output on stderr, except for unreliable ResourceWarnings.
|
||||
# (https://github.com/pytest-dev/pytest/issues/5088)
|
||||
assert [
|
||||
x
|
||||
for x in result.stderr.lines
|
||||
if not x.startswith("Exception ignored in:")
|
||||
and not x.startswith("ResourceWarning")
|
||||
] == [""]
|
||||
|
||||
assert _strip_resource_warnings(result.stderr.lines) == [""]
|
||||
assert result.ret == 99
|
||||
|
||||
# It prints to stderr also in case of exit during pytest_sessionstart.
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
"""\
|
||||
import pytest
|
||||
|
||||
def pytest_sessionstart():
|
||||
@@ -598,7 +602,10 @@ def test_pytest_exit_returncode(testdir):
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(["*! *Exit: during_sessionstart !*"])
|
||||
assert result.stderr.lines == ["Exit: during_sessionstart", ""]
|
||||
assert _strip_resource_warnings(result.stderr.lines) == [
|
||||
"Exit: during_sessionstart",
|
||||
"",
|
||||
]
|
||||
assert result.ret == 98
|
||||
|
||||
|
||||
|
||||
@@ -383,6 +383,10 @@ class TestRmRf:
|
||||
on_rm_rf_error(os.unlink, str(fn), exc_info, start_path=tmp_path)
|
||||
assert fn.is_file()
|
||||
|
||||
# we ignore FileNotFoundError
|
||||
exc_info = (None, FileNotFoundError(), None)
|
||||
assert not on_rm_rf_error(None, str(fn), exc_info, start_path=tmp_path)
|
||||
|
||||
# unknown function
|
||||
with pytest.warns(pytest.PytestWarning):
|
||||
exc_info = (None, PermissionError(), None)
|
||||
|
||||
4
tox.ini
4
tox.ini
@@ -41,6 +41,8 @@ setenv =
|
||||
xdist: _PYTEST_TOX_POSARGS_XDIST=-n auto
|
||||
extras = testing
|
||||
deps =
|
||||
oldattrs: attrs==17.4.0
|
||||
oldattrs: hypothesis<=4.38.1
|
||||
numpy: numpy
|
||||
pexpect: pexpect
|
||||
pluggymaster: git+https://github.com/pytest-dev/pluggy.git@master
|
||||
@@ -140,6 +142,8 @@ filterwarnings =
|
||||
error
|
||||
default:Using or importing the ABCs:DeprecationWarning:unittest2.*
|
||||
ignore:Module already imported so cannot be rewritten:pytest.PytestWarning
|
||||
# https://github.com/pytest-dev/pytest/issues/5974
|
||||
default:\(rm_rf\) error removing.*:pytest.PytestWarning
|
||||
# produced by python3.6/site.py itself (3.6.7 on Travis, could not trigger it with 3.6.8).
|
||||
ignore:.*U.*mode is deprecated:DeprecationWarning:(?!(pytest|_pytest))
|
||||
# produced by pytest-xdist
|
||||
|
||||
Reference in New Issue
Block a user