From d97295730330f7686a155dd6482405ad4a823b1d Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 23 Jan 2024 16:08:16 +0200 Subject: [PATCH] hookspec: document conftest behavior for all hooks (#9496) Have each hook explain how implementing it in conftests works. This is part of the functional specification of a hook. --- src/_pytest/hookspec.py | 340 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 315 insertions(+), 25 deletions(-) diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index c4cce2d83..83c9be3ef 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -58,6 +58,12 @@ def pytest_addhooks(pluginmanager: "PytestPluginManager") -> None: .. note:: This hook is incompatible with hook wrappers. + + Use in conftest plugins + ======================= + + If a conftest plugin implements this hook, it will be called immediately + when the conftest is registered. """ @@ -75,6 +81,14 @@ def pytest_plugin_registered( .. note:: This hook is incompatible with hook wrappers. + + Use in conftest plugins + ======================= + + If a conftest plugin implements this hook, it will be called immediately + when the conftest is registered, once for each plugin registered thus far + (including itself!), and for all plugins thereafter when they are + registered. """ @@ -83,12 +97,6 @@ def pytest_addoption(parser: "Parser", pluginmanager: "PytestPluginManager") -> """Register argparse-style options and ini-style config values, called once at the beginning of a test run. - .. note:: - - This function should be implemented only in plugins or ``conftest.py`` - files situated at the tests root directory due to how pytest - :ref:`discovers plugins during startup `. - :param parser: To add command line options, call :py:func:`parser.addoption(...) `. @@ -114,6 +122,14 @@ def pytest_addoption(parser: "Parser", pluginmanager: "PytestPluginManager") -> .. note:: This hook is incompatible with hook wrappers. + + Use in conftest plugins + ======================= + + If a conftest plugin implements this hook, it will be called immediately + when the conftest is registered. + + This hook is only called for :ref:`initial conftests `. """ @@ -121,16 +137,17 @@ def pytest_addoption(parser: "Parser", pluginmanager: "PytestPluginManager") -> def pytest_configure(config: "Config") -> None: """Allow plugins and conftest files to perform initial configuration. - This hook is called for every plugin and initial conftest file - after command line options have been parsed. - - After that, the hook is called for other conftest files as they are - imported. - .. note:: This hook is incompatible with hook wrappers. :param config: The pytest config object. + + Use in conftest plugins + ======================= + + This hook is called for every :ref:`initial conftest ` file + after command line options have been parsed. After that, the hook is called + for other conftest files as they are registered. """ @@ -149,28 +166,35 @@ def pytest_cmdline_parse( Stops at first non-None result, see :ref:`firstresult`. .. note:: - This hook will only be called for plugin classes passed to the + This hook is only called for plugin classes passed to the ``plugins`` arg when using `pytest.main`_ to perform an in-process test run. :param pluginmanager: The pytest plugin manager. :param args: List of arguments passed on the command line. :returns: A pytest config object. + + Use in conftest plugins + ======================= + + This hook is not called for conftest files. """ def pytest_load_initial_conftests( early_config: "Config", parser: "Parser", args: List[str] ) -> None: - """Called to implement the loading of initial conftest files ahead - of command line option parsing. - - .. note:: - This hook will not be called for ``conftest.py`` files, only for setuptools plugins. + """Called to implement the loading of :ref:`initial conftest files + ` ahead of command line option parsing. :param early_config: The pytest config object. :param args: Arguments passed on the command line. :param parser: To add command line options. + + Use in conftest plugins + ======================= + + This hook is not called for conftest files. """ @@ -185,6 +209,11 @@ def pytest_cmdline_main(config: "Config") -> Optional[Union["ExitCode", int]]: :param config: The pytest config object. :returns: The exit code. + + Use in conftest plugins + ======================= + + This hook is only called for :ref:`initial conftests `. """ @@ -227,6 +256,11 @@ def pytest_collection(session: "Session") -> Optional[object]: counter (and returns `None`). :param session: The pytest session object. + + Use in conftest plugins + ======================= + + This hook is only called for :ref:`initial conftests `. """ @@ -239,6 +273,11 @@ def pytest_collection_modifyitems( :param session: The pytest session object. :param config: The pytest config object. :param items: List of item objects. + + Use in conftest plugins + ======================= + + Any conftest plugin can implement this hook. """ @@ -246,6 +285,11 @@ def pytest_collection_finish(session: "Session") -> None: """Called after collection has been performed and modified. :param session: The pytest session object. + + Use in conftest plugins + ======================= + + Any conftest plugin can implement this hook. """ @@ -268,6 +312,14 @@ def pytest_ignore_collect(collection_path: Path, config: "Config") -> Optional[b .. versionchanged:: 8.0.0 The ``path`` parameter has been removed. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given collection path, only + conftest files in parent directories of the collection path are consulted + (if the path is a directory, its own conftest file is *not* consulted - a + directory cannot ignore itself!). """ @@ -289,6 +341,14 @@ def pytest_collect_directory(path: Path, parent: "Collector") -> "Optional[Colle See :ref:`custom directory collectors` for a simple example of use of this hook. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given collection path, only + conftest files in parent directories of the collection path are consulted + (if the path is a directory, its own conftest file is *not* consulted - a + directory cannot collect itself!). """ @@ -309,6 +369,12 @@ def pytest_collect_file(file_path: Path, parent: "Collector") -> "Optional[Colle .. versionchanged:: 8.0.0 The ``path`` parameter was removed. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given file path, only + conftest files in parent directories of the file path are consulted. """ @@ -320,6 +386,13 @@ def pytest_collectstart(collector: "Collector") -> None: :param collector: The collector. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given collector, only + conftest files in the collector's directory and its parent directories are + consulted. """ @@ -328,6 +401,12 @@ def pytest_itemcollected(item: "Item") -> None: :param item: The item. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only conftest + files in the item's directory and its parent directories are consulted. """ @@ -336,6 +415,13 @@ def pytest_collectreport(report: "CollectReport") -> None: :param report: The collect report. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given collector, only + conftest files in the collector's directory and its parent directories are + consulted. """ @@ -346,6 +432,11 @@ def pytest_deselected(items: Sequence["Item"]) -> None: :param items: The items. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. """ @@ -358,6 +449,13 @@ def pytest_make_collect_report(collector: "Collector") -> "Optional[CollectRepor :param collector: The collector. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given collector, only + conftest files in the collector's directory and its parent directories are + consulted. """ @@ -385,6 +483,13 @@ def pytest_pycollect_makemodule(module_path: Path, parent) -> Optional["Module"] .. versionchanged:: 8.0.0 The ``path`` parameter has been removed in favor of ``module_path``. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given parent collector, + only conftest files in the collector's directory and its parent directories + are consulted. """ @@ -404,6 +509,13 @@ def pytest_pycollect_makeitem( The object. :returns: The created items/collectors. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given collector, only + conftest files in the collector's directory and its parent directories + are consulted. """ @@ -415,6 +527,13 @@ def pytest_pyfunc_call(pyfuncitem: "Function") -> Optional[object]: :param pyfuncitem: The function item. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only + conftest files in the item's directory and its parent directories + are consulted. """ @@ -423,6 +542,13 @@ def pytest_generate_tests(metafunc: "Metafunc") -> None: :param metafunc: The :class:`~pytest.Metafunc` helper for the test function. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given function definition, + only conftest files in the functions's directory and its parent directories + are consulted. """ @@ -441,6 +567,11 @@ def pytest_make_parametrize_id( :param config: The pytest config object. :param val: The parametrized value. :param argname: The automatic parameter name produced by pytest. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. """ @@ -467,6 +598,11 @@ def pytest_runtestloop(session: "Session") -> Optional[object]: Stops at first non-None result, see :ref:`firstresult`. The return value is not used, but only stops further processing. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. """ @@ -505,6 +641,11 @@ def pytest_runtest_protocol( Stops at first non-None result, see :ref:`firstresult`. The return value is not used, but only stops further processing. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. """ @@ -519,6 +660,12 @@ def pytest_runtest_logstart( :param location: A tuple of ``(filename, lineno, testname)`` where ``filename`` is a file path relative to ``config.rootpath`` and ``lineno`` is 0-based. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only conftest + files in the item's directory and its parent directories are consulted. """ @@ -533,6 +680,12 @@ def pytest_runtest_logfinish( :param location: A tuple of ``(filename, lineno, testname)`` where ``filename`` is a file path relative to ``config.rootpath`` and ``lineno`` is 0-based. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only conftest + files in the item's directory and its parent directories are consulted. """ @@ -546,6 +699,12 @@ def pytest_runtest_setup(item: "Item") -> None: :param item: The item. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only conftest + files in the item's directory and its parent directories are consulted. """ @@ -556,6 +715,12 @@ def pytest_runtest_call(item: "Item") -> None: :param item: The item. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only conftest + files in the item's directory and its parent directories are consulted. """ @@ -574,6 +739,12 @@ def pytest_runtest_teardown(item: "Item", nextitem: Optional["Item"]) -> None: scheduled). This argument is used to perform exact teardowns, i.e. calling just enough finalizers so that nextitem only needs to call setup functions. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only conftest + files in the item's directory and its parent directories are consulted. """ @@ -590,6 +761,12 @@ def pytest_runtest_makereport( :param call: The :class:`~pytest.CallInfo` for the phase. Stops at first non-None result, see :ref:`firstresult`. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only conftest + files in the item's directory and its parent directories are consulted. """ @@ -598,6 +775,12 @@ def pytest_runtest_logreport(report: "TestReport") -> None: of the setup, call and teardown runtest phases of an item. See :hook:`pytest_runtest_protocol` for a description of the runtest protocol. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only conftest + files in the item's directory and its parent directories are consulted. """ @@ -611,6 +794,12 @@ def pytest_report_to_serializable( :param config: The pytest config object. :param report: The report. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. The exact details may depend + on the plugin which calls the hook. """ @@ -623,6 +812,12 @@ def pytest_report_from_serializable( :hook:`pytest_report_to_serializable`. :param config: The pytest config object. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. The exact details may depend + on the plugin which calls the hook. """ @@ -650,6 +845,13 @@ def pytest_fixture_setup( If the fixture function returns None, other implementations of this hook function will continue to be called, according to the behavior of the :ref:`firstresult` option. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given fixture, only + conftest files in the fixture scope's directory and its parent directories + are consulted. """ @@ -664,6 +866,13 @@ def pytest_fixture_post_finalizer( The fixture definition object. :param request: The fixture request object. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given fixture, only + conftest files in the fixture scope's directory and its parent directories + are consulted. """ @@ -677,6 +886,11 @@ def pytest_sessionstart(session: "Session") -> None: and entering the run test loop. :param session: The pytest session object. + + Use in conftest plugins + ======================= + + This hook is only called for :ref:`initial conftests `. """ @@ -688,6 +902,11 @@ def pytest_sessionfinish( :param session: The pytest session object. :param exitstatus: The status which pytest will return to the system. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. """ @@ -695,6 +914,11 @@ def pytest_unconfigure(config: "Config") -> None: """Called before test process is exited. :param config: The pytest config object. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. """ @@ -717,6 +941,12 @@ def pytest_assertrepr_compare( :param op: The operator, e.g. `"=="`, `"!="`, `"not in"`. :param left: The left operand. :param right: The right operand. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only conftest + files in the item's directory and its parent directories are consulted. """ @@ -745,6 +975,12 @@ def pytest_assertion_pass(item: "Item", lineno: int, orig: str, expl: str) -> No :param lineno: Line number of the assert statement. :param orig: String with the original assertion. :param expl: String with the assert explanation. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only conftest + files in the item's directory and its parent directories are consulted. """ @@ -769,18 +1005,17 @@ def pytest_report_header( # type:ignore[empty-body] If you want to have your line(s) displayed first, use :ref:`trylast=True `. - .. note:: - - This function should be implemented only in plugins or ``conftest.py`` - files situated at the tests root directory due to how pytest - :ref:`discovers plugins during startup `. - .. versionchanged:: 7.0.0 The ``start_path`` parameter was added as a :class:`pathlib.Path` equivalent of the ``startdir`` parameter. .. versionchanged:: 8.0.0 The ``startdir`` parameter has been removed. + + Use in conftest plugins + ======================= + + This hook is only called for :ref:`initial conftests `. """ @@ -814,6 +1049,11 @@ def pytest_report_collectionfinish( # type:ignore[empty-body] .. versionchanged:: 8.0.0 The ``startdir`` parameter has been removed. + + Use in conftest plugins + ======================= + + Any conftest plugin can implement this hook. """ @@ -842,6 +1082,11 @@ def pytest_report_teststatus( # type:ignore[empty-body] :returns: The test status. Stops at first non-None result, see :ref:`firstresult`. + + Use in conftest plugins + ======================= + + Any conftest plugin can implement this hook. """ @@ -858,6 +1103,11 @@ def pytest_terminal_summary( .. versionadded:: 4.2 The ``config`` parameter. + + Use in conftest plugins + ======================= + + Any conftest plugin can implement this hook. """ @@ -882,7 +1132,8 @@ def pytest_warning_recorded( * ``"runtest"``: during test execution. :param nodeid: - Full id of the item. + Full id of the item. Empty string for warnings that are not specific to + a particular node. :param location: When available, holds information about the execution context of the captured @@ -890,6 +1141,13 @@ def pytest_warning_recorded( when the execution context is at the module level. .. versionadded:: 6.0 + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. If the warning is specific to a + particular node, only conftest files in parent directories of the node are + consulted. """ @@ -913,6 +1171,12 @@ def pytest_markeval_namespace( # type:ignore[empty-body] :param config: The pytest config object. :returns: A dictionary of additional globals to add. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only conftest + files in parent directories of the item are consulted. """ @@ -932,6 +1196,11 @@ def pytest_internalerror( :param excrepr: The exception repr object. :param excinfo: The exception info. + + Use in conftest plugins + ======================= + + Any conftest plugin can implement this hook. """ @@ -941,6 +1210,11 @@ def pytest_keyboard_interrupt( """Called for keyboard interrupt. :param excinfo: The exception info. + + Use in conftest plugins + ======================= + + Any conftest plugin can implement this hook. """ @@ -967,6 +1241,12 @@ def pytest_exception_interact( The call information. Contains the exception. :param report: The collection or test report. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given node, only conftest + files in parent directories of the node are consulted. """ @@ -978,6 +1258,11 @@ def pytest_enter_pdb(config: "Config", pdb: "pdb.Pdb") -> None: :param config: The pytest config object. :param pdb: The Pdb instance. + + Use in conftest plugins + ======================= + + Any conftest plugin can implement this hook. """ @@ -989,4 +1274,9 @@ def pytest_leave_pdb(config: "Config", pdb: "pdb.Pdb") -> None: :param config: The pytest config object. :param pdb: The Pdb instance. + + Use in conftest plugins + ======================= + + Any conftest plugin can implement this hook. """