Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/pytest-2' into pytest
Browse files Browse the repository at this point in the history
  • Loading branch information
smotornyuk committed Dec 19, 2019
2 parents bb3c8b5 + 274ed2c commit 67e8056
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 26 deletions.
45 changes: 41 additions & 4 deletions ckan/tests/helpers.py
Expand Up @@ -15,10 +15,8 @@
and make writing tests so much easier, that it's worth having them despite the
potential drawbacks.
Consider using :ref:`fixtures` whenever is possible for setting up initial
state of a test or creating related objects.
This module is reserved for these very useful functions.
New in CKAN 2.9: Consider using :ref:`fixtures` whenever possible for setting
up the initial state of a test or to create helpers objects like client apps.
"""

Expand All @@ -45,6 +43,22 @@
def reset_db():
"""Reset CKAN's database.
Rather than use this function directly, use the ``clean_db`` fixture
either for all tests in a class::
@pytest.mark.usefixtures("clean_db")
class TestExample(object):
def test_example(self):
or for a single test::
class TestExample(object):
@pytest.mark.usefixtures("clean_db")
def test_example(self):
If a test class uses the database, then it may call this function in its
``setup()`` method to make sure that it has a clean database to start with
(nothing left over from other test classes or from previous test runs).
Expand Down Expand Up @@ -167,6 +181,15 @@ def post(self, url, *args, **kwargs):
def _get_test_app():
"""Return a webtest.TestApp for CKAN, with legacy templates disabled.
Don't use this function directly, use the ``app`` fixture::
def test_dataset_search(self, app):
url = h.url_for('dataset.search')
response = app.get(url)
For functional tests that need to request CKAN pages or post to the API.
Unit tests shouldn't need this.
Expand All @@ -181,6 +204,20 @@ def _get_test_app():
class FunctionalTestBase(object):
"""A base class for functional test classes to inherit from.
Deprecated: Use the ``app``, ``clean_db``, ``ckan_config`` and
``with_plugins`` ref:`fixtures` as needed to create functional test
classes, eg::
@pytest.mark.ckan_config('ckan.plugins', 'image_view')
@pytest.mark.usefixtures('with_plugins')
@pytest.mark.usefixtures('clean_db')
class TestDatasetSearch(object):
def test_dataset_search(self, app):
url = h.url_for('dataset.search')
response = app.get(url)
Allows configuration changes by overriding _apply_config_changes and
resetting the CKAN config after your test class has run. It creates a
webtest.TestApp at self.app for your class to use to make HTTP requests
Expand Down
72 changes: 54 additions & 18 deletions ckan/tests/pytest_ckan/fixtures.py
Expand Up @@ -37,17 +37,27 @@

@pytest.fixture
def ckan_config(request, monkeypatch):
"""Configuration object used by application.
"""Allows to override the configuration object used by tests
Takes into account config patches introduced by `ckan_config`
mark. For using custom config in the whole test, apply
`ckan_config` mark to it and inject `ckan_config` fixture:
Takes into account config patches introduced by the ``ckan_config``
mark.
If you just want to set one or more configuration options for the
scope of a test (or a test class), use the ``ckan_config`` mark::
@pytest.mark.ckan_config('ckan.auth.create_unowned_dataset', True)
def test_auth_create_unowned_dataset():
# ...
To use the custom config inside a test, apply the
``ckan_config`` mark to it and inject the ``ckan_config`` fixture:
.. literalinclude:: /../ckan/tests/pytest_ckan/test_fixtures.py
:start-after: # START-CONFIG-OVERRIDE
:end-before: # END-CONFIG-OVERRIDE
Otherwise, when change only need to be applied locally, use
If the change only needs to be applied locally, use the
``monkeypatch`` fixture
.. literalinclude:: /../ckan/tests/test_common.py
Expand All @@ -65,56 +75,84 @@ def ckan_config(request, monkeypatch):

