我有一个项目目录结构如下(我认为这很标准):
my_project
setup.py
mypkg
__init__.py
foo.py
tests
functional
test_f1.py
unit
test_u1.py
我正在使用py.test作为我的测试框架,我期望能够在py.test tests
目录中运行my_project
来运行我的测试。这确实有效,直到我尝试在测试中使用(例如)import mypkg
导入我的应用程序代码。那时,我收到错误“没有名为mypkg的模块”。在进行一些调查时,似乎py.test
使用sys.path
中的测试文件目录运行测试,但不 py.test
所在的目录从。运行。
为了解决这个问题,我在conftest.py
目录中添加了一个tests
文件,其中包含以下代码:
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
文档,但我看不出这个问题的解释或推荐的处理方法。
答案 0 :(得分:39)
正如你所说,py.test基本上假设你正确设置了PYTHONPATH。有几种方法可以实现这一目标:
为您的项目提供setup.py,并在此项目的virtualenv中使用pip install -e .
。这可能是标准方法。
作为一个变种,如果你有一个virtualenv但没有setup.py使用你的venv工具在sys.path上添加项目目录,例如pew add .
如果您使用pew,或add2virtualenv .
如果您使用virtualenv和virtualenvwrapper的扩展名。
如果你总是喜欢sys.path上的当前工作目录,你可以随时在shell中导出PYTHONPATH=''
。这是确保sys.path上的空字符串,python将其解释为当前工作目标。这可能存在安全隐患。
我自己最喜欢的黑客,滥用py.test如何加载conftest文件:在项目的顶级目录中放置一个空的conftest.py
。
py.test以这种方式运行的原因是为了便于在结帐的test /目录中针对已安装的包运行测试。如果它无条件地将项目目录添加到PYTHONPATH那么这将不再可能。
答案 1 :(得分:10)
答案实际上要容易得多,如here所示。
您需要做的就是在测试目录及其每个子目录中添加__init__.py
,如下所示;
tests/__init__.py
tests/functional/__init__.py
tests/unit/__init__.py
答案 2 :(得分:4)
最简单的方法是,在terminal / cmd更改目录到父目录的位置(例如,在本例中为cd C:/.../my_project
)。
然后运行:
python -m pytest --cov=mypkg tests
无需弄乱PYTHONPATH
环境变量。
通过运行python -m pytest
,它将自动将当前目录添加到sys.path
。
答案 3 :(得分:2)
1 个包裹
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