我使用easy_install在Mac上安装pytest,并开始为一个具有如下文件结构的项目编写测试:

repo/
   |--app.py
   |--settings.py
   |--models.py
   |--tests/
          |--test_app.py

py运行。在repo目录中进行测试,一切都如您所料。

但是当我在Linux或Windows上尝试同样的事情时(两者都有pytest 2.2.3),每当它第一次从我的应用程序路径导入某些东西时,它就会发出吠叫。例如,from app import some_def_in_app。

我需要编辑我的PATH来运行py。测试这些系统?


是,如果您cd到测试目录,则源文件夹不在Python的路径中。

你有两个选择:

手动将路径添加到测试文件中。就像这样: 导入sys, OS myPath = os.path.dirname(os.path.abspath(__file__)) sys.path。insert(0, myPath + '/../') 使用env var PYTHONPATH=../运行测试。


我也有同样的问题。我通过在我的测试目录中添加一个空的__init__.py文件来修复它。


您可以在项目根中使用PYTHONPATH运行

PYTHONPATH=. py.test

或者使用pip install作为可编辑导入

pip install -e .   # install package using setup.py in editable mode

我不确定为什么是py。test不会在PYTHONPATH本身中添加当前目录,但这里有一个变通方法(从存储库的根目录执行):

python -m pytest tests/

它能工作是因为Python为你在PYTHONPATH中添加了当前目录。


我创建这个是为了回答你的问题和我自己的困惑。我希望这能有所帮助。注意py. conf文件中的PYTHONPATH。测试命令行和tox.ini。

https://github.com/jeffmacdonald/pytest_test

具体来说:您必须告诉py。测试和毒害在哪里找到您包含的模块。

py。测试你可以这样做:

PYTHONPATH=. py.test

使用tox,将这个添加到你的tox.ini:

[testenv]
deps= -r{toxinidir}/requirements.txt
commands=py.test
setenv =
    PYTHONPATH = {toxinidir}

我开始得到奇怪的ConftestImportFailure: ImportError('没有模块命名…错误时,我不小心添加__init__.py文件到我的src目录(这不是一个Python包,只是一个容器的所有源代码)。


我得到这个错误由于一些更简单的(你甚至可以说微不足道)。我还没有安装pytest模块。所以一个简单的安装python-pytest为我解决了这个问题。

'pytest'将在setup.py中作为测试依赖项列出。确保您也安装了测试需求。


将pytest本身作为一个模块运行: Python -m pytest测试

例如,当项目层次结构为package/src package/tests时,在从src导入的测试中,就会发生这种情况。作为模块执行会将导入视为绝对的,而不是相对于执行位置。


pytest>=7的推荐方法:使用pythonpath设置

最近,pytest增加了一个新的核心插件,该插件支持sys。通过pythonpath配置值修改路径。因此,现在的解决方案要简单得多,不再需要任何变通:

pyproject。toml例子:

[tool.pytest.ini_options]
pythonpath = [
  "."
]

pytest.ini例子:

[pytest]
pythonpath = .

路径条目是相对于根目录计算的,因此。将repo目录添加到sys。路径。

多个路径条目也被允许:对于一个布局

repo/
├── src/
|   └── lib.py
├── app.py
└── tests
     ├── test_app.py
     └── test_lib.py

配置

[tool.pytest.ini_options]
pythonpath = [
  ".", "src",
]

or

[pytest]
pythonpath = . src

将app和lib模块都添加到sys。路径,所以

import app
import lib

都可以。

原始答案(不建议用于最新的pytest版本;仅用于pytest<7): conftest解决方案

侵入性最小的解决方案是在repo/目录中添加一个名为conftest.py的空文件:

$ touch repo/conftest.py

就是这样。不需要编写自定义代码来破坏系统。path,或者记得拖拽PYTHONPATH,或者把__init__.py放到不属于它的dirs中(在Apteryx的回答中建议使用python -m pytest是一个很好的解决方案!)

之后的项目目录:

repo
├── conftest.py
├── app.py
├── settings.py
├── models.py
└── tests
     └── test_app.py

解释

Pytest在测试集合中寻找conftest模块来收集自定义钩子和fixture,为了从它们导入自定义对象,Pytest将conftest.py的父目录添加到sys. py目录中。路径(在本例中为repo目录)。

其他项目结构

如果你有其他的项目结构,将conftest.py放在包的根目录下(包含包但本身不是包,所以不包含__init__.py),例如:

repo
├── conftest.py
├── spam
│   ├── __init__.py
│   ├── bacon.py
│   └── egg.py
├── eggs
│   ├── __init__.py
│   └── sausage.py
└── tests
     ├── test_bacon.py
     └── test_egg.py

src布局

虽然这种方法可以用于src布局(将conftest.py放在src dir中):

repo
├── src
│   ├── conftest.py
│   ├── spam
│   │   ├── __init__.py
│   │   ├── bacon.py
│   │   └── egg.py
│   └── eggs 
│       ├── __init__.py
│       └── sausage.py
└── tests
     ├── test_bacon.py
     └── test_egg.py

注意,将src添加到PYTHONPATH会降低src布局的意义和好处!您最终将测试来自存储库的代码,而不是安装的包。如果你需要这样做,也许你根本不需要src目录。

从这里往哪里走

当然,conftest模块不仅仅是一些帮助发现源代码的文件;pytest框架的所有特定于项目的增强和测试套件的定制都发生在这里。Pytest有很多关于conftest模块的信息,分散在它们的文档中;从conftest.py开始:本地每个目录的插件

另外,SO有一个关于conftest模块的很好的问题:在py中。测试,conftest。py文件有什么用?


对我来说,问题是Django生成的tests.py和tests目录。删除tests.py就解决了这个问题。


我得到这个错误,因为我使用相对导入不正确。在OP示例中,test_app.py应该使用e.g.导入函数。

from repo.app import *

然而,尽管__init__.py文件分散在文件结构中,但这不会起作用,并会创建所见的ImportError类型,除非文件和测试文件在同一目录中。

from app import *

以下是我在一个项目中所做的一个例子:

这是我的项目结构:

microbit/
microbit/activity_indicator/activity_indicator.py
microbit/tests/test_activity_indicator.py

为了能够从test_activity_indicator.py访问activity_indicator.py,我需要:

使用正确的相对导入启动test_activity_indicator .py:

    from microbit.activity_indicator.activity_indicator import *

在整个项目结构中放置__init__.py文件:

    microbit/
    microbit/__init__.py
    microbit/activity_indicator/__init__.py
    microbit/activity_indicator/activity_indicator.py
    microbit/tests/__init__.py
    microbit/tests/test_activity_indicator.py

我也遇到过类似的问题。pytest无法识别安装在我工作的环境中的模块。

我通过在相同的环境中安装pytest来解决这个问题。


我通过删除源文件父文件夹中的顶层__init__.py来解决这个问题。


由于无法导入模块,测试经常会中断。

经过研究,我发现系统在错误的地方查看文件,我们可以通过在相同的文件夹中复制包含模块的文件来轻松克服这个问题,以便正确导入。

另一个解决方案建议是更改导入的声明,并向MutPy显示单元的正确路径。然而,由于多个单元可能具有这种依赖关系,这意味着我们也需要在它们的声明中提交更改,因此我们更喜欢简单地将单元移动到文件夹中。


根据Dirk Avery在Medium上的一篇文章(我个人经验也支持),如果你在项目中使用虚拟环境,那么你就不能使用系统范围的pytest安装;您必须在虚拟环境中安装它并使用该安装。

特别是,如果在两个地方都安装了它,那么简单地运行pytest命令将不起作用,因为它将使用系统安装。正如其他答案所描述的,一个简单的解决方案是运行python -m pytest而不是pytest;这是因为它使用了环境版本的pytest。或者,你也可以卸载系统版本的pytest;重新激活虚拟环境后,pytest命令应该可以工作。


在跟随Flask教程时,我也遇到了同样的问题,我在官方的Pytest文档中找到了答案。 这与我(以及其他许多人)过去做事的方式有一点不同。

你必须在你的项目根目录下创建一个setup.py文件,至少包含以下两行代码:

from setuptools import setup, find_packages
setup(name="PACKAGENAME", packages=find_packages())

其中PACKAGENAME是应用程序的名称。然后你要用pip安装它:

pip install -e .

-e标志告诉pip以可编辑或“开发”模式安装包。因此,下次运行pytest时,它应该在标准PYTHONPATH中找到你的应用程序。


我在弗拉斯克也遇到了同样的问题。

当我补充说:

__init__.py

到测试文件夹,问题消失了:)

