main: fix only one doctest collected on pytest --doctest-modules __init__.py

When --doctest-modules is used, an `__init__.py` file is not a `Package`
but a `DoctestModule`, but some collection code assumed that
`__init__.py` implies a `Package`. That code caused only a single test
to be collected in the scenario in the subject.

Tighten up this check to explicitly check for `Package`. There are
better solutions, but for another time.

Report & test by Nick Gates <nickgatzgates@gmail.com>.
This commit is contained in:
Ran Benita 2020-11-09 14:08:27 +00:00
parent e986d84466
commit 265cc2cfec
3 changed files with 17 additions and 9 deletions

View File

@ -0,0 +1 @@
Fixed only one doctest being collected when using ``pytest --doctest-modules path/to/an/__init__.py``.

View File

@ -765,12 +765,14 @@ class Session(nodes.FSCollector):
self._notfound.append((report_arg, col)) self._notfound.append((report_arg, col))
continue continue
# If __init__.py was the only file requested, then the matched node will be # If __init__.py was the only file requested, then the matched
# the corresponding Package, and the first yielded item will be the __init__ # node will be the corresponding Package (by default), and the
# Module itself, so just use that. If this special case isn't taken, then all # first yielded item will be the __init__ Module itself, so
# the files in the package will be yielded. # just use that. If this special case isn't taken, then all the
if argpath.basename == "__init__.py": # files in the package will be yielded.
assert isinstance(matching[0], nodes.Collector) if argpath.basename == "__init__.py" and isinstance(
matching[0], Package
):
try: try:
yield next(iter(matching[0].collect())) yield next(iter(matching[0].collect()))
except StopIteration: except StopIteration:

View File

@ -68,9 +68,13 @@ class TestDoctests:
assert isinstance(items[0].parent, DoctestModule) assert isinstance(items[0].parent, DoctestModule)
assert items[0].parent is items[1].parent assert items[0].parent is items[1].parent
def test_collect_module_two_doctest_no_modulelevel(self, pytester: Pytester): @pytest.mark.parametrize("filename", ["__init__", "whatever"])
def test_collect_module_two_doctest_no_modulelevel(
self, pytester: Pytester, filename: str,
) -> None:
path = pytester.makepyfile( path = pytester.makepyfile(
whatever=""" **{
filename: """
'# Empty' '# Empty'
def my_func(): def my_func():
">>> magic = 42 " ">>> magic = 42 "
@ -84,7 +88,8 @@ class TestDoctests:
# This is another function # This is another function
>>> import os # this one does have a doctest >>> import os # this one does have a doctest
''' '''
""" """,
},
) )
for p in (path, pytester.path): for p in (path, pytester.path):
items, reprec = pytester.inline_genitems(p, "--doctest-modules") items, reprec = pytester.inline_genitems(p, "--doctest-modules")