pytest 的 ModuleNotFoundError

myo*_*yol 32 python pytest python-3.x docker

我希望我的测试文件夹与我的应用程序代码分开。我的项目结构是这样的

myproject/
  myproject/
    myproject.py
    moduleone.py
  tests/
    myproject_test.py
Run Code Online (Sandbox Code Playgroud)

我的项目.py

from moduleone import ModuleOne

class MyProject(object)
....
Run Code Online (Sandbox Code Playgroud)

myproject_test.py

from myproject.myproject import MyProject
import pytest

...
Run Code Online (Sandbox Code Playgroud)

我使用myproject.myproject因为我使用命令

python -m pytest
Run Code Online (Sandbox Code Playgroud)

从项目根目录 ./myproject/

但是,然后这些模块中的导入失败

E ModuleNotFoundError: 没有名为“moduleone”的模块

我正在运行 Python 3.7 并已阅读自 3.3 以来,__init__不再需要空文件,这意味着我的项目成为隐式命名空间包

但是,我尝试在其中添加__init__.py文件myproject/myproject/并尝试在其中添加conftest.py文件myproject/但都不起作用

我已经阅读了一些答案,这些答案说要弄乱路径,然后在其他问题中投票说不要

什么是正确的方法,我错过了什么?

编辑;

可能相关,我使用 arequirements.txt使用 pip 安装 pytest。这可能有关系吗?如果是这样,在这种情况下安装 pytest 的正确方法是什么?

编辑2:

其中的路径之一sys.path/usr/src/app/docker 卷内衬到/my/local/path/myproject/.

音量应该/my/local/path/myproject/myproject/改为吗?

Art*_*mão 21

解决方案:使用PYTHONPATHenv. 无功

PYTHONPATH=. pytest
Run Code Online (Sandbox Code Playgroud)

正如@J_H 所提到的,您需要明确添加项目的根目录,因为pytest只添加到sys.path测试文件所在的目录(这就是@Mak2006 的答案有效的原因。)


好的做法:使用 Makefile 或其他一些自动化工具

如果您不想一直输入这么长的命令,一种选择是Makefile在项目的根目录中创建一个,例如,以下内容:

.PHONY: test
test:
    PYTHONPATH=. pytest
Run Code Online (Sandbox Code Playgroud)

这使您可以简单地运行:

.PHONY: test
test:
    PYTHONPATH=. pytest
Run Code Online (Sandbox Code Playgroud)

另一种常见的替代方法是使用一些标准测试工具,例如tox

  • 只是一个小注意事项:makefile 需要制表符进行缩进,因此复制粘贴代码可能不起作用,因为它使用空格。 (5认同)

Sta*_*agg 18

就我而言,我将一个添加__init__.py到我的测试目录中,其中包含以下内容:

import sys
sys.path.append('.')
Run Code Online (Sandbox Code Playgroud)

我的应用程序代码与我的测试目录处于同一级别。

  • 添加这个解决了我的问题。 (2认同)

J_H*_*J_H 16

确保.$PYTHONPATHenv var 中包含点。

使用$ python -m site, 或此代码片段来调试此类问题:

import pprint
import sys
pprint.pprint(sys.path)
Run Code Online (Sandbox Code Playgroud)

您的问题设法myproject在三个不同的级别上使用。至少在调试期间,您可能希望使用三个不同的名称,以减少可能的混淆。


Erf*_*fan 13

不确定此解决方案是否特定于我的问题,但我只是将其添加__init__.py到我的tests文件夹中即可解决问题。

  • 我的“tests”文件夹已经有一个“__init__.py”文件,所以我可以确认这个解决方案不是通用的。 (24认同)
  • 这可以解决问题,谢谢。我可以知道为什么它通过在测试文件夹中添加 __init__.py 来改变 pytest 导入行为吗? (3认同)

Qin*_*ang 9

就我而言,这是因为我安装pytest在系统级别,但没有安装在虚拟环境中。

您可以通过 进行测试python -m pytest。如果您看到,ModuleNotFoundError: No module named 'pytest'那么您pytest处于系统级别。

pytest激活虚拟环境时安装将解决此问题。

  • 就我而言,它安装在系统和 virtualenv 级别。但只有“python3 -m pytest”有效。 (2认同)

kay*_*kay 8

在2023.02中,根据pytest 的文档,您只需将以下配置添加到您的 pyproject.toml 即可解决此问题

[tool.pytest.ini_options]
pythonpath = "src"
addopts = [
    "--import-mode=importlib",
]
Run Code Online (Sandbox Code Playgroud)


Wes*_*eek 7

更好的解决方案

尝试将__init__.py以下内容添加到您的测试目录(模块的上一级):

import sys
sys.path.append('.')
sys.path.append('./my_module')
Run Code Online (Sandbox Code Playgroud)

您的文件结构应如下所示:

project
  my_module
    package.py
  tests
    __init__.py
    my_tests.py
Run Code Online (Sandbox Code Playgroud)

第一个追加sys.path将使您能够从中导入<your-module-name>,第二个追加将使您的包能够正常导入。

在您的测试中,您可以使用 using 进行导入from my_module.package import function,而在模块中则可以简单地使用 进行导入from package import function


编辑:似乎这个解决方案并不通用(就像其他解决方案一样)。

我能够使用此答案的帮助解决此问题。添加__init__.py到您的主模块目录,其中包含

project
  my_module
    package.py
  tests
    __init__.py
    my_tests.py
Run Code Online (Sandbox Code Playgroud)

我还在__init__.py我的目录中添加了另一个tests(感谢这个答案

import pathlib, sys
sys.path.append(str(pathlib.Path(__file__).parent))
Run Code Online (Sandbox Code Playgroud)


小智 5

保持一切相同,只是在根文件夹中添加一个空白测试文件..已解决

这是调查结果,这个问题确实困扰了我一段时间。我的文件夹结构是

mathapp/
    - server.py  
    - configuration.py 
    - __init__.py 
    - static/ 
       - home.html  
tests/            
    - functional 
       - test_errors.py 
    - unit  
       - test_add.py
Run Code Online (Sandbox Code Playgroud)

pytest 会抱怨 ModuleNotFoundError。

我引入了与 mathsapp 和测试目录处于同一级别的模拟测试文件。该文件不包含任何内容。现在 pytest 不再抱怨。

没有文件的结果

$ 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 ===============================
Run Code Online (Sandbox Code Playgroud)

结果与文件

$ 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 ==============================
Run Code Online (Sandbox Code Playgroud)