@pytest.fixture
def make_app(ckan_config):
"""Factory for client app.
"""Factory for client app instances.
Prefer using ``app`` instead if you have no need in lazy instantiation.
Unless you need to create app instances lazily for some reason,
use the ``app`` fixture instead.
"""
return test_helpers._get_test_app


@pytest.fixture
def app(make_app):
"""Instance of client app.
"""Returns a client app instance to use in functional tests
To use it, just add the ``app`` parameter to your test function signature::
def test_dataset_search(self, app):
url = h.url_for('dataset.search')
response = app.get(url)
"""
return make_app()


@pytest.fixture(scope=u"session")
def reset_db():
"""Callable for setting DB into initial state. Prefer using
``clean_db``.
"""Callable for resetting the database to the initial state.
If possible use the ``clean_db`` fixture instead.
"""
return test_helpers.reset_db


@pytest.fixture(scope=u"session")
def reset_index():
"""Callable for cleaning search index. Prefer using ``clean_index``.
"""Callable for cleaning search index.
If possible use the ``clean_index`` fixture instead.
"""
return search.clear_all


@pytest.fixture
def clean_db(reset_db):
"""Start test with database in initial state.
"""Resets the database to the initial state.
This can be used either for all tests in a class::
@pytest.mark.usefixtures("clean_db")
class TestExample(object):
def test_example(self):
or for a single test::
class TestExample(object):
@pytest.mark.usefixtures("clean_db")
def test_example(self):
"""
reset_db()


@pytest.fixture
def clean_index(reset_index):
"""Start test with empty search index.
"""Clear search index before starting the test.
"""
reset_index()


@pytest.fixture
def with_plugins(ckan_config):
"""Load all plugins specified by ``ckan.plugins`` config option in the
beginning of the test. When test ends (event with fail) unload all
those plugins in reverse order.
"""Load all plugins specified by the ``ckan.plugins`` config option
at the beginning of the test. When the test ends (even it fails), it will
unload all the plugins in the reverse order.
.. literalinclude:: /../ckan/tests/test_factories.py
:start-after: # START-CONFIG-OVERRIDE
Expand All @@ -125,9 +163,7 @@ def with_plugins(ckan_config):
for plugin in plugins:
if not ckan.plugins.plugin_loaded(plugin):
ckan.plugins.load(plugin)
# ckan.plugins.load_all()
yield
for plugin in reversed(plugins):
if ckan.plugins.plugin_loaded(plugin):
ckan.plugins.unload(plugin)
# ckan.plugins.unload_all()
4 changes: 2 additions & 2 deletions ckan/tests/test_coding_standards.py
Expand Up @@ -218,7 +218,7 @@ def find_unprefixed_string_literals(filename):
for lineno, line in renumerate(lines[:lineno]):
try:
i = line.rindex(quotes)
if (i > 1) and (line[i - 2:i].lower() == u"ur"):
if (i > 1) and (line[i - 2: i].lower() == u"ur"):
col_offset = i - 2
elif (i > 0) and (line[i - 1].lower() in u"rbu"):
col_offset = i - 1
Expand All @@ -227,7 +227,7 @@ def find_unprefixed_string_literals(filename):
break
except ValueError:
continue
leading = lines[lineno][col_offset - 1:col_offset + 1]
leading = lines[lineno][col_offset - 1: col_offset + 1]
if leading[:-1] == u"[": # data['id'] is unambiguous, ignore these
continue
if leading[-1:] not in u"ub": # Don't allow capital U and B either
Expand Down
4 changes: 2 additions & 2 deletions doc/contributing/testing.rst
Expand Up @@ -53,8 +53,8 @@ Fast
``setup_class()`` methods, saved against the ``self`` attribute of test
classes, or in test helper modules).

Instead use fixtures that create test objects and return them, and
inject into every method only required fixtures.
Instead use fixtures that create test objects and pass them as parameters, and
inject into every method only the required fixtures.

* Where appropriate, use the ``monkeypatch`` `fixture
<https://docs.pytest.org/en/latest/monkeypatch.html>`_ to avoid
Expand Down

0 comments on commit 67e8056

Please sign in to comment.