From 906d8496c9e7af420cd604685a92aceb15e53d95 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 10 Jul 2020 09:50:03 -0300 Subject: [PATCH] New doc role: globalvar for special variables This introduces a new role, `:globalvar:`, so we can mark/reference variables like `pytest_plugins`, `pytestmark`, etc. This besides being useful also makes the documentation look more consistent. --- doc/en/assert.rst | 2 -- doc/en/changelog.rst | 2 +- doc/en/conf.py | 7 ++++++ doc/en/deprecations.rst | 2 +- doc/en/example/markers.rst | 35 ++++++++++------------------- doc/en/example/pythoncollection.rst | 2 +- doc/en/fixture.rst | 5 +---- doc/en/plugins.rst | 3 ++- doc/en/reference.rst | 27 ++++++++-------------- doc/en/skipping.rst | 4 ++-- doc/en/warnings.rst | 2 +- doc/en/writing_plugins.rst | 16 ++++++------- 12 files changed, 45 insertions(+), 62 deletions(-) diff --git a/doc/en/assert.rst b/doc/en/assert.rst index e39da6e8a..7e43b07fd 100644 --- a/doc/en/assert.rst +++ b/doc/en/assert.rst @@ -294,8 +294,6 @@ Assertion introspection details ------------------------------- - - Reporting details about a failing assertion is achieved by rewriting assert statements before they are run. Rewritten assert statements put introspection information into the assertion failure message. ``pytest`` only rewrites test diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index d6e07c8e4..415bfd7c7 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -2188,7 +2188,7 @@ Features - `#3711 `_: Add the ``--ignore-glob`` parameter to exclude test-modules with Unix shell-style wildcards. - Add the ``collect_ignore_glob`` for ``conftest.py`` to exclude test-modules with Unix shell-style wildcards. + Add the :globalvar:`collect_ignore_glob` for ``conftest.py`` to exclude test-modules with Unix shell-style wildcards. - `#4698 `_: The warning about Python 2.7 and 3.4 not being supported in pytest 5.0 has been removed. diff --git a/doc/en/conf.py b/doc/en/conf.py index 72e2d4f20..c631484aa 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -390,4 +390,11 @@ def setup(app: "sphinx.application.Sphinx") -> None: indextemplate="pair: %s; configuration value", ) + app.add_object_type( + "globalvar", + "globalvar", + objname="global variable interpreted by pytest", + indextemplate="pair: %s; global variable interpreted by pytest", + ) + configure_logging(app) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index ccf31cd8b..a2bed1862 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -413,7 +413,7 @@ pytest_plugins in non-top-level conftest files .. versionremoved:: 4.0 -Defining ``pytest_plugins`` is now deprecated in non-top-level conftest.py +Defining :globalvar:`pytest_plugins` is now deprecated in non-top-level conftest.py files because they will activate referenced plugins *globally*, which is surprising because for all other pytest features ``conftest.py`` files are only *active* for tests at or below it. diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst index 454304679..38610ee3a 100644 --- a/doc/en/example/markers.rst +++ b/doc/en/example/markers.rst @@ -280,27 +280,7 @@ its test methods: This is equivalent to directly applying the decorator to the two test functions. -Due to legacy reasons, it is possible to set the ``pytestmark`` attribute on a TestClass like this: - -.. code-block:: python - - import pytest - - - class TestClass: - pytestmark = pytest.mark.webtest - -or if you need to use multiple markers you can use a list: - -.. code-block:: python - - import pytest - - - class TestClass: - pytestmark = [pytest.mark.webtest, pytest.mark.slowtest] - -You can also set a module level marker:: +To apply marks at the module level, use the :globalvar:`pytestmark` global variable: import pytest pytestmark = pytest.mark.webtest @@ -309,8 +289,17 @@ or multiple markers:: pytestmark = [pytest.mark.webtest, pytest.mark.slowtest] -in which case markers will be applied (in left-to-right order) to -all functions and methods defined in the module. + +Due to legacy reasons, before class decorators were introduced, it is possible to set the +:globalvar:`pytestmark` attribute on a test class like this: + +.. code-block:: python + + import pytest + + + class TestClass: + pytestmark = pytest.mark.webtest .. _`marking individual tests when using parametrize`: diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 85e5da263..a12e2deaa 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -299,7 +299,7 @@ file will be left out: ========================== no tests ran in 0.12s =========================== It's also possible to ignore files based on Unix shell-style wildcards by adding -patterns to ``collect_ignore_glob``. +patterns to :globalvar:`collect_ignore_glob`. The following example ``conftest.py`` ignores the file ``setup.py`` and in addition all files that end with ``*_py2.py`` when executed with a Python 3 diff --git a/doc/en/fixture.rst b/doc/en/fixture.rst index 8d2d06367..a023621dc 100644 --- a/doc/en/fixture.rst +++ b/doc/en/fixture.rst @@ -1213,15 +1213,12 @@ You can specify multiple fixtures like this: def test(): ... -and you may specify fixture usage at the test module level, using -a generic feature of the mark mechanism: +and you may specify fixture usage at the test module level using :globalvar:`pytestmark`: .. code-block:: python pytestmark = pytest.mark.usefixtures("cleandir") -Note that the assigned variable *must* be called ``pytestmark``, assigning e.g. -``foomark`` will not activate the fixtures. It is also possible to put fixtures required by all tests in your project into an ini-file: diff --git a/doc/en/plugins.rst b/doc/en/plugins.rst index c3a931419..855b59739 100644 --- a/doc/en/plugins.rst +++ b/doc/en/plugins.rst @@ -70,7 +70,7 @@ You may also discover more plugins through a `pytest- pypi.org search`_. Requiring/Loading plugins in a test module or conftest file ----------------------------------------------------------- -You can require plugins in a test module or a conftest file like this: +You can require plugins in a test module or a conftest file using :globalvar:`pytest_plugins`: .. code-block:: python @@ -80,6 +80,7 @@ When the test module or conftest plugin is loaded the specified plugins will be loaded as well. .. note:: + Requiring plugins using a ``pytest_plugins`` variable in non-root ``conftest.py`` files is deprecated. See :ref:`full explanation ` diff --git a/doc/en/reference.rst b/doc/en/reference.rst index 86ed89d89..d81ba9bc7 100644 --- a/doc/en/reference.rst +++ b/doc/en/reference.rst @@ -900,14 +900,14 @@ Result used within :ref:`hook wrappers `. .. automethod:: pluggy.callers._Result.get_result .. automethod:: pluggy.callers._Result.force_result -Special Variables ------------------ +Global Variables +---------------- -pytest treats some global variables in a special manner when defined in a test module. +pytest treats some global variables in a special manner when defined in a test module or +``conftest.py`` files. -collect_ignore -~~~~~~~~~~~~~~ +.. globalvar:: collect_ignore **Tutorial**: :ref:`customizing-test-collection` @@ -919,8 +919,7 @@ Needs to be ``list[str]``. collect_ignore = ["setup.py"] -collect_ignore_glob -~~~~~~~~~~~~~~~~~~~ +.. globalvar:: collect_ignore_glob **Tutorial**: :ref:`customizing-test-collection` @@ -933,8 +932,7 @@ contain glob patterns. collect_ignore_glob = ["*_ignore.py"] -pytest_plugins -~~~~~~~~~~~~~~ +.. globalvar:: pytest_plugins **Tutorial**: :ref:`available installable plugins` @@ -950,13 +948,12 @@ Can be either a ``str`` or ``Sequence[str]``. pytest_plugins = ("myapp.testsupport.tools", "myapp.testsupport.regression") -pytestmark -~~~~~~~~~~ +.. globalvar:: pytestmark **Tutorial**: :ref:`scoped-marking` Can be declared at the **global** level in *test modules* to apply one or more :ref:`marks ` to all -test functions and methods. Can be either a single mark or a list of marks. +test functions and methods. Can be either a single mark or a list of marks (applied in left-to-right order). .. code-block:: python @@ -971,12 +968,6 @@ test functions and methods. Can be either a single mark or a list of marks. pytestmark = [pytest.mark.integration, pytest.mark.slow] -PYTEST_DONT_REWRITE (module docstring) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The text ``PYTEST_DONT_REWRITE`` can be add to any **module docstring** to disable -:ref:`assertion rewriting ` for that module. - Environment Variables --------------------- diff --git a/doc/en/skipping.rst b/doc/en/skipping.rst index 951a56566..c4e7d4a0a 100644 --- a/doc/en/skipping.rst +++ b/doc/en/skipping.rst @@ -152,8 +152,8 @@ You can use the ``skipif`` marker (as any other marker) on classes: If the condition is ``True``, this marker will produce a skip result for each of the test methods of that class. -If you want to skip all test functions of a module, you may use -the ``pytestmark`` name on the global level: +If you want to skip all test functions of a module, you may use the +:globalvar:`pytestmark` global: .. code-block:: python diff --git a/doc/en/warnings.rst b/doc/en/warnings.rst index 6a37b2ad0..30ea52965 100644 --- a/doc/en/warnings.rst +++ b/doc/en/warnings.rst @@ -117,7 +117,7 @@ Filters applied using a mark take precedence over filters passed on the command by the ``filterwarnings`` ini option. You may apply a filter to all tests of a class by using the ``filterwarnings`` mark as a class -decorator or to all tests in a module by setting the ``pytestmark`` variable: +decorator or to all tests in a module by setting the :globalvar:`pytestmark` variable: .. code-block:: python diff --git a/doc/en/writing_plugins.rst b/doc/en/writing_plugins.rst index f3e4cbd23..27ef40e5b 100644 --- a/doc/en/writing_plugins.rst +++ b/doc/en/writing_plugins.rst @@ -52,7 +52,7 @@ Plugin discovery order at tool startup your ``conftest.py`` file in the top level test or project root directory. * by recursively loading all plugins specified by the - ``pytest_plugins`` variable in ``conftest.py`` files + :globalvar:`pytest_plugins` variable in ``conftest.py`` files .. _`pytest/plugin`: http://bitbucket.org/pytest-dev/pytest/src/tip/pytest/plugin/ @@ -227,7 +227,7 @@ import ``helper.py`` normally. The contents of Requiring/Loading plugins in a test module or conftest file ----------------------------------------------------------- -You can require plugins in a test module or a ``conftest.py`` file like this: +You can require plugins in a test module or a ``conftest.py`` file using :globalvar:`pytest_plugins`: .. code-block:: python @@ -241,31 +241,31 @@ application modules: pytest_plugins = "myapp.testsupport.myplugin" -``pytest_plugins`` variables are processed recursively, so note that in the example above -if ``myapp.testsupport.myplugin`` also declares ``pytest_plugins``, the contents +:globalvar:`pytest_plugins` are processed recursively, so note that in the example above +if ``myapp.testsupport.myplugin`` also declares :globalvar:`pytest_plugins`, the contents of the variable will also be loaded as plugins, and so on. .. _`requiring plugins in non-root conftests`: .. note:: - Requiring plugins using a ``pytest_plugins`` variable in non-root + Requiring plugins using :globalvar:`pytest_plugins` variable in non-root ``conftest.py`` files is deprecated. This is important because ``conftest.py`` files implement per-directory hook implementations, but once a plugin is imported, it will affect the entire directory tree. In order to avoid confusion, defining - ``pytest_plugins`` in any ``conftest.py`` file which is not located in the + :globalvar:`pytest_plugins` in any ``conftest.py`` file which is not located in the tests root directory is deprecated, and will raise a warning. This mechanism makes it easy to share fixtures within applications or even external applications without the need to create external plugins using the ``setuptools``'s entry point technique. -Plugins imported by ``pytest_plugins`` will also automatically be marked +Plugins imported by :globalvar:`pytest_plugins` will also automatically be marked for assertion rewriting (see :func:`pytest.register_assert_rewrite`). However for this to have any effect the module must not be imported already; if it was already imported at the time the -``pytest_plugins`` statement is processed, a warning will result and +:globalvar:`pytest_plugins` statement is processed, a warning will result and assertions inside the plugin will not be rewritten. To fix this you can either call :func:`pytest.register_assert_rewrite` yourself before the module is imported, or you can arrange the code to delay the