确保 py.test 包含 sys.path 中的应用程序目录

我有一个项目目录结构如下(我认为这是相当标准的) :

my_project
setup.py
mypkg
__init__.py
foo.py
tests
functional
test_f1.py
unit
test_u1.py

我使用 py.test 作为我的测试框架,我希望能够在 my_project目录中运行 py.test tests来运行我的测试。这确实有效,直到我尝试在测试中使用(例如) import mypkg导入我的应用程序代码。此时,我得到错误“ No module name mypkg”。在进行一些调查之后,发现 py.test使用 sys.path中的测试文件目录运行测试,但是使用 没有运行 py.test

为了解决这个问题,我在 tests目录中添加了一个 conftest.py文件,其中包含以下代码:

import sys, os


# Make sure that the application source directory (this directory's parent) is
# on sys.path.


here = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, here)

这看起来是可行的,但是这是确保测试可以看到应用程序代码的好方法吗?有没有更好的方法来实现这一点,或者我在如何构建我的项目结构方面做错了什么?

我看过一些使用 py.test的其他项目(例如,pip) ,但是我看不到这样的代码,但是运行 py.test tests似乎可以。我不知道为什么,但我担心他们可能用更简单的方法得到了同样的结果。

我已经查看了 py.test文档,但是我看不到对这个问题的解释,也看不到处理这个问题的推荐方法。

37301 次浏览

正如您所说的,py.test 基本上假设您已经正确地设置了 PYTHONPATH。有几种方法可以做到这一点:

  • 给您的项目一个 setup.py 并在这个项目的 viralenv 中使用 pip install -e .。这可能是标准的方法。

  • 如果你有一个 viralenv,但是没有 setup.py,那么可以使用 venv 的工具在 sys.path 上添加项目目录,比如使用 pew 时添加 pew add .,使用 viralenv 时添加 add2virtualenv .,使用 viralenvwrapper 扩展时添加 add2virtualenv .

  • 如果你总是喜欢 sys.path 上的当前工作目录,你可以简单地在 shell 中导出 PYTHONPATH=''。这就是确保 sys.path 上的空字符串,python 将其解释为当前工作目录。不过,这可能是一个安全隐患。

  • 我自己最喜欢的技巧是,滥用 py.test 加载角逐文件的方式: 在项目的顶级目录中放入一个空的 conftest.py

Test 采用这种方式的原因是为了更容易地根据已安装的软件包在结帐目录的 test/目录中运行测试。如果它将无条件地将项目目录添加到 PYTHONPATH,那么这将不再可能。

答案实际上要简单得多,如 给你所示。

您所需要做的就是向您的测试目录及其每个子目录添加一个 __init__.py,如下所示;

tests/__init__.py
tests/functional/__init__.py
tests/unit/__init__.py

最简单的方法是,在终端/cmd 中将目录更改为父目录所在的位置(例如,在本例中为 cd C:/.../my_project)。

然后跑: python -m pytest --cov=mypkg tests

没必要动 PYTHONPATH的环境变量。 通过运行 python -m pytest,它会自动将工作目录添加到 sys.path

运行引用单个/多个包的 pytest

一个包裹

PYTHONPATH=$(pwd)/mypkg/ python3 -m pytest
# or
PYTHONPATH=$(pwd)/mypkg/ python3 -m pytest  path/to/tests

2包(pkg1 pkg2)

# Use ; as a separator in windows
PYTHONPATH=/path/to/pkg1/:/path/to/pkg2/ python3 -m pytest tests