Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test discovery finds module that doesn't exist #9586

Open
jaraco opened this issue Feb 1, 2022 · 1 comment
Open

Test discovery finds module that doesn't exist #9586

jaraco opened this issue Feb 1, 2022 · 1 comment
Labels
plugin: doctests related to the doctests builtin plugin topic: collection related to the collection phase type: bug problem that needs to be addressed

Comments

@jaraco
Copy link
Contributor

jaraco commented Feb 1, 2022

In jaraco/inflect#135, the contributor has accidentally misnamed the package. They attempted to rename inflect (module) to inflect (package). Instead, by accident, they renamed inflect to inflect.inflect and as a result, created an empty inflect module (as a namespace package). I would have expected the tests to fail, but they did not. Something about the test collection caused pytest to find inflect/inflect.py as the top-level inflect module, masking the mistake.

troubleshooting

I tried to create a minimal reproducer, but the reproducer fails as expected:

draft $ tree
.
├── inflect
│   └── inflect.py
└── test_something.py

1 directory, 2 files
draft $ cat inflect/*
value = 'exists'
draft $ cat test*
import inflect


def test_something():
    assert inflect.value == 'exists'
draft $ pip-run pytest -- -m pytest
Collecting pytest
  Using cached pytest-6.2.5-py3-none-any.whl (280 kB)
Collecting py>=1.8.2
  Using cached py-1.11.0-py2.py3-none-any.whl (98 kB)
Collecting packaging
  Using cached packaging-21.3-py3-none-any.whl (40 kB)
Collecting pluggy<2.0,>=0.12
  Using cached pluggy-1.0.0-py2.py3-none-any.whl (13 kB)
Collecting iniconfig
  Using cached iniconfig-1.1.1-py2.py3-none-any.whl (5.0 kB)
Collecting toml
  Using cached toml-0.10.2-py2.py3-none-any.whl (16 kB)
Collecting attrs>=19.2.0
  Using cached attrs-21.4.0-py2.py3-none-any.whl (60 kB)
Collecting pyparsing!=3.0.5,>=2.0.2
  Using cached pyparsing-3.0.7-py3-none-any.whl (98 kB)
Installing collected packages: pyparsing, toml, py, pluggy, packaging, iniconfig, attrs, pytest
Successfully installed attrs-21.4.0 iniconfig-1.1.1 packaging-21.3 pluggy-1.0.0 py-1.11.0 pyparsing-3.0.7 pytest-6.2.5 toml-0.10.2
WARNING: You are using pip version 21.3.1; however, version 22.0.2 is available.
You should consider upgrading via the '/Library/Frameworks/Python.framework/Versions/3.10/bin/python3.10 -m pip install --upgrade pip' command.
====================================================================== test session starts =======================================================================
platform darwin -- Python 3.10.1, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /Users/jaraco/draft
collected 1 item                                                                                                                                                 

test_something.py F                                                                                                                                        [100%]

============================================================================ FAILURES ============================================================================
_________________________________________________________________________ test_something _________________________________________________________________________

    def test_something():
>       assert inflect.value == 'exists'
E       AttributeError: module 'inflect' has no attribute 'value'

test_something.py:5: AttributeError
==================================================================== short test summary info =====================================================================
FAILED test_something.py::test_something - AttributeError: module 'inflect' has no attribute 'value'
======================================================================= 1 failed in 0.03s ========================================================================

I'm confident that one of the plugins (doctests, mypy, black, flake8, ...) is probably implicated, but when I try to enable doctests, I get another error:

draft $ pip-run -q pytest -- -m pytest --doctest-modules
====================================================================== test session starts =======================================================================
platform darwin -- Python 3.10.1, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /Users/jaraco/draft
collected 1 item / 1 error                                                                                                                                       

============================================================================= ERRORS =============================================================================
______________________________________________________________ ERROR collecting inflect/inflect.py _______________________________________________________________
/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-run-q5qn9lt4/_pytest/runner.py:311: in from_call
    result: Optional[TResult] = func()
/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-run-q5qn9lt4/_pytest/runner.py:341: in <lambda>
    call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-run-q5qn9lt4/_pytest/doctest.py:532: in collect
    module = import_path(self.fspath)
/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-run-q5qn9lt4/_pytest/pathlib.py:533: in import_path
    if module_file.endswith((".pyc", ".pyo")):
E   AttributeError: 'NoneType' object has no attribute 'endswith'
==================================================================== short test summary info =====================================================================
ERROR inflect/inflect.py - AttributeError: 'NoneType' object has no attribute 'endswith'
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
======================================================================== 1 error in 0.10s ========================================================================

It seems that error is occurring because inflect is discovered as a namespace package, but doesn't have a __file__ attribute.

I found that I could minimally reproduce the non-failure by (a) putting the test in a subdirectory and (b) invoking doctests.

draft $ tree
.
├── inflect
│   └── inflect.py
└── tests
    └── test_something.py

2 directories, 2 files
draft $ cat inflect/*
value = 'exists'
draft $ cat tests/*
import inflect


def test_something():
    assert inflect.value == 'exists'
draft $ pip-run -q pytest -- -m pytest --doctest-modules
====================================================================== test session starts =======================================================================
platform darwin -- Python 3.10.1, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /Users/jaraco/draft
collected 1 item                                                                                                                                                 

tests/test_something.py .                                                                                                                                  [100%]

======================================================================= 1 passed in 0.02s ========================================================================

As you can see, the test passes, even though the 'inflect' module should have only been found at inflect.inflect. Remove the --doctest-modules and the expected failure occurs:

draft $ pip-run -q pytest -- -m pytest
====================================================================== test session starts =======================================================================
platform darwin -- Python 3.10.1, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /Users/jaraco/draft
collected 1 item                                                                                                                                                 

tests/test_something.py F                                                                                                                                  [100%]

============================================================================ FAILURES ============================================================================
_________________________________________________________________________ test_something _________________________________________________________________________

    def test_something():
>       assert inflect.value == 'exists'
E       AttributeError: module 'inflect' has no attribute 'value'

tests/test_something.py:5: AttributeError
==================================================================== short test summary info =====================================================================
FAILED tests/test_something.py::test_something - AttributeError: module 'inflect' has no attribute 'value'
======================================================================= 1 failed in 0.03s ========================================================================

I'm fairly certain this missed failure is just another manifestation of #3396 and #8332. In this case, the namespace package was an accident.

@RonnyPfannschmidt
Copy link
Member

Yeah, what happens is that the file gets found, and then pytest adds the packages own namespace folder to sys.path in order to get the doctests out of the file

@Zac-HD Zac-HD added plugin: doctests related to the doctests builtin plugin topic: collection related to the collection phase type: bug problem that needs to be addressed labels Feb 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
plugin: doctests related to the doctests builtin plugin topic: collection related to the collection phase type: bug problem that needs to be addressed
Projects
None yet
Development

No branches or pull requests

3 participants