From 2840634c2c918fb5ff74536999a2f7de495a6ea4 Mon Sep 17 00:00:00 2001 From: Raphael Pierzina Date: Sat, 15 Jul 2017 11:45:28 +0200 Subject: [PATCH 1/5] Fix typo and improve comment about cookiecutter-template --- doc/en/writing_plugins.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/writing_plugins.rst b/doc/en/writing_plugins.rst index 9f5190c3e..25097db6d 100644 --- a/doc/en/writing_plugins.rst +++ b/doc/en/writing_plugins.rst @@ -122,8 +122,8 @@ to extend and add functionality. for authoring plugins. The template provides an excellent starting point with a working plugin, - tests running with tox, comprehensive README and - entry-pointy already pre-configured. + tests running with tox, a comprehensive README file as well as a + pre-configured entry-point. Also consider :ref:`contributing your plugin to pytest-dev` once it has some happy users other than yourself. From 91b4b229aa82711c3ee4eaa8159fe5face1bbcfb Mon Sep 17 00:00:00 2001 From: Raphael Pierzina Date: Sat, 15 Jul 2017 16:48:02 +0200 Subject: [PATCH 2/5] Update documentation for testing plugin code --- doc/en/writing_plugins.rst | 81 ++++++++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 21 deletions(-) diff --git a/doc/en/writing_plugins.rst b/doc/en/writing_plugins.rst index 25097db6d..85c9e6b71 100644 --- a/doc/en/writing_plugins.rst +++ b/doc/en/writing_plugins.rst @@ -286,34 +286,73 @@ the ``--trace-config`` option. Testing plugins --------------- -pytest comes with some facilities that you can enable for testing your -plugin. Given that you have an installed plugin you can enable the -:py:class:`testdir <_pytest.pytester.Testdir>` fixture via specifying a -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:: +pytest comes with a plugin named ``pytester`` that helps you write tests for +your plugin code. The plugin is disabled by default, so you will have to enable +it before you can use it. - # 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. + +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(""" - def test_example(): - pass - """) - result = testdir.runpytest("--verbose") - result.stdout.fnmatch_lines(""" - test_example* + def test_hello_default(hello): + assert hello() == "Hello World!" + + def test_hello_name(hello, name): + assert hello(name) == "Hello {0}!".format(name) """) -Note that by default ``testdir.runpytest()`` will perform a pytest -in-process. You can pass the command line option ``--runpytest=subprocess`` -to have it happen in a subprocess. + # run all tests with pytest + result = testdir.runpytest() + + # 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`: From e73a2f7ad98e35ec6ee972d2003a417731c1eb86 Mon Sep 17 00:00:00 2001 From: Raphael Pierzina Date: Wed, 19 Jul 2017 18:57:32 +0200 Subject: [PATCH 3/5] Add changelog entry changelog/971.doc --- changelog/971.doc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/971.doc diff --git a/changelog/971.doc b/changelog/971.doc new file mode 100644 index 000000000..e182cf8ee --- /dev/null +++ b/changelog/971.doc @@ -0,0 +1 @@ +Extend documentation for testing plugin code with the ``pytester`` plugin. From d06d97a7ac6b9f6c723eadaa2fc3fd59e2f91b4f Mon Sep 17 00:00:00 2001 From: Raphael Pierzina Date: Wed, 19 Jul 2017 19:42:33 +0200 Subject: [PATCH 4/5] Remove unnecessary comma from docs --- doc/en/writing_plugins.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/writing_plugins.rst b/doc/en/writing_plugins.rst index 85c9e6b71..ad568ee33 100644 --- a/doc/en/writing_plugins.rst +++ b/doc/en/writing_plugins.rst @@ -349,7 +349,7 @@ return a result object, with which we can assert the tests' outcomes. result.assert_outcomes(passed=4) -For more information about the result object, that ``runpytest()`` returns, and +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. From 1ac02b8a3bb41864ffe2c2aa028ef385adb559b8 Mon Sep 17 00:00:00 2001 From: Raphael Pierzina Date: Wed, 19 Jul 2017 20:14:46 +0200 Subject: [PATCH 5/5] Add plugin code --- doc/en/writing_plugins.rst | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/doc/en/writing_plugins.rst b/doc/en/writing_plugins.rst index ad568ee33..861f2f48a 100644 --- a/doc/en/writing_plugins.rst +++ b/doc/en/writing_plugins.rst @@ -311,6 +311,34 @@ 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.