Add a new doctest_namespace fixture

This fixture can be used to inject names into the namespace in which
your doctests run.
This commit is contained in:
Matt Williams 2016-03-02 12:43:57 +00:00
parent 5a2500800d
commit 891e029518
5 changed files with 91 additions and 1 deletions

View File

@ -59,6 +59,7 @@ Marc Schlaich
Mark Abramowitz
Markus Unterwaditzer
Martijn Faassen
Matt Williams
Michael Aquilina
Michael Birtwell
Michael Droettboom

View File

@ -3,7 +3,8 @@
**New Features**
*
* New ``doctest_namespace`` fixture for injecting names into the
namespace in which your doctests run.
*

View File

@ -71,6 +71,8 @@ class DoctestItem(pytest.Item):
if self.dtest is not None:
self.fixture_request = _setup_fixtures(self)
globs = dict(getfixture=self.fixture_request.getfuncargvalue)
for name, value in self.fixture_request.getfuncargvalue('doctest_namespace').items():
globs[name] = value
self.dtest.globs.update(globs)
def runtest(self):
@ -159,6 +161,9 @@ class DoctestTextfile(DoctestItem, pytest.Module):
if '__name__' not in globs:
globs['__name__'] = '__main__'
for name, value in fixture_request.getfuncargvalue('doctest_namespace').items():
globs[name] = value
optionflags = get_optionflags(self)
runner = doctest.DebugRunner(verbose=0, optionflags=optionflags,
checker=_get_checker())
@ -288,3 +293,11 @@ def _get_allow_bytes_flag():
"""
import doctest
return doctest.register_optionflag('ALLOW_BYTES')
@pytest.fixture(scope='session')
def doctest_namespace():
"""
Inject names into the doctest namespace.
"""
return dict()

View File

@ -102,4 +102,29 @@ itself::
>>> get_unicode_greeting() # doctest: +ALLOW_UNICODE
'Hello'
The 'doctest_namespace' fixture
-------------------------------
The ``doctest_namespace`` fixture can be used to inject items into the
namespace in which your doctests run. It is intended to be used within
your own fixtures to provide the tests that use them with context.
``doctest_namespace`` is a standard ``dict`` object into which you
place the objects you want to appear in the doctest namespace::
# content of conftest.py
import numpy
@pytest.fixture(autouse=True)
def add_np(doctest_namespace):
doctest_namespace['np'] = numpy
which can then be used in your doctests directly::
# content of numpy.py
def arange():
"""
>>> a = np.arange(10)
>>> len(a)
10
"""
pass

View File

@ -713,3 +713,53 @@ class TestDoctestAutoUseFixtures:
result = testdir.runpytest('--doctest-modules')
assert 'FAILURES' not in str(result.stdout.str())
result.stdout.fnmatch_lines(['*=== 1 passed in *'])
class TestDoctestNamespaceFixture:
SCOPES = ['module', 'session', 'class', 'function']
@pytest.mark.parametrize('scope', SCOPES)
def test_namespace_doctestfile(self, testdir, scope):
"""
Check that inserting something into the namespace works in a
simple text file doctest
"""
testdir.makeconftest("""
import pytest
import contextlib
@pytest.fixture(autouse=True, scope="{scope}")
def add_contextlib(doctest_namespace):
doctest_namespace['cl'] = contextlib
""".format(scope=scope))
p = testdir.maketxtfile("""
>>> print(cl.__name__)
contextlib
""")
reprec = testdir.inline_run(p)
reprec.assertoutcome(passed=1)
@pytest.mark.parametrize('scope', SCOPES)
def test_namespace_pyfile(self, testdir, scope):
"""
Check that inserting something into the namespace works in a
simple Python file docstring doctest
"""
testdir.makeconftest("""
import pytest
import contextlib
@pytest.fixture(autouse=True, scope="{scope}")
def add_contextlib(doctest_namespace):
doctest_namespace['cl'] = contextlib
""".format(scope=scope))
p = testdir.makepyfile("""
def foo():
'''
>>> print(cl.__name__)
contextlib
'''
""")
reprec = testdir.inline_run(p, "--doctest-modules")
reprec.assertoutcome(passed=1)