Skip to content

Commit acec0b6

Browse files
authored
Fix usage of pytester with doctests (#6802)
Use `request.node.name` instead of `request.function.__name__`: `request.function` is `None` with `DoctestItem`s.
1 parent 197b7c3 commit acec0b6

File tree

3 files changed

+32
-4
lines changed

3 files changed

+32
-4
lines changed

changelog/6802.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
The :fixture:`testdir fixture <testdir>` works within doctests now.

src/_pytest/pytester.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,11 @@ def __init__(self, request: FixtureRequest, tmpdir_factory: TempdirFactory) -> N
543543
self._mod_collections = (
544544
WeakKeyDictionary()
545545
) # type: WeakKeyDictionary[Module, List[Union[Item, Collector]]]
546-
name = request.function.__name__
546+
if request.function:
547+
name = request.function.__name__ # type: str
548+
else:
549+
name = request.node.name
550+
self._name = name
547551
self.tmpdir = tmpdir_factory.mktemp(name, numbered=True)
548552
self.test_tmproot = tmpdir_factory.mktemp("tmp-" + name, numbered=True)
549553
self.plugins = [] # type: List[Union[str, _PluggyPlugin]]
@@ -617,7 +621,7 @@ def to_text(s):
617621

618622
if lines:
619623
source = "\n".join(to_text(x) for x in lines)
620-
basename = self.request.function.__name__
624+
basename = self._name
621625
items.insert(0, (basename, source))
622626

623627
ret = None
@@ -720,7 +724,7 @@ def copy_example(self, name=None):
720724
example_dir = example_dir.join(*extra_element.args)
721725

722726
if name is None:
723-
func_name = self.request.function.__name__
727+
func_name = self._name
724728
maybe_dir = example_dir / func_name
725729
maybe_file = example_dir / (func_name + ".py")
726730

@@ -1059,7 +1063,7 @@ def getmodulecol(self, source, configargs=(), withinit=False):
10591063
path = self.tmpdir.join(str(source))
10601064
assert not withinit, "not supported for paths"
10611065
else:
1062-
kw = {self.request.function.__name__: Source(source).strip()}
1066+
kw = {self._name: Source(source).strip()}
10631067
path = self.makepyfile(**kw)
10641068
if withinit:
10651069
self.makepyfile(__init__="#")

testing/test_pytester.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,29 @@ def test_hello(testdir):
8989
result.assert_outcomes(passed=1)
9090

9191

92+
def test_testdir_with_doctest(testdir):
93+
"""Check that testdir can be used within doctests.
94+
95+
It used to use `request.function`, which is `None` with doctests."""
96+
testdir.makepyfile(
97+
**{
98+
"sub/t-doctest.py": """
99+
'''
100+
>>> import os
101+
>>> testdir = getfixture("testdir")
102+
>>> str(testdir.makepyfile("content")).replace(os.sep, '/')
103+
'.../basetemp/sub.t-doctest0/sub.py'
104+
'''
105+
""",
106+
"sub/__init__.py": "",
107+
}
108+
)
109+
result = testdir.runpytest(
110+
"-p", "pytester", "--doctest-modules", "sub/t-doctest.py"
111+
)
112+
assert result.ret == 0
113+
114+
92115
def test_runresult_assertion_on_xfail(testdir) -> None:
93116
testdir.makepyfile(
94117
"""

0 commit comments

Comments
 (0)