Merge pull request #2593 from hackebrot/extend-pytester-docs-for-testing-plugin-code
Extend pytester docs for testing plugin code
This commit is contained in:
commit
61d4345ea4
|
@ -0,0 +1 @@
|
||||||
|
Extend documentation for testing plugin code with the ``pytester`` plugin.
|
|
@ -122,8 +122,8 @@ to extend and add functionality.
|
||||||
for authoring plugins.
|
for authoring plugins.
|
||||||
|
|
||||||
The template provides an excellent starting point with a working plugin,
|
The template provides an excellent starting point with a working plugin,
|
||||||
tests running with tox, comprehensive README and
|
tests running with tox, a comprehensive README file as well as a
|
||||||
entry-pointy already pre-configured.
|
pre-configured entry-point.
|
||||||
|
|
||||||
Also consider :ref:`contributing your plugin to pytest-dev<submitplugin>`
|
Also consider :ref:`contributing your plugin to pytest-dev<submitplugin>`
|
||||||
once it has some happy users other than yourself.
|
once it has some happy users other than yourself.
|
||||||
|
@ -286,34 +286,101 @@ the ``--trace-config`` option.
|
||||||
Testing plugins
|
Testing plugins
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
pytest comes with some facilities that you can enable for testing your
|
pytest comes with a plugin named ``pytester`` that helps you write tests for
|
||||||
plugin. Given that you have an installed plugin you can enable the
|
your plugin code. The plugin is disabled by default, so you will have to enable
|
||||||
:py:class:`testdir <_pytest.pytester.Testdir>` fixture via specifying a
|
it before you can use it.
|
||||||
command line option to include the pytester plugin (``-p pytester``) or
|
|
||||||
by putting ``pytest_plugins = "pytester"`` into your test or
|
|
||||||
``conftest.py`` file. You then will have a ``testdir`` fixture which you
|
|
||||||
can use like this::
|
|
||||||
|
|
||||||
# content of test_myplugin.py
|
You can do so by adding the following line to a ``conftest.py`` file in your
|
||||||
|
testing directory:
|
||||||
|
|
||||||
pytest_plugins = "pytester" # to get testdir fixture
|
.. code-block:: python
|
||||||
|
|
||||||
def test_myplugin(testdir):
|
# content of conftest.py
|
||||||
|
|
||||||
|
pytest_plugins = ["pytester"]
|
||||||
|
|
||||||
|
Alternatively you can invoke pytest with the ``-p pytester`` command line
|
||||||
|
option.
|
||||||
|
|
||||||
|
This will allow you to use the :py:class:`testdir <_pytest.pytester.Testdir>`
|
||||||
|
fixture for testing your plugin code.
|
||||||
|
|
||||||
|
Let's demonstrate what you can do with the plugin with an example. Imagine we
|
||||||
|
developed a plugin that provides a fixture ``hello`` which yields a function
|
||||||
|
and we can invoke this function with one optional parameter. It will return a
|
||||||
|
string value of ``Hello World!`` if we do not supply a value or ``Hello
|
||||||
|
{value}!`` if we do supply a string value.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
def pytest_addoption(parser):
|
||||||
|
group = parser.getgroup('helloworld')
|
||||||
|
group.addoption(
|
||||||
|
'--name',
|
||||||
|
action='store',
|
||||||
|
dest='name',
|
||||||
|
default='World',
|
||||||
|
help='Default "name" for hello().'
|
||||||
|
)
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def hello(request):
|
||||||
|
name = request.config.option.name
|
||||||
|
|
||||||
|
def _hello(name=None):
|
||||||
|
if not name:
|
||||||
|
name = request.config.option.name
|
||||||
|
return "Hello {name}!".format(name=name)
|
||||||
|
|
||||||
|
return _hello
|
||||||
|
|
||||||
|
|
||||||
|
Now the ``testdir`` fixture provides a convenient API for creating temporary
|
||||||
|
``conftest.py`` files and test files. It also allows us to run the tests and
|
||||||
|
return a result object, with which we can assert the tests' outcomes.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def test_hello(testdir):
|
||||||
|
"""Make sure that our plugin works."""
|
||||||
|
|
||||||
|
# create a temporary conftest.py file
|
||||||
|
testdir.makeconftest("""
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
@pytest.fixture(params=[
|
||||||
|
"Brianna",
|
||||||
|
"Andreas",
|
||||||
|
"Floris",
|
||||||
|
])
|
||||||
|
def name(request):
|
||||||
|
return request.param
|
||||||
|
""")
|
||||||
|
|
||||||
|
# create a temporary pytest test file
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
def test_example():
|
def test_hello_default(hello):
|
||||||
pass
|
assert hello() == "Hello World!"
|
||||||
""")
|
|
||||||
result = testdir.runpytest("--verbose")
|
def test_hello_name(hello, name):
|
||||||
result.stdout.fnmatch_lines("""
|
assert hello(name) == "Hello {0}!".format(name)
|
||||||
test_example*
|
|
||||||
""")
|
""")
|
||||||
|
|
||||||
Note that by default ``testdir.runpytest()`` will perform a pytest
|
# run all tests with pytest
|
||||||
in-process. You can pass the command line option ``--runpytest=subprocess``
|
result = testdir.runpytest()
|
||||||
to have it happen in a subprocess.
|
|
||||||
|
# check that all 4 tests passed
|
||||||
|
result.assert_outcomes(passed=4)
|
||||||
|
|
||||||
|
|
||||||
|
For more information about the result object that ``runpytest()`` returns, and
|
||||||
|
the methods that it provides please check out the :py:class:`RunResult
|
||||||
|
<_pytest.pytester.RunResult>` documentation.
|
||||||
|
|
||||||
Also see the :py:class:`RunResult <_pytest.pytester.RunResult>` for more
|
|
||||||
methods of the result object that you get from a call to ``runpytest``.
|
|
||||||
|
|
||||||
.. _`writinghooks`:
|
.. _`writinghooks`:
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue