Merge remote-tracking branch 'upstream/master' into mm
This commit is contained in:
commit
853889e5db
1
AUTHORS
1
AUTHORS
|
@ -63,6 +63,7 @@ Christian Tismer
|
||||||
Christoph Buelter
|
Christoph Buelter
|
||||||
Christopher Dignam
|
Christopher Dignam
|
||||||
Christopher Gilling
|
Christopher Gilling
|
||||||
|
Claudio Madotto
|
||||||
CrazyMerlyn
|
CrazyMerlyn
|
||||||
Cyrus Maden
|
Cyrus Maden
|
||||||
Damian Skrzypczak
|
Damian Skrzypczak
|
||||||
|
|
|
@ -137,7 +137,7 @@ Save time, reduce risk, and improve code health, while paying the maintainers of
|
||||||
Security
|
Security
|
||||||
^^^^^^^^
|
^^^^^^^^
|
||||||
|
|
||||||
pytest has never been associated with a security vunerability, but in any case, to report a
|
pytest has never been associated with a security vulnerability, but in any case, to report a
|
||||||
security vulnerability please use the `Tidelift security contact <https://tidelift.com/security>`_.
|
security vulnerability please use the `Tidelift security contact <https://tidelift.com/security>`_.
|
||||||
Tidelift will coordinate the fix and disclosure.
|
Tidelift will coordinate the fix and disclosure.
|
||||||
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
The supporting files in the ``.pytest_cache`` directory are kept with ``--cache-clear``, which only clears cached values now.
|
|
|
@ -6,6 +6,7 @@ Release announcements
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
|
|
||||||
|
release-5.3.2
|
||||||
release-5.3.1
|
release-5.3.1
|
||||||
release-5.3.0
|
release-5.3.0
|
||||||
release-5.2.4
|
release-5.2.4
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
pytest-5.3.2
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
pytest 5.3.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:
|
||||||
|
|
||||||
|
* Anthony Sottile
|
||||||
|
* Bruno Oliveira
|
||||||
|
* Claudio Madotto
|
||||||
|
* Daniel Hahler
|
||||||
|
* Jared Vasquez
|
||||||
|
* Michael Rose
|
||||||
|
* Ran Benita
|
||||||
|
* Ronny Pfannschmidt
|
||||||
|
* Zac Hatfield-Dodds
|
||||||
|
|
||||||
|
|
||||||
|
Happy testing,
|
||||||
|
The pytest Development Team
|
|
@ -24,13 +24,32 @@ with advance notice in the **Deprecations** section of releases.
|
||||||
|
|
||||||
.. include:: _changelog_towncrier_draft.rst
|
.. include:: _changelog_towncrier_draft.rst
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. towncrier release notes start
|
.. towncrier release notes start
|
||||||
|
|
||||||
|
pytest 5.3.2 (2019-12-13)
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Improvements
|
||||||
|
------------
|
||||||
|
|
||||||
|
- `#4639 <https://github.com/pytest-dev/pytest/issues/4639>`_: Revert "A warning is now issued when assertions are made for ``None``".
|
||||||
|
|
||||||
|
The warning proved to be less useful than initially expected and had quite a
|
||||||
|
few false positive cases.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Bug Fixes
|
||||||
|
---------
|
||||||
|
|
||||||
|
- `#5430 <https://github.com/pytest-dev/pytest/issues/5430>`_: junitxml: Logs for failed test are now passed to junit report in case the test fails during call phase.
|
||||||
|
|
||||||
|
|
||||||
|
- `#6290 <https://github.com/pytest-dev/pytest/issues/6290>`_: The supporting files in the ``.pytest_cache`` directory are kept with ``--cache-clear``, which only clears cached values now.
|
||||||
|
|
||||||
|
|
||||||
|
- `#6301 <https://github.com/pytest-dev/pytest/issues/6301>`_: Fix assertion rewriting for egg-based distributions and ``editable`` installs (``pip install --editable``).
|
||||||
|
|
||||||
|
|
||||||
pytest 5.3.1 (2019-11-25)
|
pytest 5.3.1 (2019-11-25)
|
||||||
=========================
|
=========================
|
||||||
|
@ -796,6 +815,20 @@ Improved Documentation
|
||||||
- `#5416 <https://github.com/pytest-dev/pytest/issues/5416>`_: Fix PytestUnknownMarkWarning in run/skip example.
|
- `#5416 <https://github.com/pytest-dev/pytest/issues/5416>`_: Fix PytestUnknownMarkWarning in run/skip example.
|
||||||
|
|
||||||
|
|
||||||
|
pytest 4.6.7 (2019-12-05)
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Bug Fixes
|
||||||
|
---------
|
||||||
|
|
||||||
|
- `#5477 <https://github.com/pytest-dev/pytest/issues/5477>`_: The XML file produced by ``--junitxml`` now correctly contain a ``<testsuites>`` root element.
|
||||||
|
|
||||||
|
|
||||||
|
- `#6044 <https://github.com/pytest-dev/pytest/issues/6044>`_: Properly ignore ``FileNotFoundError`` (``OSError.errno == NOENT`` in Python 2) 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 4.6.6 (2019-10-11)
|
pytest 4.6.6 (2019-10-11)
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
|
|
|
@ -475,10 +475,10 @@ Running it results in some skips if we don't have all the python interpreters in
|
||||||
.. code-block:: pytest
|
.. code-block:: pytest
|
||||||
|
|
||||||
. $ pytest -rs -q multipython.py
|
. $ pytest -rs -q multipython.py
|
||||||
ssssssssssssssssssssssss... [100%]
|
ssssssssssss...ssssssssssss [100%]
|
||||||
========================= short test summary info ==========================
|
========================= short test summary info ==========================
|
||||||
SKIPPED [12] $REGENDOC_TMPDIR/CWD/multipython.py:29: 'python3.5' not found
|
SKIPPED [12] $REGENDOC_TMPDIR/CWD/multipython.py:29: 'python3.5' not found
|
||||||
SKIPPED [12] $REGENDOC_TMPDIR/CWD/multipython.py:29: 'python3.6' not found
|
SKIPPED [12] $REGENDOC_TMPDIR/CWD/multipython.py:29: 'python3.7' not found
|
||||||
3 passed, 24 skipped in 0.12s
|
3 passed, 24 skipped in 0.12s
|
||||||
|
|
||||||
Indirect parametrization of optional implementations/imports
|
Indirect parametrization of optional implementations/imports
|
||||||
|
@ -604,13 +604,13 @@ Then run ``pytest`` with verbose mode and with only the ``basic`` marker:
|
||||||
platform linux -- Python 3.x.y, pytest-5.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python
|
platform linux -- Python 3.x.y, pytest-5.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python
|
||||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||||
rootdir: $REGENDOC_TMPDIR
|
rootdir: $REGENDOC_TMPDIR
|
||||||
collecting ... collected 18 items / 15 deselected / 3 selected
|
collecting ... collected 17 items / 14 deselected / 3 selected
|
||||||
|
|
||||||
test_pytest_param_example.py::test_eval[1+7-8] PASSED [ 33%]
|
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_2+4] PASSED [ 66%]
|
||||||
test_pytest_param_example.py::test_eval[basic_6*9] XFAIL [100%]
|
test_pytest_param_example.py::test_eval[basic_6*9] XFAIL [100%]
|
||||||
|
|
||||||
=============== 2 passed, 15 deselected, 1 xfailed in 0.12s ================
|
=============== 2 passed, 14 deselected, 1 xfailed in 0.12s ================
|
||||||
|
|
||||||
As the result:
|
As the result:
|
||||||
|
|
||||||
|
|
|
@ -436,7 +436,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
|
||||||
items = [1, 2, 3]
|
items = [1, 2, 3]
|
||||||
print("items is {!r}".format(items))
|
print("items is {!r}".format(items))
|
||||||
> a, b = items.pop()
|
> a, b = items.pop()
|
||||||
E TypeError: cannot unpack non-iterable int object
|
E TypeError: 'int' object is not iterable
|
||||||
|
|
||||||
failure_demo.py:181: TypeError
|
failure_demo.py:181: TypeError
|
||||||
--------------------------- Captured stdout call ---------------------------
|
--------------------------- Captured stdout call ---------------------------
|
||||||
|
@ -516,7 +516,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
|
||||||
def test_z2_type_error(self):
|
def test_z2_type_error(self):
|
||||||
items = 3
|
items = 3
|
||||||
> a, b = items
|
> a, b = items
|
||||||
E TypeError: cannot unpack non-iterable int object
|
E TypeError: 'int' object is not iterable
|
||||||
|
|
||||||
failure_demo.py:222: TypeError
|
failure_demo.py:222: TypeError
|
||||||
______________________ TestMoreErrors.test_startswith ______________________
|
______________________ TestMoreErrors.test_startswith ______________________
|
||||||
|
|
|
@ -442,8 +442,8 @@ Now we can profile which test functions execute the slowest:
|
||||||
|
|
||||||
========================= slowest 3 test durations =========================
|
========================= slowest 3 test durations =========================
|
||||||
0.30s call test_some_are_slow.py::test_funcslow2
|
0.30s call test_some_are_slow.py::test_funcslow2
|
||||||
0.21s call test_some_are_slow.py::test_funcslow1
|
0.20s call test_some_are_slow.py::test_funcslow1
|
||||||
0.11s call test_some_are_slow.py::test_funcfast
|
0.10s call test_some_are_slow.py::test_funcfast
|
||||||
============================ 3 passed in 0.12s =============================
|
============================ 3 passed in 0.12s =============================
|
||||||
|
|
||||||
incremental testing - test steps
|
incremental testing - test steps
|
||||||
|
|
|
@ -28,7 +28,7 @@ Install ``pytest``
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ pytest --version
|
$ pytest --version
|
||||||
This is pytest version 5.x.y, imported from $PYTHON_PREFIX/lib/python3.7/site-packages/pytest.py
|
This is pytest version 5.x.y, imported from $PYTHON_PREFIX/lib/python3.6/site-packages/pytest/__init__.py
|
||||||
|
|
||||||
.. _`simpletest`:
|
.. _`simpletest`:
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,7 @@ Save time, reduce risk, and improve code health, while paying the maintainers of
|
||||||
Security
|
Security
|
||||||
^^^^^^^^
|
^^^^^^^^
|
||||||
|
|
||||||
pytest has never been associated with a security vunerability, but in any case, to report a
|
pytest has never been associated with a security vulnerability, but in any case, to report a
|
||||||
security vulnerability please use the `Tidelift security contact <https://tidelift.com/security>`_.
|
security vulnerability please use the `Tidelift security contact <https://tidelift.com/security>`_.
|
||||||
Tidelift will coordinate the fix and disclosure.
|
Tidelift will coordinate the fix and disclosure.
|
||||||
|
|
||||||
|
|
|
@ -626,16 +626,67 @@ notset = Notset()
|
||||||
|
|
||||||
|
|
||||||
def _iter_rewritable_modules(package_files):
|
def _iter_rewritable_modules(package_files):
|
||||||
|
"""
|
||||||
|
Given an iterable of file names in a source distribution, return the "names" that should
|
||||||
|
be marked for assertion rewrite (for example the package "pytest_mock/__init__.py" should
|
||||||
|
be added as "pytest_mock" in the assertion rewrite mechanism.
|
||||||
|
|
||||||
|
This function has to deal with dist-info based distributions and egg based distributions
|
||||||
|
(which are still very much in use for "editable" installs).
|
||||||
|
|
||||||
|
Here are the file names as seen in a dist-info based distribution:
|
||||||
|
|
||||||
|
pytest_mock/__init__.py
|
||||||
|
pytest_mock/_version.py
|
||||||
|
pytest_mock/plugin.py
|
||||||
|
pytest_mock.egg-info/PKG-INFO
|
||||||
|
|
||||||
|
Here are the file names as seen in an egg based distribution:
|
||||||
|
|
||||||
|
src/pytest_mock/__init__.py
|
||||||
|
src/pytest_mock/_version.py
|
||||||
|
src/pytest_mock/plugin.py
|
||||||
|
src/pytest_mock.egg-info/PKG-INFO
|
||||||
|
LICENSE
|
||||||
|
setup.py
|
||||||
|
|
||||||
|
We have to take in account those two distribution flavors in order to determine which
|
||||||
|
names should be considered for assertion rewriting.
|
||||||
|
|
||||||
|
More information:
|
||||||
|
https://github.com/pytest-dev/pytest-mock/issues/167
|
||||||
|
"""
|
||||||
|
package_files = list(package_files)
|
||||||
|
seen_some = False
|
||||||
for fn in package_files:
|
for fn in package_files:
|
||||||
is_simple_module = "/" not in fn and fn.endswith(".py")
|
is_simple_module = "/" not in fn and fn.endswith(".py")
|
||||||
is_package = fn.count("/") == 1 and fn.endswith("__init__.py")
|
is_package = fn.count("/") == 1 and fn.endswith("__init__.py")
|
||||||
if is_simple_module:
|
if is_simple_module:
|
||||||
module_name, _ = os.path.splitext(fn)
|
module_name, _ = os.path.splitext(fn)
|
||||||
yield module_name
|
# we ignore "setup.py" at the root of the distribution
|
||||||
|
if module_name != "setup":
|
||||||
|
seen_some = True
|
||||||
|
yield module_name
|
||||||
elif is_package:
|
elif is_package:
|
||||||
package_name = os.path.dirname(fn)
|
package_name = os.path.dirname(fn)
|
||||||
|
seen_some = True
|
||||||
yield package_name
|
yield package_name
|
||||||
|
|
||||||
|
if not seen_some:
|
||||||
|
# at this point we did not find any packages or modules suitable for assertion
|
||||||
|
# rewriting, so we try again by stripping the first path component (to account for
|
||||||
|
# "src" based source trees for example)
|
||||||
|
# this approach lets us have the common case continue to be fast, as egg-distributions
|
||||||
|
# are rarer
|
||||||
|
new_package_files = []
|
||||||
|
for fn in package_files:
|
||||||
|
parts = fn.split("/")
|
||||||
|
new_fn = "/".join(parts[1:])
|
||||||
|
if new_fn:
|
||||||
|
new_package_files.append(new_fn)
|
||||||
|
if new_package_files:
|
||||||
|
yield from _iter_rewritable_modules(new_package_files)
|
||||||
|
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -43,5 +43,6 @@ NODE_USE_FROM_PARENT = UnformattedWarning(
|
||||||
|
|
||||||
JUNIT_XML_DEFAULT_FAMILY = PytestDeprecationWarning(
|
JUNIT_XML_DEFAULT_FAMILY = PytestDeprecationWarning(
|
||||||
"The 'junit_family' default value will change to 'xunit2' in pytest 6.0.\n"
|
"The 'junit_family' default value will change to 'xunit2' in pytest 6.0.\n"
|
||||||
"Add 'junit_family=legacy' to your pytest.ini file to silence this warning and make your suite compatible."
|
"Add 'junit_family=xunit1' to your pytest.ini file to keep the current format "
|
||||||
|
"in future versions of pytest and silence this warning."
|
||||||
)
|
)
|
||||||
|
|
|
@ -591,6 +591,8 @@ class LogXML:
|
||||||
if report.when == "call":
|
if report.when == "call":
|
||||||
reporter.append_failure(report)
|
reporter.append_failure(report)
|
||||||
self.open_reports.append(report)
|
self.open_reports.append(report)
|
||||||
|
if not self.log_passing_tests:
|
||||||
|
reporter.write_captured_output(report)
|
||||||
else:
|
else:
|
||||||
reporter.append_error(report)
|
reporter.append_error(report)
|
||||||
elif report.skipped:
|
elif report.skipped:
|
||||||
|
|
|
@ -422,15 +422,21 @@ class TestConfigAPI:
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"names, expected",
|
"names, expected",
|
||||||
[
|
[
|
||||||
|
# dist-info based distributions root are files as will be put in PYTHONPATH
|
||||||
(["bar.py"], ["bar"]),
|
(["bar.py"], ["bar"]),
|
||||||
(["foo", "bar.py"], []),
|
(["foo/bar.py"], ["bar"]),
|
||||||
(["foo", "bar.pyc"], []),
|
(["foo/bar.pyc"], []),
|
||||||
(["foo", "__init__.py"], ["foo"]),
|
(["foo/__init__.py"], ["foo"]),
|
||||||
(["foo", "bar", "__init__.py"], []),
|
(["bar/__init__.py", "xz.py"], ["bar", "xz"]),
|
||||||
|
(["setup.py"], []),
|
||||||
|
# egg based distributions root contain the files from the dist root
|
||||||
|
(["src/bar/__init__.py"], ["bar"]),
|
||||||
|
(["src/bar/__init__.py", "setup.py"], ["bar"]),
|
||||||
|
(["source/python/bar/__init__.py", "setup.py"], ["bar"]),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_iter_rewritable_modules(self, names, expected):
|
def test_iter_rewritable_modules(self, names, expected):
|
||||||
assert list(_iter_rewritable_modules(["/".join(names)])) == expected
|
assert list(_iter_rewritable_modules(names)) == expected
|
||||||
|
|
||||||
|
|
||||||
class TestConfigFromdictargs:
|
class TestConfigFromdictargs:
|
||||||
|
|
|
@ -1477,3 +1477,45 @@ def test_logging_passing_tests_disabled_does_not_log_test_output(
|
||||||
node = dom.find_first_by_tag("testcase")
|
node = dom.find_first_by_tag("testcase")
|
||||||
assert len(node.find_by_tag("system-err")) == 0
|
assert len(node.find_by_tag("system-err")) == 0
|
||||||
assert len(node.find_by_tag("system-out")) == 0
|
assert len(node.find_by_tag("system-out")) == 0
|
||||||
|
|
||||||
|
|
||||||
|
@parametrize_families
|
||||||
|
@pytest.mark.parametrize("junit_logging", ["no", "system-out", "system-err"])
|
||||||
|
def test_logging_passing_tests_disabled_logs_output_for_failing_test_issue5430(
|
||||||
|
testdir, junit_logging, run_and_parse, xunit_family
|
||||||
|
):
|
||||||
|
testdir.makeini(
|
||||||
|
"""
|
||||||
|
[pytest]
|
||||||
|
junit_log_passing_tests=False
|
||||||
|
junit_family={family}
|
||||||
|
""".format(
|
||||||
|
family=xunit_family
|
||||||
|
)
|
||||||
|
)
|
||||||
|
testdir.makepyfile(
|
||||||
|
"""
|
||||||
|
import pytest
|
||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def test_func():
|
||||||
|
logging.warning('hello')
|
||||||
|
assert 0
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
result, dom = run_and_parse(
|
||||||
|
"-o", "junit_logging=%s" % junit_logging, family=xunit_family
|
||||||
|
)
|
||||||
|
assert result.ret == 1
|
||||||
|
node = dom.find_first_by_tag("testcase")
|
||||||
|
if junit_logging == "system-out":
|
||||||
|
assert len(node.find_by_tag("system-err")) == 0
|
||||||
|
assert len(node.find_by_tag("system-out")) == 1
|
||||||
|
elif junit_logging == "system-err":
|
||||||
|
assert len(node.find_by_tag("system-err")) == 1
|
||||||
|
assert len(node.find_by_tag("system-out")) == 0
|
||||||
|
else:
|
||||||
|
assert junit_logging == "no"
|
||||||
|
assert len(node.find_by_tag("system-err")) == 0
|
||||||
|
assert len(node.find_by_tag("system-out")) == 0
|
||||||
|
|
Loading…
Reference in New Issue