Commits

Danilo Bellini committed 5162e91

Doctests xfail/skip & neglect empty textfile

Comments (0)

Files changed (2)

_pytest/doctest.py

             tw.line(line)
         self.reprlocation.toterminal(tw)
 
-class DoctestItem(pytest.Item):
+class DoctestItem(pytest.Function):
     def __init__(self, name, parent, runner=None, dtest=None):
+        self.obj = self.runtest
         super(DoctestItem, self).__init__(name, parent)
         self.runner = runner
         self.dtest = dtest
 
     def runtest(self):
-        self.runner.run(self.dtest)
+        try:
+            self.runner.run(self.dtest)
+        except:
+            import sys
+            e = getattr(sys.exc_info()[1], "exc_info", [type(None)])
+            if issubclass(e[0], (pytest.skip.Exception,
+                                 pytest.xfail.Exception)):
+                raise e[1]
+            raise
 
     def repr_failure(self, excinfo):
         doctest = py.std.doctest
     def reportinfo(self):
         return self.fspath, None, "[doctest] %s" % self.name
 
-class DoctestTextfile(DoctestItem, pytest.File):
-    def runtest(self):
+class DoctestTextfile(pytest.File):
+    def collect(self):
+        import os
         doctest = py.std.doctest
+        filename = str(self.fspath)
+        name = os.path.basename(filename)
+        with open(filename, "r") as f:
+            text = f.read()
+        self.obj = text
         # satisfy `FixtureRequest` constructor...
         self.funcargs = {}
         self._fixtureinfo = FuncFixtureInfo((), [], {})
         fixture_request = FixtureRequest(self)
-        failed, tot = doctest.testfile(
-            str(self.fspath), module_relative=False,
-            optionflags=doctest.ELLIPSIS,
-            extraglobs=dict(getfixture=fixture_request.getfuncargvalue),
-            raise_on_error=True, verbose=0)
+        doctest_globals = dict(getfixture=fixture_request.getfuncargvalue,
+                               __name__="__main__")
+        # uses internal doctest module parsing mechanism
+        parser = doctest.DocTestParser()
+        runner = doctest.DebugRunner(verbose=0, optionflags=doctest.ELLIPSIS)
+        test = parser.get_doctest(text, doctest_globals, name, filename, 0)
+        if test.examples: # skip empty doctests
+            yield DoctestItem(test.name, self, runner, test)
 
 class DoctestModule(pytest.File):
     def collect(self):
             module = self.config._conftest.importconftest(self.fspath)
         else:
             module = self.fspath.pyimport()
+        self.obj = module
         # satisfy `FixtureRequest` constructor...
         self.funcargs = {}
         self._fixtureinfo = FuncFixtureInfo((), [], {})

testing/test_doctest.py

             #print "checking that %s returns custom items" % (x,)
             items, reprec = testdir.inline_genitems(x)
             assert len(items) == 1
-            assert isinstance(items[0], DoctestTextfile)
+            assert isinstance(items[0], DoctestItem)
+            assert isinstance(items[0].parent, DoctestTextfile)
         items, reprec = testdir.inline_genitems(w)
-        assert len(items) == 1
+        assert len(items) == 0
 
     def test_collect_module_empty(self, testdir):
         path = testdir.makepyfile(whatever="#")
         """)
         reprec = testdir.inline_run(p, "--doctest-modules")
         reprec.assertoutcome(failed=1, passed=1)
+
+    def test_doctestmodule_two_tests_one_xfail(self, testdir):
+        p = testdir.makepyfile('''
+            """ >>> pass """
+            import pytest
+            class MyClass:
+                """
+                >>> pytest.xfail("a strange message here")
+                """
+        ''')
+        reprec = testdir.inline_run(p, "--doctest-modules")
+        reprec.assertoutcome(failed=0, passed=1, skipped=1)
+
+        result = testdir.runpytest(p, "--doctest-modules")
+        result.stdout.fnmatch_lines([
+            "*1 xfailed*",
+        ])
+        result = testdir.runpytest(p, "--doctest-modules", "-rx")
+        result.stdout.fnmatch_lines([
+            "*XFAIL*",
+            "*reason:*a strange message here*",
+        ])
+        reprec = testdir.inline_run(p, "--doctest-modules", "--runxfail")
+        reprec.assertoutcome(failed=1, passed=1, skipped=0)
+
+    def test_doctestmodule_two_tests_one_skip(self, testdir):
+        p = testdir.makepyfile('''
+            """ >>> x = 3 """
+            import pytest
+            def my_function():
+                """
+                >>> pytest.skip("another strange message")
+                """
+        ''')
+        reprec = testdir.inline_run(p, "--doctest-modules")
+        reprec.assertoutcome(failed=0, passed=1, skipped=1)
+
+        result = testdir.runpytest(p, "--doctest-modules")
+        result.stdout.fnmatch_lines([
+            "*1 skipped*",
+        ])
+        result = testdir.runpytest(p, "--doctest-modules", "-rs")
+        result.stdout.fnmatch_lines([
+            "*SKIP*another strange message*",
+        ])