【问题标题】:ModuleNotFoundError with pytestModuleNotFoundError 与 pytest
【发布时间】:2019-07-20 13:21:58
【问题描述】:

我希望我的tests folder separate 用于我的应用程序代码。我的项目结构是这样的

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

我的项目.py

from moduleone import ModuleOne

class MyProject(object)
....

myproject_test.py

from myproject.myproject import MyProject
import pytest

...

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

python -m pytest

从项目根目录./myproject/

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

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

我正在运行 Python 3.7,并且已阅读自 3.3 以来,不再需要空的 __init__ 文件,这意味着我的项目变成了 implicit namespace package

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

我有 read answersmess with the paths 说,然后在其他问题中投票给 cmets 说 not to

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

编辑;

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

编辑 2:

sys.path 中的路径之一是 /usr/src/app/,它是与 /my/local/path/myproject/ 对齐的 docker 卷。

音量是否应该改为/my/local/path/myproject/myproject/

【问题讨论】:

  • 老实说,这将是一场舆论战。您可以将测试文件夹移动到您的主结构中并从那里执行它,您可以按原样工作。不需要更改任何东西,因为导入路径是相关的。除此之外,您需要对测试文件中的路径进行猴子修补以包含目标目录,这不是一件坏事(意见)。只需知道您在做什么以及您在做什么。
  • Long cmets.. 您还可以(在命令行上)附加 PYTHONPATH 以包含目标目录。这意味着您不必从任何脚本中操作sys.path,但您会在运行测试时获得更新的路径。 PYTHONPATH=./myproject python -m pytest 就像你一样。
  • 您在项目结构中列出的目录中,哪些(如果有)在您的PYTHONPATH?
  • @JohnGordon 用新信息更新了问题
  • 您是否尝试将空的 init.py 添加到 ./tests 目录而不是您的项目目录。这听起来可能很奇怪,但值得一试。

标签: python python-3.x docker pytest


【解决方案1】:

解决方案:使用PYTHONPATH 环境。变量

PYTHONPATH=. pytest

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


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

如果您不想一直键入那个长命令,一种选择是在项目的根目录中创建一个Makefile,例如:

.PHONY: test
test:
    PYTHONPATH=. pytest

这让您可以简单地运行:

make test

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

【讨论】:

  • 请注意:makefile 需要制表符进行缩进,因此复制粘贴代码可能不起作用,因为它使用空格。
  • 感谢@SilverSlash!源代码实际上使用了制表符,但实际上,它在答案中呈现为空格。有谁知道如何解决这个问题?
  • 不幸的是,我认为这是 HTML 和网络浏览器的限制。
【解决方案2】:

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

【讨论】:

  • 这可以解决问题,谢谢。我可以知道为什么它通过在测试文件夹中添加 init.py 来改变 pytest 导入行为吗?
【解决方案3】:

确保在 $PYTHONPATH 环境变量中包含 . 点。

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

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

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

【讨论】:

    【解决方案4】:

    所以sys.path 似乎必须包含应用程序目录,而不是包含应用程序目录和测试目录的项目根文件夹。

    所以在我的情况下,/my/local/path/myproject/myproject/ 必须在 sys.path 而不是 /my/local/path/myproject/

    然后我可以在/my/local/path/myproject/ 中运行pytest(不需要python -m pytest)。这意味着/myproject/myproject/ 中的模块可以找到彼此以及测试,而无需任何命名空间嵌套。

    所以我的测试看起来像

     from moduleone import ModuleOne
     import pytest
    
     def test_fun():
         assert ModuleOne.example_func() == True
    

    也就是说,似乎有many gotchas,所以我不知道这是否正确..

    【讨论】:

      【解决方案5】:

      在我的例子中,我在我的测试目录中添加了一个__init__.py,里面有这个:

      import sys
      sys.path.append('.')
      

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

      【讨论】:

        【解决方案6】:

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

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

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

        并且 pytest 会抱怨 ModuleNotFoundError。

        我在 mathsapp 和 tests 目录中引入了一个模拟测试文件。该文件不包含任何内容。现在 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 ===============================
        

        文件结果

        $ 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 ==============================
        

        【讨论】:

          【解决方案7】:

          我也遇到了这个问题,我正在使用诗歌进行依赖管理,并将 direnv 用于我的项目特定环境变量。请注意,我对 Python 比较陌生,所以我不知道这是否是正确的解决方法。

          这是我的整个 .envrc 文件:

          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"
          

          我不知道我是否需要布置诗歌,因为它应该已经为我们创建了虚拟环境,但这是我同事推荐的,所以我同意了。如果没有这个功能,布局诗歌也无法工作,而且当我将它添加到我的 zshenv 时它不喜欢,所以我在这里添加了它。

          对于这个特定的问题,最后一行是赚钱的人。

          【讨论】:

            【解决方案8】:

            使用诗歌和 pytest 5.4.3,我有以下结构(为清楚起见,删除了一些文件夹/文件):

            项目结构

            .
            ├── my_app
            │   ├── __init__.py
            │   ├── main.py
            │   ├── model.py
            │   └── orm.py
            ├── poetry.lock
            ├── pyproject.toml
            ├── README.rst
            └── tests
                ├── __init__.py
                ├── conftest.py
                ├── test_my_app.py
                └── utilities
                    └── db_postgresql_inmemory.py
            

            测试/conftest.py

            pytest_plugins = [
                "utilities.db_postgresql_inmemory",
            ]
            

            它为夹具生成了一个找不到模块的错误:

            ImportError: Error importing plugin "utilities.db_postgresql_inmemory": No module named 'utilities'
            

            其他答案都不适合我,因为我试图补充:

            [me@linux ~/code/my_app]touch tests/utilities/__init__.py
            [me@linux ~/code/my_app]touch ./test_blank.py
            

            我可以通过 REMOVING 两个 __init__.py 文件来使从 conftest.py 的导入工作:

            [me@linux ~/code/my_app]rm tests/utilities/__init__.py tests/__init__.py
            

            【讨论】:

              【解决方案9】:

              在我的情况下,这是因为我在系统级别安装了pytest,而不是在我的虚拟环境中。

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

              在激活虚拟环境时安装pytest会解决这个问题。

              【讨论】:

                【解决方案10】:

                另一个建议

                看到这个答案:https://stackoverflow.com/a/69691436/595305

                【讨论】:

                  【解决方案11】:

                  我遇到了我解决的问题

                  • 使用pip install pytest 在我的项目的根目录下安装pytest
                  • 在我想要执行的test_file.py 的兄弟姐妹中添加空白__init__.py

                  【讨论】:

                    【解决方案12】:

                    就我而言,我创建了一个单独的应用程序,用于测试同一级别的__init__.pyconftest.py。删除__init__.py 后错误消失了。

                    归功于qci-amos

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2021-11-09
                      • 2020-01-18
                      • 2022-11-09
                      • 1970-01-01
                      • 2021-12-04
                      • 2015-03-13
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多