diff --git a/CHANGELOG b/CHANGELOG index 3cbd8c10a..e5221df04 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,9 @@ 2.8.0.dev (compared to 2.7.X) ----------------------------- +- fix issue768: docstrings found in python modules were not setting up session + fixtures. Thanks Jason R. Coombs for reporting and Bruno Oliveira for the PR. + - fix issue 808: pytest's internal assertion rewrite hook now implements the optional PEP302 get_data API so tests can access data files next to them. Thanks xmo-odoo for request and example and Bruno Oliveira for diff --git a/_pytest/doctest.py b/_pytest/doctest.py index 7c8190139..c6c60b9c2 100644 --- a/_pytest/doctest.py +++ b/_pytest/doctest.py @@ -2,7 +2,7 @@ from __future__ import absolute_import import traceback import pytest, py -from _pytest.python import FixtureRequest, FuncFixtureInfo +from _pytest.python import FixtureRequest from py._code.code import TerminalRepr, ReprFileLocation def pytest_addoption(parser): @@ -113,15 +113,7 @@ def get_optionflags(parent): class DoctestTextfile(DoctestItem, pytest.File): def runtest(self): import doctest - # satisfy `FixtureRequest` constructor... - self.funcargs = {} - fm = self.session._fixturemanager - def func(): - pass - self._fixtureinfo = fm.getfixtureinfo(node=self, func=func, - cls=None, funcargs=False) - fixture_request = FixtureRequest(self) - fixture_request._fillfixtures() + fixture_request = _setup_fixtures(self) failed, tot = doctest.testfile( str(self.fspath), module_relative=False, optionflags=get_optionflags(self), @@ -132,7 +124,7 @@ class DoctestModule(pytest.File): def collect(self): import doctest if self.fspath.basename == "conftest.py": - module = self.config._conftest._importconftest(self.fspath) + module = self.config.pluginmanager._importconftest(self.fspath) else: try: module = self.fspath.pyimport() @@ -142,9 +134,7 @@ class DoctestModule(pytest.File): else: raise # satisfy `FixtureRequest` constructor... - self.funcargs = {} - self._fixtureinfo = FuncFixtureInfo((), [], {}) - fixture_request = FixtureRequest(self) + fixture_request = _setup_fixtures(self) doctest_globals = dict(getfixture=fixture_request.getfuncargvalue) # uses internal doctest module parsing mechanism finder = doctest.DocTestFinder() @@ -154,3 +144,19 @@ class DoctestModule(pytest.File): extraglobs=doctest_globals): if test.examples: # skip empty doctests yield DoctestItem(test.name, self, runner, test) + + +def _setup_fixtures(doctest_item): + """ + Used by DoctestTextfile and DoctestModule to setup fixture information. + """ + def func(): + pass + + doctest_item.funcargs = {} + fm = doctest_item.session._fixturemanager + doctest_item._fixtureinfo = fm.getfixtureinfo(node=doctest_item, func=func, + cls=None, funcargs=False) + fixture_request = FixtureRequest(doctest_item) + fixture_request._fillfixtures() + return fixture_request diff --git a/testing/test_doctest.py b/testing/test_doctest.py index 2fc683b1a..882747b9e 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -368,3 +368,36 @@ class TestDoctests: reprec = testdir.inline_run(p, "--doctest-modules", "--junit-xml=junit.xml") reprec.assertoutcome(failed=1) + + def test_doctest_module_session_fixture(self, testdir): + """Test that session fixtures are initialized for doctest modules (#768) + """ + # session fixture which changes some global data, which will + # be accessed by doctests in a module + testdir.makeconftest(""" + import pytest + import sys + + @pytest.yield_fixture(autouse=True, scope='session') + def myfixture(): + assert not hasattr(sys, 'pytest_session_data') + sys.pytest_session_data = 1 + yield + del sys.pytest_session_data + """) + testdir.makepyfile(foo=""" + import sys + + def foo(): + ''' + >>> assert sys.pytest_session_data == 1 + ''' + + def bar(): + ''' + >>> assert sys.pytest_session_data == 1 + ''' + """) + result = testdir.runpytest("--doctest-modules") + result.stdout.fnmatch_lines('*2 passed*') +