diff options
Diffstat (limited to 'tests/conftest.py')
| -rw-r--r-- | tests/conftest.py | 140 |
1 files changed, 131 insertions, 9 deletions
diff --git a/tests/conftest.py b/tests/conftest.py index c83c3f94b..6fab88b12 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,19 +1,25 @@ # -*- coding: utf-8 -*- +from __future__ import print_function + import sys import subprocess +from collections import namedtuple import pytest -from six import StringIO +from six import StringIO, string_types -from util import SphinxTestApp, path +import util @pytest.fixture -def app_params(request): +def app_params(request, test_params, shared_result): """ parameters that is specified by 'pytest.mark.sphinx' for sphinx.application.Sphinx initialization """ + + # ##### process pytest.mark.sphinx + markers = request.node.get_marker("sphinx") pargs = {} kwargs = {} @@ -26,17 +32,99 @@ def app_params(request): kwargs.update(info.kwargs) args = [pargs[i] for i in sorted(pargs.keys())] - return args, kwargs + + # ##### process pytest.mark.test_params + + if test_params['shared_result']: + if 'srcdir' in kwargs: + raise pytest.Exception('You can not spcify shared_result and ' + 'srcdir in same time.') + kwargs['srcdir'] = test_params['shared_result'] + restore = shared_result.restore(test_params['shared_result']) + kwargs.update(restore) + + # ##### prepare Application params + + if 'srcdir' in kwargs: + srcdir = util.tempdir / kwargs['srcdir'] + else: + srcdir = util.tempdir / kwargs.get('testroot', 'root') + kwargs['srcdir'] = srcdir + + if kwargs.get('testroot') is None: + testroot_path = util.rootdir / 'root' + else: + testroot_path = util.rootdir / 'roots' / ('test-' + kwargs['testroot']) + + if not srcdir.exists(): + testroot_path.copytree(srcdir) + + return namedtuple('app_params', 'args,kwargs')(args, kwargs) + + +@pytest.fixture +def test_params(request): + """ + test parameters that is specified by 'pytest.mark.test_params' + + :param Union[str] shared_result: + If the value is provided, app._status and app._warning objects will be + shared in the parametrized test functions and/or test functions that + have same 'shared_result' value. + **NOTE**: You can not specify shared_result and srcdir in same time. + """ + env = request.node.get_marker('test_params') + kwargs = env.kwargs if env else {} + result = { + 'shared_result': None, + } + result.update(kwargs) + + if (result['shared_result'] and + not isinstance(result['shared_result'], string_types)): + raise pytest.Exception('You can only provide a string type of value ' + 'for "shared_result" ') + return result + + +class SphinxTestAppWrapperForSkipBuilding(object): + """ + This class is a wrapper for SphinxTestApp to speed up the test by skipping + `app.build` process if it is already built and there is even one output + file. + """ + + def __init__(self, app_): + self.app = app_ + + def __getattr__(self, name): + return getattr(self.app, name) + + def build(self, *args, **kw): + if not self.app.outdir.listdir(): + # if listdir is empty, do build. + self.app.build(*args, **kw) + # otherwise, we can use built cache @pytest.fixture(scope='function') -def app(app_params, make_app): +def app(test_params, app_params, make_app, shared_result): """ provides sphinx.application.Sphinx object """ args, kwargs = app_params app_ = make_app(*args, **kwargs) - return app_ + yield app_ + + print('# testroot:', kwargs.get('testroot', 'root')) + print('# builder:', app_.buildername) + print('# srcdir:', app_.srcdir) + print('# outdir:', app_.outdir) + print('# status:', '\n' + app_._status.getvalue()) + print('# warning:', '\n' + app_._warning.getvalue()) + + if test_params['shared_result']: + shared_result.store(test_params['shared_result'], app_) @pytest.fixture(scope='function') @@ -56,7 +144,7 @@ def warning(app): @pytest.fixture() -def make_app(): +def make_app(test_params): """ provides make_app function to initialize SphinxTestApp instance. if you want to initialize 'app' in your test function. please use this @@ -69,8 +157,10 @@ def make_app(): status, warning = StringIO(), StringIO() kwargs.setdefault('status', status) kwargs.setdefault('warning', warning) - app_ = SphinxTestApp(*args, **kwargs) + app_ = util.SphinxTestApp(*args, **kwargs) apps.append(app_) + if test_params['shared_result']: + app_ = SphinxTestAppWrapperForSkipBuilding(app_) return app_ yield make @@ -79,6 +169,38 @@ def make_app(): app_.cleanup() +class SharedResult(object): + cache = {} + + def store(self, key, app_): + if key in self.cache: + return + data = { + 'status': app_._status.getvalue(), + 'warning': app_._warning.getvalue(), + } + self.cache[key] = data + + def restore(self, key): + if key not in self.cache: + return {} + data = self.cache[key] + return { + 'status': StringIO(data['status']), + 'warning': StringIO(data['warning']), + } + + +@pytest.fixture +def shared_result(): + return SharedResult() + + +@pytest.fixture(scope='module', autouse=True) +def _shared_result_cache(): + SharedResult.cache.clear() + + @pytest.fixture def if_graphviz_found(app): """ @@ -105,4 +227,4 @@ def tempdir(tmpdir): temporary directory that wrapped with `path` class. this fixture is for compat with old test implementation. """ - return path(tmpdir) + return util.path(tmpdir) |
