summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changelog/6082.bugfix.rst1
-rw-r--r--src/_pytest/doctest.py10
-rw-r--r--testing/test_doctest.py65
3 files changed, 71 insertions, 5 deletions
diff --git a/changelog/6082.bugfix.rst b/changelog/6082.bugfix.rst
new file mode 100644
index 000000000..24d389257
--- /dev/null
+++ b/changelog/6082.bugfix.rst
@@ -0,0 +1 @@
+Fix line detection for doctest samples inside ``property`` docstrings, as a workaround to `bpo-17446 <https://bugs.python.org/issue17446>`__.
diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py
index f7d96257e..c81f0bfd4 100644
--- a/src/_pytest/doctest.py
+++ b/src/_pytest/doctest.py
@@ -435,6 +435,16 @@ class DoctestModule(pytest.Module):
https://bugs.python.org/issue25532
"""
+ def _find_lineno(self, obj, source_lines):
+ """
+ Doctest code does not take into account `@property`, this is a hackish way to fix it.
+
+ https://bugs.python.org/issue17446
+ """
+ if isinstance(obj, property):
+ obj = getattr(obj, "fget", obj)
+ return doctest.DocTestFinder._find_lineno(self, obj, source_lines)
+
def _find(self, tests, obj, name, module, source_lines, globs, seen):
if _is_mocked(obj):
return
diff --git a/testing/test_doctest.py b/testing/test_doctest.py
index 79095e3e7..bd214e3de 100644
--- a/testing/test_doctest.py
+++ b/testing/test_doctest.py
@@ -288,12 +288,67 @@ class TestDoctests:
)
result = testdir.runpytest("--doctest-modules")
result.stdout.fnmatch_lines(
+ ["*hello*", "006*>>> 1/0*", "*UNEXPECTED*ZeroDivision*", "*1 failed*"]
+ )
+
+ def test_doctest_linedata_on_property(self, testdir):
+ testdir.makepyfile(
+ """
+ class Sample(object):
+ @property
+ def some_property(self):
+ '''
+ >>> Sample().some_property
+ 'another thing'
+ '''
+ return 'something'
+ """
+ )
+ result = testdir.runpytest("--doctest-modules")
+ result.stdout.fnmatch_lines(
[
- "*hello*",
- "*EXAMPLE LOCATION UNKNOWN, not showing all tests of that example*",
- "*1/0*",
- "*UNEXPECTED*ZeroDivision*",
- "*1 failed*",
+ "*= FAILURES =*",
+ "*_ [[]doctest[]] test_doctest_linedata_on_property.Sample.some_property _*",
+ "004 ",
+ "005 >>> Sample().some_property",
+ "Expected:",
+ " 'another thing'",
+ "Got:",
+ " 'something'",
+ "",
+ "*/test_doctest_linedata_on_property.py:5: DocTestFailure",
+ "*= 1 failed in *",
+ ]
+ )
+
+ def test_doctest_no_linedata_on_overriden_property(self, testdir):
+ testdir.makepyfile(
+ """
+ class Sample(object):
+ @property
+ def some_property(self):
+ '''
+ >>> Sample().some_property
+ 'another thing'
+ '''
+ return 'something'
+ some_property = property(some_property.__get__, None, None, some_property.__doc__)
+ """
+ )
+ result = testdir.runpytest("--doctest-modules")
+ result.stdout.fnmatch_lines(
+ [
+ "*= FAILURES =*",
+ "*_ [[]doctest[]] test_doctest_no_linedata_on_overriden_property.Sample.some_property _*",
+ "EXAMPLE LOCATION UNKNOWN, not showing all tests of that example",
+ "[?][?][?] >>> Sample().some_property",
+ "Expected:",
+ " 'another thing'",
+ "Got:",
+ " 'something'",
+ "",
+ "*/test_doctest_no_linedata_on_overriden_property.py:None: DocTestFailure",
+ "*= 1 failed in *",
]
)