mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
pytest optimizatoin:
- remote using deprecated decorators - remove gen_with_app - remove yield testing - remove pytest warnings - refactoring
This commit is contained in:
@@ -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,114 @@ 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['specific_srcdir'] and 'srcdir' not in kwargs:
|
||||
kwargs['srcdir'] = test_params['specific_srcdir']
|
||||
|
||||
if 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, bool, None] specific_srcdir:
|
||||
If True, testroot directory will be copied into
|
||||
'<TMPDIR>/<TEST FUNCTION NAME>'.
|
||||
If string is specified, it copied into '<TMPDIR>/<THE STRING>'.
|
||||
You can used this feature for providing special crafted source
|
||||
directory. Also you can used for sharing source directory for
|
||||
parametrized testing and/or inter test functions. Default is None.
|
||||
:param Union[str, bool, None] shared_result:
|
||||
If True, app._status and app._warning objects will be shared in the
|
||||
parametrized test functions. If string is specified, the objects will
|
||||
be shred in the test functions that have same 'shared_result' value.
|
||||
If you don't specify specific_srcdir, this option override
|
||||
specific_srcdir param by 'shared_result' value. Default is None.
|
||||
"""
|
||||
env = request.node.get_marker('test_params')
|
||||
kwargs = env.kwargs if env else {}
|
||||
result = {
|
||||
'specific_srcdir': None,
|
||||
'shared_result': None,
|
||||
}
|
||||
result.update(kwargs)
|
||||
|
||||
if (result['shared_result'] and
|
||||
not isinstance(result['shared_result'], string_types)):
|
||||
result['shared_result'] = request.node.originalname or request.node.name
|
||||
|
||||
if result['shared_result'] and not result['specific_srcdir']:
|
||||
result['specific_srcdir'] = result['shared_result']
|
||||
|
||||
if (result['specific_srcdir'] and
|
||||
not isinstance(result['specific_srcdir'], string_types)):
|
||||
result['specific_srcdir'] = request.node.originalname or request.node.name
|
||||
|
||||
return result
|
||||
|
||||
|
||||
class AppWrapper(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 +159,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 +172,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_ = AppWrapper(app_)
|
||||
return app_
|
||||
yield make
|
||||
|
||||
@@ -79,6 +184,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 +242,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)
|
||||
|
||||
Reference in New Issue
Block a user