diff --git a/AUTHORS b/AUTHORS index 68268d33a..6e341d64e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -173,5 +173,6 @@ Vidar T. Fauske Vitaly Lashmanov Vlad Dragos Wouter van Ackooy +Xuan Luong Xuecong Liao Zoltán Máté diff --git a/changelog/2604.doc b/changelog/2604.doc new file mode 100644 index 000000000..f2b6dd7d1 --- /dev/null +++ b/changelog/2604.doc @@ -0,0 +1 @@ +In examples on working with custom markers, add examples demonstrating the usage of ``pytest.mark.MARKER_NAME.with_args`` in comparison with ``pytest.mark.MARKER_NAME.__call__`` diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst index 52627245c..ca28e898e 100644 --- a/doc/en/example/markers.rst +++ b/doc/en/example/markers.rst @@ -393,7 +393,49 @@ The ``--markers`` option always gives you a list of available markers:: @pytest.mark.tryfirst: mark a hook implementation function such that the plugin machinery will try to call it first/as early as possible. @pytest.mark.trylast: mark a hook implementation function such that the plugin machinery will try to call it last/as late as possible. - + +.. _`passing callables to custom markers`: + +Passing a callable to custom markers +-------------------------------------------- + +.. regendoc:wipe + +Below is the config file that will be used in the next examples:: + + # content of conftest.py + import sys + + def pytest_runtest_setup(item): + marker = item.get_marker('my_marker') + if marker is not None: + for info in marker: + print('Marker info name={} args={} kwars={}'.format(info.name, info.args, info.kwargs)) + sys.stdout.flush() + +A custom marker can have its argument set, i.e. ``args`` and ``kwargs`` properties, defined by either invoking it as a callable or using ``pytest.mark.MARKER_NAME.with_args``. These two methods achieve the same effect most of the time. + +However, if there is a callable as the single positional argument with no keyword arguments, using the ``pytest.mark.MARKER_NAME(c)`` will not pass ``c`` as a positional argument but decorate ``c`` with the custom marker (see :ref:`MarkDecorator `). Fortunately, ``pytest.mark.MARKER_NAME.with_args`` comes to the rescue:: + + # content of test_custom_marker.py + import pytest + + def hello_world(*args, **kwargs): + return 'Hello World' + + @pytest.mark.my_marker.with_args(hello_world) + def test_with_args(): + pass + +The output is as follows:: + + $ pytest -q -s + Marker info name=my_marker args=(,) kwars={} + . + 1 passed in 0.01 seconds + +We can see that the custom marker has its argument set extended with the function ``hello_world``. This is the key different between creating a custom marker as a callable, which invokes ``__call__`` behind the scenes, and using ``with_args``. + Reading markers which were set from multiple places ----------------------------------------------------