Compare commits

...

28 Commits
main ... 6.1.x

Author SHA1 Message Date
Ran Benita 1142d138e3
Merge pull request #7986 from bluetech/backport-7956
[6.1.x] Fix handling recursive symlinks
2020-11-08 16:38:33 +02:00
Ran Benita 296f468a7c
Merge pull request #7983 from bluetech/backports
[6.1.x] Two backports
2020-11-08 16:38:11 +02:00
Ran Benita 84247c4bab
Merge pull request #7984 from nicoddemus/backport-7979
[6.1.x] Merge pull request #7979 from nicoddemus/metafunc-ref
2020-11-08 16:37:49 +02:00
Ran Benita 1adbb04f02 Merge pull request #7956 from csernazs/fix-7951
Fix handling recursive symlinks

(cherry picked from commit 7fb0ea3f68)

Adjusted to pass str(path) for Python 3.5 support.
2020-10-31 22:27:02 +02:00
Bruno Oliveira 0dca7ee21a Merge pull request #7979 from nicoddemus/metafunc-ref
Add FunctionDefinition to the reference docs
2020-10-31 10:01:04 -03:00
Ran Benita 8cf0bbdf75 Merge pull request #7982 from bluetech/symlink-collect
pathlib: fix symlinked directories not followed during collection
(cherry picked from commit a14a229d1b)

Changed pytester -> testdir.
2020-10-31 14:59:59 +02:00
Ran Benita 573860d71c Merge pull request #7978 from nicoddemus/port-4.6-release-notes
Manually add the remaining 4.6.x release notes to the changelog