可能应用程序无法将文件夹测试识别为模块。


我的解决方案:

在test目录下创建conftest.py文件,包含:

import os
import sys
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + "/relative/path/to/code/")

这将把感兴趣的文件夹添加到Python解释器路径中,而无需修改每个测试文件,设置环境变量或混淆绝对/相对路径。


正如Luiz Lezcano Arialdi所指出的,正确的解决方案是将您的包安装为可编辑包。

因为我正在使用Pipenv,所以我考虑在他的回答中逐步添加如何使用Pipenv将当前路径安装为可食用路径,允许运行pytest而不需要任何破坏代码或丢失文件。

你需要有以下最小的文件夹结构(文档):

package/
    package/
        __init__.py
        module.py
    tests/
        module_test.py
    setup.py

Setup.py主要有以下最小代码(文档):

import setuptools

setuptools.setup(name='package', # Change to your package name
                 packages=setuptools.find_packages())

然后你只需要运行pipenv install——dev -e。Pipenv将当前路径安装为可编辑包(——dev标志是可选的)(文档)。

现在您应该能够毫无问题地运行pytest了。


我们通过添加以下环境变量修复了这个问题。

PYTHONPATH=${PYTHONPATH}:${PWD}/src:${PWD}/test

此外,如果在虚拟环境中运行pytest,请确保在虚拟环境中安装了pytest模块。激活虚拟环境并运行pip install pytest。


有点遗憾的是,这是Python中的一个问题……但在我看来,加入这个环境变量是最舒服的方式:

export PYTHONPATH=$PYTHONPATH:.

你可以把这一行放在你的。zshrc或。bashrc文件中。


因为没有人建议这样做,你也可以在pytest.ini文件中传递测试的路径:

[pytest]
...
testpaths = repo/tests

参见文档:https://docs.pytest.org/en/6.2.x/customize.html#pytest-ini

Visual Studio Code的副作用:它应该在UI中拾取单元测试。


如果这个pytest错误不是出现在您自己的包上,而是出现在包的requirements.txt中的git安装包上,解决方案是切换到可编辑的安装模式。

例如,假设你的包的requirements.txt有如下一行:

git+https://github.com/foo/bar.git

您可以将其替换为以下内容:

-e git+https://github.com/foo/bar.git#egg=bar

如果没有工作,请确保test_module.py被列在正确的src目录下。 有时它会给出ModuleNotFoundError,不是因为模块放错了地方,也不是因为export PYTHONPATH="${PWD}:${PYTHONPATH}"不工作,而是因为test_module.py被放在了tests文件夹下的错误目录中。

它应该是递归的1对1映射关系,而不是根文件夹应该命名为“tests”,包含测试代码的文件名应该以“test_”开头, 例如,

./nlu_service/型号/变压器.py

-测试- test_transformers models . py。


这就是我的经历。