From 265cc2cfece4ee5a2094b7c02dd80cd6099af60f Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 9 Nov 2020 14:08:27 +0000 Subject: [PATCH] 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 . --- changelog/8016.bugfix.rst | 1 + src/_pytest/main.py | 14 ++++++++------ testing/test_doctest.py | 11 ++++++++--- 3 files changed, 17 insertions(+), 9 deletions(-) create mode 100644 changelog/8016.bugfix.rst diff --git a/changelog/8016.bugfix.rst b/changelog/8016.bugfix.rst new file mode 100644 index 000000000..94539af5c --- /dev/null +++ b/changelog/8016.bugfix.rst @@ -0,0 +1 @@ +Fixed only one doctest being collected when using ``pytest --doctest-modules path/to/an/__init__.py``. diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 04b51ac00..4234ae951 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -765,12 +765,14 @@ class Session(nodes.FSCollector): self._notfound.append((report_arg, col)) continue - # If __init__.py was the only file requested, then the matched node will be - # the corresponding Package, and the first yielded item will be the __init__ - # Module itself, so just use that. If this special case isn't taken, then all - # the files in the package will be yielded. - if argpath.basename == "__init__.py": - assert isinstance(matching[0], nodes.Collector) + # If __init__.py was the only file requested, then the matched + # node will be the corresponding Package (by default), and the + # first yielded item will be the __init__ Module itself, so + # just use that. If this special case isn't taken, then all the + # files in the package will be yielded. + if argpath.basename == "__init__.py" and isinstance( + matching[0], Package + ): try: yield next(iter(matching[0].collect())) except StopIteration: diff --git a/testing/test_doctest.py b/testing/test_doctest.py index 8f31cb606..6e3880330 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -68,9 +68,13 @@ class TestDoctests: assert isinstance(items[0].parent, DoctestModule) 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( - whatever=""" + **{ + filename: """ '# Empty' def my_func(): ">>> magic = 42 " @@ -84,7 +88,8 @@ class TestDoctests: # This is another function >>> import os # this one does have a doctest ''' - """ + """, + }, ) for p in (path, pytester.path): items, reprec = pytester.inline_genitems(p, "--doctest-modules")