(cherry picked from commit dd323980f9)
2020-10-31 14:48:45 +02:00
Bruno Oliveira 1ed903e8fc
Merge pull request #7958 from pytest-dev/release-6.1.2
Prepare release 6.1.2
2020-10-28 14:21:33 -03:00
pytest bot 4e8b50ba01 Prepare release version 6.1.2 2020-10-28 11:37:31 +00:00
Bruno Oliveira cd221df8e2
Merge pull request #7955 from nicoddemus/backport-7914
[6.1.x] Increase temp dir deletion period to 3 days (#7914)
2020-10-28 08:33:01 -03:00
Vasilis Gerakaris 8c1c1ae310 Increase temp dir deletion period to 3 days (#7914)
Co-authored-by: Bruno Oliveira <nicoddemus@gmail.com>
2020-10-28 08:26:16 -03:00
Bruno Oliveira a88fe584ad
Merge pull request #7919 from nicoddemus/backport-7917
[6.1.x] ci: decrease job timeout from 6 hours to 30 minutes
2020-10-21 09:15:09 -03:00
Bruno Oliveira cd57271455 Merge pull request #7917 from bluetech/ci-timeout
ci: decrease job timeout from 6 hours to 30 minutes
2020-10-21 08:03:37 -03:00
Ran Benita 46195edc3e
Merge pull request #7918 from bluetech/backport-7915
[6.1.x] cacheprovider: fix some files in packages getting lost from --lf
2020-10-21 10:51:52 +03:00
Ran Benita 9237b5f633 Merge pull request #7915 from bluetech/fix-lf-package
cacheprovider: fix some files in packages getting lost from --lf
(cherry picked from commit a66b6b857a)

with some needed adjustments to 6.1.x.
2020-10-21 10:27:12 +03:00
Bruno Oliveira 95fd566133
Merge pull request #7867 from nicoddemus/backport-7829 2020-10-06 12:06:15 -03:00
Manuel Mariñez c93962c491 Add alias clarification to deprecation warning (#7829)
Co-authored-by: Bruno Oliveira <nicoddemus@gmail.com>
2020-10-06 11:49:13 -03:00
Bruno Oliveira dc96e485a0
Merge pull request #7861 from nicoddemus/backport-7860
[6.1.x] Update reference.rst informing the default junit_family (#7860)
2020-10-05 15:24:42 -03:00
William Jamir Silva 7ccfc39f15 Update reference.rst informing the default junit_family (#7860)
Co-authored-by: Bruno Oliveira <nicoddemus@gmail.com>
2020-10-05 14:05:16 -03:00
Ran Benita 69d903260d
Merge pull request #7849 from pytest-dev/release-6.1.1
Prepare release 6.1.1
2020-10-03 22:37:28 +03:00
pytest bot 0ad20b533f Prepare release version 6.1.1 2020-10-03 19:05:02 +00:00
Ran Benita 9df5267648
Merge pull request #7842 from bluetech/backport-7817
[6.1.x] terminal: fix crash in header reporting when absolute testpaths is used
2020-10-03 13:21:16 +03:00
Ran Benita 1521849c87 terminal: fix crash in header reporting when absolute testpaths is used
Regressed in 6.1.0 in 62e249a1f9.
The `x` is an `str` but is expected to be a `pathlib.Path`. Not caught
by mypy because `config.getini()` returns `Any`.

Fix by just removing the `bestrelpath` call:

- testpaths are always relative to the rootdir, it thus would be very
  unusual to specify an absolute path there.

- The code was wrong even before the regression: `py.path.local`'s
  `bestrelpath` function expects a `py.path.local`, not an `str`. But it
  had some weird `try ... except AttributeError` fallback which just
  returns the argument, i.e. it was a no-op. So there is no behavior
  change.

- It seems reasonable to me to just print the full path if that's what
  the ini specifies.

(cherry picked from commit 61f80a783a)
2020-10-03 13:01:19 +03:00
Ran Benita bcb94c4c8b
Merge pull request #7822 from bluetech/backport-7813
[6.1.x] findpaths: fix regression causing incorrect rootdir to be determined
2020-09-30 15:08:56 +03:00
Ran Benita 0f83df4f55 Merge pull request #7813 from bluetech/findpaths-confusion
findpaths: fix regression causing incorrect rootdir to be determined
(cherry picked from commit b250c9d615)
2020-09-30 13:22:00 +03:00
Ran Benita 330caac2ca
[6.1.x] Improve docs about plugin discovery/loading at startup (#7803) 2020-09-27 11:14:54 -03:00
Ran Benita 08a1ab3a8a
Merge pull request #7797 from pytest-dev/release-6.1.0
Prepare release 6.1.0
2020-09-26 21:09:34 +03:00
pytest bot 868bc003ec Prepare release version 6.1.0 2020-09-26 17:32:18 +00:00
50 changed files with 585 additions and 150 deletions

View File

@ -16,6 +16,7 @@ on:
jobs: jobs:
build: build:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
timeout-minutes: 30
strategy: strategy:
fail-fast: false fail-fast: false
@ -187,6 +188,7 @@ jobs:
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') && github.repository == 'pytest-dev/pytest' if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') && github.repository == 'pytest-dev/pytest'
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 30
needs: [build] needs: [build]

View File

@ -310,3 +310,4 @@ Xuecong Liao
Yoav Caspi Yoav Caspi
Zac Hatfield-Dodds Zac Hatfield-Dodds
Zoltán Máté Zoltán Máté
Zsolt Cserna

View File

@ -1 +0,0 @@
Removed faq.rst and its reference in contents.rst.

View File

@ -1,20 +0,0 @@
Fixed error when overwriting a parametrized fixture, while also reusing the super fixture value.
.. code-block:: python
# conftest.py
import pytest
@pytest.fixture(params=[1, 2])
def foo(request):
return request.param
# test_foo.py
import pytest
@pytest.fixture
def foo(foo):
return foo * 2

View File

@ -1,3 +0,0 @@
Fixed an internal error crash with ``IndexError: list index out of range`` when
collecting a module which starts with a decorated function, the decorator
raises, and assertion rewriting is enabled.

View File

@ -1,18 +0,0 @@
As per our policy, the following features which have been deprecated in the 5.X series are now
removed:
* The ``funcargnames`` read-only property of ``FixtureRequest``, ``Metafunc``, and ``Function`` classes. Use ``fixturenames`` attribute.
* ``@pytest.fixture`` no longer supports positional arguments, pass all arguments by keyword instead.
* Direct construction of ``Node`` subclasses now raise an error, use ``from_parent`` instead.
* The default value for ``junit_family`` has changed to ``xunit2``. If you require the old format, add ``junit_family=xunit1`` to your configuration file.
* The ``TerminalReporter`` no longer has a ``writer`` attribute. Plugin authors may use the public functions of the ``TerminalReporter`` instead of accessing the ``TerminalWriter`` object directly.
* The ``--result-log`` option has been removed. Users are recommended to use the `pytest-reportlog <https://github.com/pytest-dev/pytest-reportlog>`__ plugin instead.
For more information consult
`Deprecations and Removals <https://docs.pytest.org/en/stable/deprecations.html>`__ in the docs.

View File

@ -1,3 +0,0 @@
Internal pytest warnings issued during the early stages of initialization are now properly handled and can filtered through :confval:`filterwarnings` or ``--pythonwarnings/-W``.
This also fixes a number of long standing issues: `#2891 <https://github.com/pytest-dev/pytest/issues/2891>`__, `#7620 <https://github.com/pytest-dev/pytest/issues/7620>`__, `#7426 <https://github.com/pytest-dev/pytest/issues/7426>`__.

View File

@ -1 +0,0 @@
The ``pytest.collect`` module is deprecated: all its names can be imported from ``pytest`` directly.

View File

@ -1,6 +0,0 @@
The ``pytest._fillfuncargs`` function is deprecated. This function was kept
for backward compatibility with an older plugin.
It's functionality is not meant to be used directly, but if you must replace
it, use `function._request._fillfixtures()` instead, though note this is not
a public API and may break in the future.

View File

@ -1,5 +0,0 @@
The special ``-k '-expr'`` syntax to ``-k`` is deprecated. Use ``-k 'not expr'``
instead.
The special ``-k 'expr:'`` syntax to ``-k`` is deprecated. Please open an issue
if you use this and want a replacement.

View File

@ -1,2 +0,0 @@
The :func:`pytest_warning_captured <_pytest.hookspec.pytest_warning_captured>` hook is deprecated in favor
of :func:`pytest_warning_recorded <_pytest.hookspec.pytest_warning_recorded>`, and will be removed in a future version.

View File

@ -1,3 +0,0 @@
The internal ``junitxml`` plugin has rewritten to use ``xml.etree.ElementTree``.
The order of attributes in XML elements might differ. Some unneeded escaping is
no longer performed.

View File

@ -1 +0,0 @@
When a plugin listed in ``required_plugins`` is missing or an unknown config key is used with ``--strict-config``, a simple error message is now shown instead of a stacktrace.

View File

@ -1 +0,0 @@
The dependency on the ``more-itertools`` package has been removed.

View File

@ -1 +0,0 @@
pylint shouldn't complain anymore about unimplemented abstract methods when inheriting from :ref:`File <non-python tests>`.

View File

@ -1 +0,0 @@
Fixed test collection when a full path without a drive letter was passed to pytest on Windows (for example ``\projects\tests\test.py`` instead of ``c:\projects\tests\pytest.py``).

View File

@ -1,2 +0,0 @@
The result type of :meth:`capfd.readouterr() <_pytest.capture.CaptureFixture.readouterr>` (and similar) is no longer a namedtuple,
but should behave like one in all respects. This was done for technical reasons.

View File

@ -1 +0,0 @@
Fix handling of command-line options that appear as paths but trigger an OS-level syntax error on Windows, such as the options used internally by ``pytest-xdist``.

View File

@ -1,3 +0,0 @@
The ``gethookproxy()`` and ``isinitpath()`` methods of ``FSCollector`` and ``Package`` are deprecated;
use ``self.session.gethookproxy()`` and ``self.session.isinitpath()`` instead.
This should work on all pytest versions.

View File

@ -1 +0,0 @@
New ``--durations-min`` command-line flag controls the minimal duration for inclusion in the slowest list of tests shown by ``--durations``. Previously this was hard-coded to ``0.005s``.

View File

@ -1,6 +0,0 @@
When collecting tests, pytest finds test classes and functions by examining the
attributes of python objects (modules, classes and instances). To speed up this
process, pytest now ignores builtin attributes (like ``__class__``,
``__delattr__`` and ``__new__``) without consulting the :confval:`python_classes` and
:confval:`python_functions` configuration options and without passing them to plugins
using the :func:`pytest_pycollect_makeitem <_pytest.hookspec.pytest_pycollect_makeitem>` hook.

View File

@ -1,3 +0,0 @@
Added two new attributes :attr:`rootpath <_pytest.config.Config.rootpath>` and :attr:`inipath <_pytest.config.Config.inipath>` to :class:`Config <_pytest.config.Config>`.
These attributes are :class:`pathlib.Path` versions of the existing :attr:`rootdir <_pytest.config.Config.rootdir>` and :attr:`inifile <_pytest.config.Config.inifile>` attributes,
and should be preferred over them when possible.

View File

@ -1 +0,0 @@
Fixed INTERNALERROR when accessing locals / globals with faulty ``exec``.

View File

@ -1,3 +0,0 @@
Public classes which are not designed to be inherited from are now marked `@final <https://docs.python.org/3/library/typing.html#typing.final>`_.
Code which inherits from these classes will trigger a type-checking (e.g. mypy) error, but will still work in runtime.
Currently the ``final`` designation does not appear in the API Reference but hopefully will in the future.

View File

@ -0,0 +1 @@
Fixed handling of recursive symlinks when collecting tests.

View File

@ -0,0 +1 @@
Fixed symlinked directories not being followed during collection. Regressed in pytest 6.1.0.

View File

@ -6,6 +6,9 @@ Release announcements
:maxdepth: 2 :maxdepth: 2
release-6.1.2
release-6.1.1
release-6.1.0
release-6.0.2 release-6.0.2
release-6.0.1 release-6.0.1
release-6.0.0 release-6.0.0

View File

@ -0,0 +1,44 @@
pytest-6.1.0
=======================================
The pytest team is proud to announce the 6.1.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:
* Anthony Sottile
* Bruno Oliveira
* C. Titus Brown
* Drew Devereux
* Faris A Chugthai
* Florian Bruhin
* Hugo van Kemenade
* Hynek Schlawack
* Joseph Lucas
* Kamran Ahmad
* Mattreex
* Maximilian Cosmo Sitter
* Ran Benita
* Rüdiger Busche
* Sam Estep
* Sorin Sbarnea
* Thomas Grainger
* Vipul Kumar
* Yutaro Ikeda
* hp310780
Happy testing,
The pytest Development Team

View File

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

View File

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

View File

@ -23,7 +23,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
cache.get(key, default) cache.get(key, default)
cache.set(key, value) cache.set(key, value)
Keys must be a ``/`` separated value, where the first part is usually the Keys must be ``/`` separated strings, where the first part is usually the
name of your plugin or application to avoid clashes with other cache users. name of your plugin or application to avoid clashes with other cache users.
Values can be any object handled by the json stdlib module. Values can be any object handled by the json stdlib module.
@ -57,7 +57,8 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
``out`` and ``err`` will be ``byte`` objects. ``out`` and ``err`` will be ``byte`` objects.
doctest_namespace [session scope] doctest_namespace [session scope]
Fixture that returns a :py:class:`dict` that will be injected into the namespace of doctests. Fixture that returns a :py:class:`dict` that will be injected into the
namespace of doctests.
pytestconfig [session scope] pytestconfig [session scope]
Session-scoped fixture that returns the :class:`_pytest.config.Config` object. Session-scoped fixture that returns the :class:`_pytest.config.Config` object.
@ -89,8 +90,10 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
automatically XML-encoded. automatically XML-encoded.
record_testsuite_property [session scope] record_testsuite_property [session scope]
Records a new ``<property>`` tag as child of the root ``<testsuite>``. This is suitable to Record a new ``<property>`` tag as child of the root ``<testsuite>``.
writing global information regarding the entire test suite, and is compatible with ``xunit2`` JUnit family.
This is suitable to writing global information regarding the entire test
suite, and is compatible with ``xunit2`` JUnit family.
This is a ``session``-scoped fixture which is called with ``(name, value)``. Example: This is a ``session``-scoped fixture which is called with ``(name, value)``. Example:
@ -102,6 +105,12 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
``name`` must be a string, ``value`` will be converted to a string and properly xml-escaped. ``name`` must be a string, ``value`` will be converted to a string and properly xml-escaped.
.. warning::
Currently this fixture **does not work** with the
`pytest-xdist <https://github.com/pytest-dev/pytest-xdist>`__ plugin. See issue
`#7767 <https://github.com/pytest-dev/pytest/issues/7767>`__ for details.
caplog caplog
Access and control log capturing. Access and control log capturing.
@ -114,8 +123,10 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
* caplog.clear() -> clear captured records and formatted log output string * caplog.clear() -> clear captured records and formatted log output string
monkeypatch monkeypatch
The returned ``monkeypatch`` fixture provides these A convenient fixture for monkey-patching.
helper methods to modify objects, dictionaries or os.environ::
The fixture provides these methods to modify objects, dictionaries or
os.environ::
monkeypatch.setattr(obj, name, value, raising=True) monkeypatch.setattr(obj, name, value, raising=True)
monkeypatch.delattr(obj, name, raising=True) monkeypatch.delattr(obj, name, raising=True)
@ -126,10 +137,9 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
monkeypatch.syspath_prepend(path) monkeypatch.syspath_prepend(path)
monkeypatch.chdir(path) monkeypatch.chdir(path)
All modifications will be undone after the requesting All modifications will be undone after the requesting test function or
test function or fixture has finished. The ``raising`` fixture has finished. The ``raising`` parameter determines if a KeyError
parameter determines if a KeyError or AttributeError or AttributeError will be raised if the set/deletion operation has no target.
will be raised if the set/deletion operation has no target.
recwarn recwarn
Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions. Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions.
@ -140,30 +150,28 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
tmpdir_factory [session scope] tmpdir_factory [session scope]
Return a :class:`_pytest.tmpdir.TempdirFactory` instance for the test session. Return a :class:`_pytest.tmpdir.TempdirFactory` instance for the test session.
tmp_path_factory [session scope] tmp_path_factory [session scope]
Return a :class:`_pytest.tmpdir.TempPathFactory` instance for the test session. Return a :class:`_pytest.tmpdir.TempPathFactory` instance for the test session.
tmpdir tmpdir
Return a temporary directory path object Return a temporary directory path object which is unique to each test
which is unique to each test function invocation, function invocation, created as a sub directory of the base temporary
created as a sub directory of the base temporary directory.
directory. The returned object is a `py.path.local`_
path object. The returned object is a `py.path.local`_ path object.
.. _`py.path.local`: https://py.readthedocs.io/en/latest/path.html .. _`py.path.local`: https://py.readthedocs.io/en/latest/path.html
tmp_path tmp_path
Return a temporary directory path object Return a temporary directory path object which is unique to each test
which is unique to each test function invocation, function invocation, created as a sub directory of the base temporary
created as a sub directory of the base temporary directory.
directory. The returned object is a :class:`pathlib.Path`
object. The returned object is a :class:`pathlib.Path` object.
.. note:: .. note::
in python < 3.6 this is a pathlib2.Path In python < 3.6 this is a pathlib2.Path.
no tests ran in 0.12s no tests ran in 0.12s

View File

@ -28,6 +28,197 @@ with advance notice in the **Deprecations** section of releases.
.. towncrier release notes start .. towncrier release notes start
pytest 6.1.2 (2020-10-28)
=========================
Bug Fixes
---------
- `#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 `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.
Improved Documentation
----------------------
- `#7815 <https://github.com/pytest-dev/pytest/issues/7815>`_: Improve deprecation warning message for ``pytest._fillfuncargs()``.
pytest 6.1.1 (2020-10-03)
=========================
Bug Fixes
---------
- `#7807 <https://github.com/pytest-dev/pytest/issues/7807>`_: Fixed regression in pytest 6.1.0 causing incorrect rootdir to be determined in some non-trivial cases where parent directories have config files as well.
- `#7814 <https://github.com/pytest-dev/pytest/issues/7814>`_: Fixed crash in header reporting when :confval:`testpaths` is used and contains absolute paths (regression in 6.1.0).
pytest 6.1.0 (2020-09-26)
=========================
Breaking Changes
----------------
- `#5585 <https://github.com/pytest-dev/pytest/issues/5585>`_: As per our policy, the following features which have been deprecated in the 5.X series are now
removed:
* The ``funcargnames`` read-only property of ``FixtureRequest``, ``Metafunc``, and ``Function`` classes. Use ``fixturenames`` attribute.
* ``@pytest.fixture`` no longer supports positional arguments, pass all arguments by keyword instead.
* Direct construction of ``Node`` subclasses now raise an error, use ``from_parent`` instead.
* The default value for ``junit_family`` has changed to ``xunit2``. If you require the old format, add ``junit_family=xunit1`` to your configuration file.
* The ``TerminalReporter`` no longer has a ``writer`` attribute. Plugin authors may use the public functions of the ``TerminalReporter`` instead of accessing the ``TerminalWriter`` object directly.
* The ``--result-log`` option has been removed. Users are recommended to use the `pytest-reportlog <https://github.com/pytest-dev/pytest-reportlog>`__ plugin instead.
For more information consult
`Deprecations and Removals <https://docs.pytest.org/en/stable/deprecations.html>`__ in the docs.
Deprecations
------------
- `#6981 <https://github.com/pytest-dev/pytest/issues/6981>`_: The ``pytest.collect`` module is deprecated: all its names can be imported from ``pytest`` directly.
- `#7097 <https://github.com/pytest-dev/pytest/issues/7097>`_: The ``pytest._fillfuncargs`` function is deprecated. This function was kept
for backward compatibility with an older plugin.
It's functionality is not meant to be used directly, but if you must replace
it, use `function._request._fillfixtures()` instead, though note this is not
a public API and may break in the future.
- `#7210 <https://github.com/pytest-dev/pytest/issues/7210>`_: The special ``-k '-expr'`` syntax to ``-k`` is deprecated. Use ``-k 'not expr'``
instead.
The special ``-k 'expr:'`` syntax to ``-k`` is deprecated. Please open an issue
if you use this and want a replacement.
- `#7255 <https://github.com/pytest-dev/pytest/issues/7255>`_: The :func:`pytest_warning_captured <_pytest.hookspec.pytest_warning_captured>` hook is deprecated in favor
of :func:`pytest_warning_recorded <_pytest.hookspec.pytest_warning_recorded>`, and will be removed in a future version.
- `#7648 <https://github.com/pytest-dev/pytest/issues/7648>`_: The ``gethookproxy()`` and ``isinitpath()`` methods of ``FSCollector`` and ``Package`` are deprecated;
use ``self.session.gethookproxy()`` and ``self.session.isinitpath()`` instead.
This should work on all pytest versions.
Features
--------
- `#7667 <https://github.com/pytest-dev/pytest/issues/7667>`_: New ``--durations-min`` command-line flag controls the minimal duration for inclusion in the slowest list of tests shown by ``--durations``. Previously this was hard-coded to ``0.005s``.
Improvements
------------
- `#6681 <https://github.com/pytest-dev/pytest/issues/6681>`_: Internal pytest warnings issued during the early stages of initialization are now properly handled and can filtered through :confval:`filterwarnings` or ``--pythonwarnings/-W``.
This also fixes a number of long standing issues: `#2891 <https://github.com/pytest-dev/pytest/issues/2891>`__, `#7620 <https://github.com/pytest-dev/pytest/issues/7620>`__, `#7426 <https://github.com/pytest-dev/pytest/issues/7426>`__.
- `#7572 <https://github.com/pytest-dev/pytest/issues/7572>`_: When a plugin listed in ``required_plugins`` is missing or an unknown config key is used with ``--strict-config``, a simple error message is now shown instead of a stacktrace.
- `#7685 <https://github.com/pytest-dev/pytest/issues/7685>`_: Added two new attributes :attr:`rootpath <_pytest.config.Config.rootpath>` and :attr:`inipath <_pytest.config.Config.inipath>` to :class:`Config <_pytest.config.Config>`.
These attributes are :class:`pathlib.Path` versions of the existing :attr:`rootdir <_pytest.config.Config.rootdir>` and :attr:`inifile <_pytest.config.Config.inifile>` attributes,
and should be preferred over them when possible.
- `#7780 <https://github.com/pytest-dev/pytest/issues/7780>`_: Public classes which are not designed to be inherited from are now marked `@final <https://docs.python.org/3/library/typing.html#typing.final>`_.
Code which inherits from these classes will trigger a type-checking (e.g. mypy) error, but will still work in runtime.
Currently the ``final`` designation does not appear in the API Reference but hopefully will in the future.
Bug Fixes
---------
- `#1953 <https://github.com/pytest-dev/pytest/issues/1953>`_: Fixed error when overwriting a parametrized fixture, while also reusing the super fixture value.
.. code-block:: python
# conftest.py
import pytest
@pytest.fixture(params=[1, 2])
def foo(request):
return request.param
# test_foo.py
import pytest
@pytest.fixture
def foo(foo):
return foo * 2
- `#4984 <https://github.com/pytest-dev/pytest/issues/4984>`_: Fixed an internal error crash with ``IndexError: list index out of range`` when
collecting a module which starts with a decorated function, the decorator
raises, and assertion rewriting is enabled.
- `#7591 <https://github.com/pytest-dev/pytest/issues/7591>`_: pylint shouldn't complain anymore about unimplemented abstract methods when inheriting from :ref:`File <non-python tests>`.
- `#7628 <https://github.com/pytest-dev/pytest/issues/7628>`_: Fixed test collection when a full path without a drive letter was passed to pytest on Windows (for example ``\projects\tests\test.py`` instead of ``c:\projects\tests\pytest.py``).
- `#7638 <https://github.com/pytest-dev/pytest/issues/7638>`_: Fix handling of command-line options that appear as paths but trigger an OS-level syntax error on Windows, such as the options used internally by ``pytest-xdist``.
- `#7742 <https://github.com/pytest-dev/pytest/issues/7742>`_: Fixed INTERNALERROR when accessing locals / globals with faulty ``exec``.
Improved Documentation
----------------------
- `#1477 <https://github.com/pytest-dev/pytest/issues/1477>`_: Removed faq.rst and its reference in contents.rst.
Trivial/Internal Changes
------------------------
- `#7536 <https://github.com/pytest-dev/pytest/issues/7536>`_: The internal ``junitxml`` plugin has rewritten to use ``xml.etree.ElementTree``.
The order of attributes in XML elements might differ. Some unneeded escaping is
no longer performed.
- `#7587 <https://github.com/pytest-dev/pytest/issues/7587>`_: The dependency on the ``more-itertools`` package has been removed.
- `#7631 <https://github.com/pytest-dev/pytest/issues/7631>`_: The result type of :meth:`capfd.readouterr() <_pytest.capture.CaptureFixture.readouterr>` (and similar) is no longer a namedtuple,
but should behave like one in all respects. This was done for technical reasons.
- `#7671 <https://github.com/pytest-dev/pytest/issues/7671>`_: When collecting tests, pytest finds test classes and functions by examining the
attributes of python objects (modules, classes and instances). To speed up this
process, pytest now ignores builtin attributes (like ``__class__``,
``__delattr__`` and ``__new__``) without consulting the :confval:`python_classes` and
:confval:`python_functions` configuration options and without passing them to plugins
using the :func:`pytest_pycollect_makeitem <_pytest.hookspec.pytest_pycollect_makeitem>` hook.
pytest 6.0.2 (2020-09-04) pytest 6.0.2 (2020-09-04)
========================= =========================
@ -1682,6 +1873,44 @@ 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.11 (2020-06-04)
==========================
Bug Fixes
---------
- `#6334 <https://github.com/pytest-dev/pytest/issues/6334>`_: Fix summary entries appearing twice when ``f/F`` and ``s/S`` report chars were used at the same time in the ``-r`` command-line option (for example ``-rFf``).
The upper case variants were never documented and the preferred form should be the lower case.
- `#7310 <https://github.com/pytest-dev/pytest/issues/7310>`_: Fix ``UnboundLocalError: local variable 'letter' referenced before
assignment`` in ``_pytest.terminal.pytest_report_teststatus()``
when plugins return report objects in an unconventional state.
This was making ``pytest_report_teststatus()`` skip
entering if-block branches that declare the ``letter`` variable.
The fix was to set the initial value of the ``letter`` before
the if-block cascade so that it always has a value.
pytest 4.6.10 (2020-05-08)
==========================
Features
--------
- `#6870 <https://github.com/pytest-dev/pytest/issues/6870>`_: New ``Config.invocation_args`` attribute containing the unchanged arguments passed to ``pytest.main()``.
Remark: while this is technically a new feature and according to our `policy <https://docs.pytest.org/en/latest/py27-py34-deprecation.html#what-goes-into-4-6-x-releases>`_ it should not have been backported, we have opened an exception in this particular case because it fixes a serious interaction with ``pytest-xdist``, so it can also be considered a bugfix.
Trivial/Internal Changes
------------------------
- `#6404 <https://github.com/pytest-dev/pytest/issues/6404>`_: Remove usage of ``parser`` module, deprecated in Python 3.9.
pytest 4.6.9 (2020-01-04) pytest 4.6.9 (2020-01-04)
========================= =========================

View File

@ -28,7 +28,7 @@ Install ``pytest``
.. code-block:: bash .. code-block:: bash
$ pytest --version $ pytest --version
pytest 6.0.2 pytest 6.1.2
.. _`simpletest`: .. _`simpletest`:

View File

@ -816,6 +816,13 @@ Function
:members: :members:
:show-inheritance: :show-inheritance:
FunctionDefinition
~~~~~~~~~~~~~~~~~~
.. autoclass:: _pytest.python.FunctionDefinition()
:members:
:show-inheritance:
Item Item
~~~~ ~~~~
@ -1236,12 +1243,13 @@ passed multiple times. The expected format is ``name=value``. For example::
.. confval:: junit_family .. confval:: junit_family
.. versionadded:: 4.2 .. versionadded:: 4.2
.. versionchanged:: 6.1
Default changed to ``xunit2``.
Configures the format of the generated JUnit XML file. The possible options are: Configures the format of the generated JUnit XML file. The possible options are:
* ``xunit1`` (or ``legacy``): produces old style output, compatible with the xunit 1.0 format. **This is the default**. * ``xunit1`` (or ``legacy``): produces old style output, compatible with the xunit 1.0 format.
* ``xunit2``: produces `xunit 2.0 style output <https://github.com/jenkinsci/xunit-plugin/blob/xunit-2.3.2/src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd>`__, * ``xunit2``: produces `xunit 2.0 style output <https://github.com/jenkinsci/xunit-plugin/blob/xunit-2.3.2/src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd>`__, which should be more compatible with latest Jenkins versions. **This is the default**.
which should be more compatible with latest Jenkins versions.
.. code-block:: ini .. code-block:: ini

View File

@ -33,26 +33,34 @@ Plugin discovery order at tool startup
``pytest`` loads plugin modules at tool startup in the following way: ``pytest`` loads plugin modules at tool startup in the following way:
* by loading all builtin plugins 1. by scanning the command line for the ``-p no:name`` option
and *blocking* that plugin from being loaded (even builtin plugins can
be blocked this way). This happens before normal command-line parsing.
* by loading all plugins registered through `setuptools entry points`_. 2. by loading all builtin plugins.
* by pre-scanning the command line for the ``-p name`` option 3. by scanning the command line for the ``-p name`` option
and loading the specified plugin before actual command line parsing. and loading the specified plugin. This happens before normal command-line parsing.
* by loading all :file:`conftest.py` files as inferred by the command line 4. by loading all plugins registered through `setuptools entry points`_.
invocation:
- if no test paths are specified use current dir as a test path 5. by loading all plugins specified through the :envvar:`PYTEST_PLUGINS` environment variable.
- if exists, load ``conftest.py`` and ``test*/conftest.py`` relative
to the directory part of the first test path.
Note that pytest does not find ``conftest.py`` files in deeper nested 6. by loading all :file:`conftest.py` files as inferred by the command line
sub directories at tool startup. It is usually a good idea to keep invocation:
your ``conftest.py`` file in the top level test or project root directory.
* by recursively loading all plugins specified by the - if no test paths are specified, use the current dir as a test path
:globalvar:`pytest_plugins` variable in ``conftest.py`` files - if exists, load ``conftest.py`` and ``test*/conftest.py`` relative
to the directory part of the first test path. After the ``conftest.py``
file is loaded, load all plugins specified in its
:globalvar:`pytest_plugins` variable if present.
Note that pytest does not find ``conftest.py`` files in deeper nested
sub directories at tool startup. It is usually a good idea to keep
your ``conftest.py`` file in the top level test or project root directory.
7. by recursively loading all plugins specified by the
:globalvar:`pytest_plugins` variable in ``conftest.py`` files.
.. _`pytest/plugin`: http://bitbucket.org/pytest-dev/pytest/src/tip/pytest/plugin/ .. _`pytest/plugin`: http://bitbucket.org/pytest-dev/pytest/src/tip/pytest/plugin/

View File

@ -29,6 +29,7 @@ from _pytest.config.argparsing import Parser
from _pytest.fixtures import FixtureRequest from _pytest.fixtures import FixtureRequest
from _pytest.main import Session from _pytest.main import Session
from _pytest.python import Module from _pytest.python import Module
from _pytest.python import Package
from _pytest.reports import TestReport from _pytest.reports import TestReport
@ -233,7 +234,10 @@ class LFPluginCollSkipfiles:
def pytest_make_collect_report( def pytest_make_collect_report(
self, collector: nodes.Collector self, collector: nodes.Collector
) -> Optional[CollectReport]: ) -> Optional[CollectReport]:
if isinstance(collector, Module): # Packages are Modules, but _last_failed_paths only contains
# test-bearing paths and doesn't try to include the paths of their
# packages, so don't filter them.
if isinstance(collector, Module) and not isinstance(collector, Package):
if Path(str(collector.fspath)) not in self.lfplugin._last_failed_paths: if Path(str(collector.fspath)) not in self.lfplugin._last_failed_paths:
self.lfplugin._skipped_files += 1 self.lfplugin._skipped_files += 1

View File

@ -1,4 +1,3 @@
import itertools
import os import os
from typing import Dict from typing import Dict
from typing import Iterable from typing import Iterable
@ -100,7 +99,7 @@ def locate_config(
args = [Path.cwd()] args = [Path.cwd()]
for arg in args: for arg in args:
argpath = absolutepath(arg) argpath = absolutepath(arg)
for base in itertools.chain((argpath,), reversed(argpath.parents)): for base in (argpath, *argpath.parents):
for config_name in config_names: for config_name in config_names:
p = base / config_name p = base / config_name
if p.is_file(): if p.is_file():
@ -184,9 +183,7 @@ def determine_setup(
ancestor = get_common_ancestor(dirs) ancestor = get_common_ancestor(dirs)
rootdir, inipath, inicfg = locate_config([ancestor]) rootdir, inipath, inicfg = locate_config([ancestor])
if rootdir is None and rootdir_cmd_arg is None: if rootdir is None and rootdir_cmd_arg is None:
for possible_rootdir in itertools.chain( for possible_rootdir in (ancestor, *ancestor.parents):
(ancestor,), reversed(ancestor.parents)
):
if (possible_rootdir / "setup.py").is_file(): if (possible_rootdir / "setup.py").is_file():
rootdir = possible_rootdir rootdir = possible_rootdir
break break

View File

@ -20,9 +20,10 @@ DEPRECATED_EXTERNAL_PLUGINS = {
} }
FILLFUNCARGS = PytestDeprecationWarning( FILLFUNCARGS = UnformattedWarning(
"The `_fillfuncargs` function is deprecated, use " PytestDeprecationWarning,
"function._request._fillfixtures() instead if you cannot avoid reaching into internals." "{name} is deprecated, use "
"function._request._fillfixtures() instead if you cannot avoid reaching into internals.",
) )
PYTEST_COLLECT_MODULE = UnformattedWarning( PYTEST_COLLECT_MODULE = UnformattedWarning(

View File

@ -339,9 +339,22 @@ def reorder_items_atscope(
return items_done return items_done
def _fillfuncargs(function: "Function") -> None:
"""Fill missing fixtures for a test function, old public API (deprecated)."""
warnings.warn(FILLFUNCARGS.format(name="pytest._fillfuncargs()"), stacklevel=2)
_fill_fixtures_impl(function)
def fillfixtures(function: "Function") -> None: def fillfixtures(function: "Function") -> None:
"""Fill missing funcargs for a test function.""" """Fill missing fixtures for a test function (deprecated)."""
warnings.warn(FILLFUNCARGS, stacklevel=2) warnings.warn(
FILLFUNCARGS.format(name="_pytest.fixtures.fillfixtures()"), stacklevel=2
)
_fill_fixtures_impl(function)
def _fill_fixtures_impl(function: "Function") -> None:
"""Internal implementation to fill fixtures on the given function object."""
try: try:
request = function._request request = function._request
except AttributeError: except AttributeError:

View File

@ -9,6 +9,10 @@ import sys
import uuid import uuid
import warnings import warnings
from enum import Enum from enum import Enum
from errno import EBADF
from errno import ELOOP
from errno import ENOENT
from errno import ENOTDIR
from functools import partial from functools import partial
from os.path import expanduser from os.path import expanduser
from os.path import expandvars from os.path import expandvars
@ -38,11 +42,29 @@ else:
__all__ = ["Path", "PurePath"] __all__ = ["Path", "PurePath"]
LOCK_TIMEOUT = 60 * 60 * 3 LOCK_TIMEOUT = 60 * 60 * 24 * 3
_AnyPurePath = TypeVar("_AnyPurePath", bound=PurePath) _AnyPurePath = TypeVar("_AnyPurePath", bound=PurePath)
# The following function, variables and comments were
# copied from cpython 3.9 Lib/pathlib.py file.
# EBADF - guard against macOS `stat` throwing EBADF
_IGNORED_ERRORS = (ENOENT, ENOTDIR, EBADF, ELOOP)
_IGNORED_WINERRORS = (
21, # ERROR_NOT_READY - drive exists but is not accessible
1921, # ERROR_CANT_RESOLVE_FILENAME - fix for broken symlink pointing to itself
)
def _ignore_error(exception):
return (
getattr(exception, "errno", None) in _IGNORED_ERRORS
or getattr(exception, "winerror", None) in _IGNORED_WINERRORS
)
def get_lock_path(path: _AnyPurePath) -> _AnyPurePath: def get_lock_path(path: _AnyPurePath) -> _AnyPurePath:
return path.joinpath(".lock") return path.joinpath(".lock")
@ -563,10 +585,25 @@ def visit(
Entries at each directory level are sorted. Entries at each directory level are sorted.
""" """
entries = sorted(os.scandir(path), key=lambda entry: entry.name)
# Skip entries with symlink loops and other brokenness, so the caller doesn't
# have to deal with it.
entries = []
for entry in os.scandir(path):
try:
entry.is_file()
except OSError as err:
if _ignore_error(err):
continue
raise
entries.append(entry)
entries.sort(key=lambda entry: entry.name)
yield from entries yield from entries
for entry in entries: for entry in entries:
if entry.is_dir(follow_symlinks=False) and recurse(entry): if entry.is_dir() and recurse(entry):
yield from visit(entry.path, recurse) yield from visit(entry.path, recurse)

View File

@ -943,6 +943,7 @@ class Metafunc:
cls=None, cls=None,
module=None, module=None,
) -> None: ) -> None:
#: Access to the underlying :class:`_pytest.python.FunctionDefinition`.
self.definition = definition self.definition = definition
#: Access to the :class:`_pytest.config.Config` object for the test session. #: Access to the :class:`_pytest.config.Config` object for the test session.
@ -1664,10 +1665,12 @@ class Function(PyobjMixin, nodes.Item):
class FunctionDefinition(Function): class FunctionDefinition(Function):
"""Internal hack until we get actual definition nodes instead of the """
crappy metafunc hack.""" This class is a step gap solution until we evolve to have actual function definition nodes
and manage to get rid of ``metafunc``.
"""
def runtest(self) -> None: def runtest(self) -> None:
raise RuntimeError("function definitions are not supposed to be used") raise RuntimeError("function definitions are not supposed to be run as tests")
setup = runtest setup = runtest

View File

@ -718,10 +718,10 @@ class TerminalReporter:
if config.inipath: if config.inipath:
line += ", configfile: " + bestrelpath(config.rootpath, config.inipath) line += ", configfile: " + bestrelpath(config.rootpath, config.inipath)
testpaths = config.getini("testpaths") testpaths = config.getini("testpaths") # type: List[str]
if testpaths and config.args == testpaths: if testpaths and config.args == testpaths:
rel_paths = [bestrelpath(config.rootpath, x) for x in testpaths] line += ", testpaths: {}".format(", ".join(testpaths))
line += ", testpaths: {}".format(", ".join(rel_paths))
result = [line] result = [line]
plugininfo = config.pluginmanager.list_plugin_distinfo() plugininfo = config.pluginmanager.list_plugin_distinfo()

View File

@ -11,7 +11,7 @@ from _pytest.config import hookspec
from _pytest.config import main from _pytest.config import main
from _pytest.config import UsageError from _pytest.config import UsageError
from _pytest.debugging import pytestPDB as __pytestPDB from _pytest.debugging import pytestPDB as __pytestPDB
from _pytest.fixtures import fillfixtures as _fillfuncargs from _pytest.fixtures import _fillfuncargs
from _pytest.fixtures import fixture from _pytest.fixtures import fixture
from _pytest.fixtures import FixtureLookupError from _pytest.fixtures import FixtureLookupError
from _pytest.fixtures import yield_fixture from _pytest.fixtures import yield_fixture

View File

@ -1,3 +1,4 @@
import re
import warnings import warnings
from unittest import mock from unittest import mock
@ -26,11 +27,27 @@ def test_external_plugins_integrated(testdir, plugin):
def test_fillfuncargs_is_deprecated() -> None: def test_fillfuncargs_is_deprecated() -> None:
with pytest.warns( with pytest.warns(
pytest.PytestDeprecationWarning, pytest.PytestDeprecationWarning,
match="The `_fillfuncargs` function is deprecated", match=re.escape(
"pytest._fillfuncargs() is deprecated, use "
"function._request._fillfixtures() instead if you cannot avoid reaching into internals."
),
): ):
pytest._fillfuncargs(mock.Mock()) pytest._fillfuncargs(mock.Mock())
def test_fillfixtures_is_deprecated() -> None:
import _pytest.fixtures
with pytest.warns(
pytest.PytestDeprecationWarning,
match=re.escape(
"_pytest.fixtures.fillfixtures() is deprecated, use "
"function._request._fillfixtures() instead if you cannot avoid reaching into internals."
),
):
_pytest.fixtures.fillfixtures(mock.Mock())
def test_minus_k_dash_is_deprecated(testdir) -> None: def test_minus_k_dash_is_deprecated(testdir) -> None:
threepass = testdir.makepyfile( threepass = testdir.makepyfile(
test_threepass=""" test_threepass="""

View File

@ -87,7 +87,7 @@ def test_getfuncargnames_staticmethod_partial():
class TestFillFixtures: class TestFillFixtures:
def test_fillfuncargs_exposed(self): def test_fillfuncargs_exposed(self):
# used by oejskit, kept for compatibility # used by oejskit, kept for compatibility
assert pytest._fillfuncargs == fixtures.fillfixtures assert pytest._fillfuncargs == fixtures._fillfuncargs
def test_funcarg_lookupfails(self, testdir): def test_funcarg_lookupfails(self, testdir):
testdir.copy_example() testdir.copy_example()

View File

@ -984,6 +984,36 @@ class TestLastFailed:
) )
assert result.ret == 0 assert result.ret == 0
def test_packages(self, testdir: Testdir) -> None:
"""Regression test for #7758.
The particular issue here was that Package nodes were included in the
filtering, being themselves Modules for the __init__.py, even if they
had failed Modules in them.
The tests includes a test in an __init__.py file just to make sure the
fix doesn't somehow regress that, it is not critical for the issue.
"""
testdir.makepyfile(
**{
"__init__.py": "",
"a/__init__.py": "def test_a_init(): assert False",
"a/test_one.py": "def test_1(): assert False",
"b/__init__.py": "",
"b/test_two.py": "def test_2(): assert False",
},
)
testdir.makeini(
"""
[pytest]
python_files = *.py
"""
)
result = testdir.runpytest()
result.assert_outcomes(failed=3)
result = testdir.runpytest("--lf")
result.assert_outcomes(failed=3)
class TestNewFirst: class TestNewFirst:
def test_newfirst_usecase(self, testdir): def test_newfirst_usecase(self, testdir):

View File

@ -1178,6 +1178,15 @@ def test_collect_symlink_out_of_tree(testdir):
assert result.ret == 0 assert result.ret == 0
def test_collect_symlink_dir(testdir: Testdir) -> None:
"""A symlinked directory is collected."""
dir = testdir.mkdir("dir")
dir.join("test_it.py").write("def test_it(): pass")
symlink_or_skip(dir, testdir.tmpdir.join("symlink_dir"))
result = testdir.runpytest()
result.assert_outcomes(passed=2)
def test_collectignore_via_conftest(testdir): def test_collectignore_via_conftest(testdir):
"""collect_ignore in parent conftest skips importing child (issue #4592).""" """collect_ignore in parent conftest skips importing child (issue #4592)."""
tests = testdir.mkpydir("tests") tests = testdir.mkpydir("tests")
@ -1407,3 +1416,17 @@ def test_does_not_crash_on_error_from_decorated_function(testdir: Testdir) -> No
result = testdir.runpytest() result = testdir.runpytest()
# Not INTERNAL_ERROR # Not INTERNAL_ERROR
assert result.ret == ExitCode.INTERRUPTED assert result.ret == ExitCode.INTERRUPTED
def test_does_not_crash_on_recursive_symlink(testdir: Testdir) -> None:
"""Regression test for an issue around recursive symlinks (#7951)."""
symlink_or_skip("recursive", testdir.tmpdir.join("recursive"))
testdir.makepyfile(
"""
def test_foo(): assert True
"""
)
result = testdir.runpytest()
assert result.ret == ExitCode.OK
assert result.parseoutcomes() == {"passed": 1}

View File

@ -1375,6 +1375,21 @@ class TestRootdir:
assert rootpath == tmp_path assert rootpath == tmp_path
assert inipath is None assert inipath is None
def test_with_config_also_in_parent_directory(
self, tmp_path: Path, monkeypatch: MonkeyPatch
) -> None:
"""Regression test for #7807."""
(tmp_path / "setup.cfg").write_text("[tool:pytest]\n", "utf-8")
(tmp_path / "myproject").mkdir()
(tmp_path / "myproject" / "setup.cfg").write_text("[tool:pytest]\n", "utf-8")
(tmp_path / "myproject" / "tests").mkdir()
monkeypatch.chdir(tmp_path / "myproject")
rootpath, inipath, _ = determine_setup(None, ["tests/"])
assert rootpath == tmp_path / "myproject"
assert inipath == tmp_path / "myproject" / "setup.cfg"
class TestOverrideIniArgs: class TestOverrideIniArgs:
@pytest.mark.parametrize("name", "setup.cfg tox.ini pytest.ini".split()) @pytest.mark.parametrize("name", "setup.cfg tox.ini pytest.ini".split())

View File

@ -17,6 +17,8 @@ from _pytest.pathlib import ImportPathMismatchError
from _pytest.pathlib import maybe_delete_a_numbered_dir from _pytest.pathlib import maybe_delete_a_numbered_dir
from _pytest.pathlib import Path from _pytest.pathlib import Path
from _pytest.pathlib import resolve_package_path from _pytest.pathlib import resolve_package_path
from _pytest.pathlib import symlink_or_skip
from _pytest.pathlib import visit
class TestFNMatcherPort: class TestFNMatcherPort:
@ -401,3 +403,13 @@ def test_commonpath() -> None:
assert commonpath(subpath, path) == path assert commonpath(subpath, path) == path
assert commonpath(Path(str(path) + "suffix"), path) == path.parent assert commonpath(Path(str(path) + "suffix"), path) == path.parent
assert commonpath(path, path.parent.parent) == path.parent.parent assert commonpath(path, path.parent.parent) == path.parent.parent
def test_visit_ignores_errors(tmpdir: py.path.local) -> None:
symlink_or_skip("recursive", tmpdir.join("recursive"))
tmpdir.join("foo").write_binary(b"")
tmpdir.join("bar").write_binary(b"")
assert [
entry.name for entry in visit(str(tmpdir), recurse=lambda entry: False)
] == ["bar", "foo"]

View File

@ -18,6 +18,7 @@ import pytest
from _pytest._io.wcwidth import wcswidth from _pytest._io.wcwidth import wcswidth
from _pytest.config import Config from _pytest.config import Config
from _pytest.config import ExitCode from _pytest.config import ExitCode
from _pytest.monkeypatch import MonkeyPatch
from _pytest.pathlib import Path from _pytest.pathlib import Path
from _pytest.pytester import Testdir from _pytest.pytester import Testdir
from _pytest.reports import BaseReport from _pytest.reports import BaseReport
@ -749,6 +750,29 @@ class TestTerminalFunctional:
result = testdir.runpytest("tests") result = testdir.runpytest("tests")
result.stdout.fnmatch_lines(["rootdir: *test_header0, configfile: tox.ini"]) result.stdout.fnmatch_lines(["rootdir: *test_header0, configfile: tox.ini"])
def test_header_absolute_testpath(
self, testdir: Testdir, monkeypatch: MonkeyPatch
) -> None:
"""Regresstion test for #7814."""
tests = testdir.tmpdir.join("tests")
tests.ensure_dir()
testdir.makepyprojecttoml(
"""
[tool.pytest.ini_options]
testpaths = ['{}']
""".format(
tests
)
)
result = testdir.runpytest()
result.stdout.fnmatch_lines(
[
"rootdir: *absolute_testpath0, configfile: pyproject.toml, testpaths: {}".format(
tests
)
]
)
def test_no_header(self, testdir): def test_no_header(self, testdir):
testdir.tmpdir.join("tests").ensure_dir() testdir.tmpdir.join("tests").ensure_dir()
testdir.tmpdir.join("gui").ensure_dir() testdir.tmpdir.join("gui").ensure_dir()