ModuleNotFoundError with pytest

ε祈祈猫儿з 提交于 2020-06-24 11:43:05

问题


I want my tests folder separate to my application code. My project structure is like so

myproject/
  myproject/
    myproject.py
    moduleone.py
  tests/
    myproject_test.py

myproject.py

from moduleone import ModuleOne

class MyProject(object)
....

myproject_test.py

from myproject.myproject import MyProject
import pytest

...

I use myproject.myproject since I use the command

python -m pytest

from the project root directory ./myproject/

However, then the imports within those modules fail with

E ModuleNotFoundError: No module named 'moduleone'

I am running Python 3.7 and have read that since 3.3, empty __init__ files are no longer needed which means my project becomes an implicit namespace package

However, I have tried adding an __init__.py file in myproject/myproject/ and also tried adding a conftest.py file in myproject/ but neither works

I have read answers that say to mess with the paths and then upvoted comments in other questions saying not to.

What is the correct way and what am I missing?

EDIT;

Possibly related, I used a requirements.txt to install pytest using pip. Could this be related? And if so, what is the correct way to install pytest in this case?

EDIT 2:

One of the paths in sys.path is /usr/src/app/ which is a docker volume lined to /my/local/path/myproject/.

Should the volume be /my/local/path/myproject/myproject/ instead?


回答1:


Be sure to include . dot in the $PYTHONPATH env var.

You can use this code fragment to debug such issues:

import pprint
import sys
pprint.pprint(sys.path)

Your question managed to use myproject at three different levels. At least during debugging you might want to use three distinct names, to reduce possible confusion.




回答2:


Kept everything same and just added a blank test file at the root folder .. Solved

Here are the findings, this problem really bugged me for a while. My folder structure was

mathapp/
    - server.py  
    - configuration.py 
    - __init__.py 
    - static/ 
       - home.html  
tests/            
    - functional 
       - test_errors.py 
    - unit  
       - test_add.py

and pytest would complain with the ModuleNotFoundError.

I introduced a mock test file at the same level as mathsapp and tests directory. The file contained nothing. Now pytest does not complain.

Result without the file

$ pytest
============================= test session starts =============================
platform win32 -- Python 3.8.2, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\mak2006\workspace\0github\python-rest-app-cont
collected 1 item / 1 error

=================================== ERRORS ====================================
_______________ ERROR collecting tests/functional/test_func.py ________________
ImportError while importing test module 'C:\mainak\workspace\0github\python-rest-app-cont\tests\functional\test_func.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
tests\functional\test_func.py:4: in <module>
    from mathapp.service import sum
E   ModuleNotFoundError: No module named 'mathapp'
=========================== short test summary info ===========================
ERROR tests/functional/test_func.py
!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
============================== 1 error in 0.24s ===============================

Results with the file

$ pytest
============================= test session starts =============================
platform win32 -- Python 3.8.2, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\mak2006\workspace\0github\python-rest-app-cont
collected 2 items

tests\functional\test_func.py .                                          [ 50%]
tests\unit\test_unit.py .                                                [100%]

============================== 2 passed in 0.11s ==============================



回答3:


So it seems that the sys.path has to include the application directory rather than the project root folder containing the application directory and test directory.

So in my case /my/local/path/myproject/myproject/ had to be in sys.path rather than /my/local/path/myproject/.

Then I could run pytest in /my/local/path/myproject/ (didn't need python -m pytest). This meant that the modules within /myproject/myproject/ could find each other and the tests as well without any namespace nesting.

So my tests looked like

 from moduleone import ModuleOne
 import pytest

 def test_fun():
     assert ModuleOne.example_func() == True

That said, there seem to be many gotchas, so I have no idea if this is correct..




回答4:


I ran into this issue as well and am using poetry for dependency management and direnv for my project specific environment variables. Please note, I am relatively new to Python so I don't know if this is the correct fix.

Here is my entire .envrc file:

layout_poetry() {
  if [[ ! -f pyproject.toml ]]; then
    log_error 'No pyproject.toml found.  Use `poetry new` or `poetry init` to create one first.'
    exit 2
  fi

  local VENV=$(poetry env list --full-path | cut -d' ' -f1)
  if [[ -z $VENV || ! -d $VENV/bin ]]; then
    log_error 'No created poetry virtual environment found.  Use `poetry install` to create one first.'
    exit 2
  fi
  VENV=$VENV/bin
  export VIRTUAL_ENV=$(echo "$VENV" | rev | cut -d'/' -f2- | rev)
  export POETRY_ACTIVE=1
  PATH_add "$VENV"
}

layout poetry
export PYTHONDONTWRITEBYTECODE=1
export PYTHONPATH="$PWD/project_name"

I don't know if I need to layout poetry because it is supposed to be creating virtual environments for us already but this is what I coworker recommended so I went with it. Layout poetry also didn't work without that function and it didn't like when I added it to my zshenv so I added it here.

For this specific question, the last line is the money maker.



来源:https://stackoverflow.com/questions/54895002/modulenotfounderror-with-pytest

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!