Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions doc/en/reference/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,19 @@ items, delete or otherwise amend the test items:
.. hook:: pytest_collection_finish
.. autofunction:: pytest_collection_finish

During collection, the following hooks are called to track collection progress:

.. hook:: pytest_collectstart
.. autofunction:: pytest_collectstart
.. hook:: pytest_make_collect_report
.. autofunction:: pytest_make_collect_report
.. hook:: pytest_itemcollected
.. autofunction:: pytest_itemcollected
.. hook:: pytest_collectreport
.. autofunction:: pytest_collectreport
.. hook:: pytest_deselected
.. autofunction:: pytest_deselected

Test running (runtest) hooks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down Expand Up @@ -796,16 +809,6 @@ Reporting hooks

Session related reporting hooks:

.. hook:: pytest_collectstart
.. autofunction:: pytest_collectstart
.. hook:: pytest_make_collect_report
.. autofunction:: pytest_make_collect_report
.. hook:: pytest_itemcollected
.. autofunction:: pytest_itemcollected
.. hook:: pytest_collectreport
.. autofunction:: pytest_collectreport
.. hook:: pytest_deselected
.. autofunction:: pytest_deselected
.. hook:: pytest_report_header
.. autofunction:: pytest_report_header
.. hook:: pytest_report_collectionfinish
Expand Down
70 changes: 70 additions & 0 deletions src/_pytest/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,16 @@ def pytest_addoption(parser: Parser) -> None:


def validate_basetemp(path: str) -> str:
"""Validate the ``--basetemp`` option value.

Raises :class:`argparse.ArgumentTypeError` if ``path`` is empty or is
an ancestor of (or equal to) the current working directory, to prevent
accidental deletion of the working tree.

:param path: The path string provided by the user for the base temp directory.
:returns: The validated path string unchanged.
:raises argparse.ArgumentTypeError: If the path is empty or an ancestor of cwd.
"""
# GH 7119
msg = "basetemp must not be empty, the current working directory or any parent directory of it"

Expand Down Expand Up @@ -361,6 +371,14 @@ def wrap_session(


def pytest_cmdline_main(config: Config) -> int | ExitCode:
"""Default implementation of the :hook:`pytest_cmdline_main` hook.

Runs the full test session by calling :func:`wrap_session` with the
default ``_main`` implementation.

:param config: The pytest :class:`~pytest.Config` object.
:returns: The session exit code.
"""
return wrap_session(config, _main)


Expand All @@ -378,10 +396,27 @@ def _main(config: Config, session: Session) -> int | ExitCode | None:


def pytest_collection(session: Session) -> None:
"""Default implementation of the :hook:`pytest_collection` hook.

Triggers test collection by calling :meth:`~pytest.Session.perform_collect`
on the active session.

:param session: The active :class:`~pytest.Session`.
"""
session.perform_collect()


def pytest_runtestloop(session: Session) -> bool:
"""Default implementation of the :hook:`pytest_runtestloop` hook.

Iterates over all collected test items and runs each one via
:hook:`pytest_runtest_protocol`. Raises :class:`~pytest.Session.Failed`
or :class:`~pytest.Session.Interrupted` if the session signals that
testing should stop early.

:param session: The active :class:`~pytest.Session`.
:returns: ``True`` when the loop completes normally.
"""
if session.testsfailed and not session.config.option.continue_on_collection_errors:
raise session.Interrupted(
f"{session.testsfailed} error{'s' if session.testsfailed != 1 else ''} during collection"
Expand Down Expand Up @@ -422,6 +457,24 @@ def _in_venv(path: Path) -> bool:


def pytest_ignore_collect(collection_path: Path, config: Config) -> bool | None:
"""Default implementation of the :hook:`pytest_ignore_collect` hook.

Returns ``True`` to skip collection of *collection_path* when any of the
following conditions hold:

* The path is a ``__pycache__`` directory.
* The path matches an entry in ``collect_ignore`` or ``--ignore``.
* The path matches a glob in ``collect_ignore_glob`` or ``--ignore-glob``.
* The path is a virtual environment root and ``--collect-in-virtualenv``
is not set.
* The path is a directory matching a pattern in ``norecursedirs``.

Returns ``None`` to allow collection to proceed normally.

:param collection_path: The filesystem path being considered for collection.
:param config: The pytest :class:`~pytest.Config` object.
:returns: ``True`` to skip the path, ``None`` to allow collection.
"""
if collection_path.name == "__pycache__":
return True

Expand Down Expand Up @@ -462,10 +515,27 @@ def pytest_ignore_collect(collection_path: Path, config: Config) -> bool | None:
def pytest_collect_directory(
path: Path, parent: nodes.Collector
) -> nodes.Collector | None:
"""Default implementation of the :hook:`pytest_collect_directory` hook.

Creates a :class:`~pytest.Dir` collector node for the given directory.

:param path: The directory path to collect.
:param parent: The parent collector node.
:returns: A :class:`~pytest.Dir` node for the directory.
"""
return Dir.from_parent(parent, path=path)


def pytest_collection_modifyitems(items: list[nodes.Item], config: Config) -> None:
"""Default implementation of the :hook:`pytest_collection_modifyitems` hook.

Removes test items whose node IDs start with any of the prefixes supplied
via the ``--deselect`` command-line option, firing the
:hook:`pytest_deselected` hook for the removed items.

:param items: The list of collected test items (modified in place).
:param config: The pytest :class:`~pytest.Config` object.
"""
deselect_prefixes = tuple(config.getoption("deselect") or [])
if not deselect_prefixes:
return
Expand Down
Loading