我刚刚设置为在Python 2.6中使用pytest。到目前为止,除了处理" import"陈述:我似乎无法以与我的程序相同的方式得到pytest以响应导入。
我的目录结构如下:
src/
main.py
util.py
test/
test_util.py
geom/
vector.py
region.py
test/
test_vector.py
test_region.py
要运行,我从src /.
调用python main.py
在main.py中,我用
导入了vector和regionfrom geom.region import Region
from geom.vector import Vector
在vector.py中,我用
导入区域from geom.region import Region
当我在标准运行中运行代码时,这些都可以正常工作。但是,当我打电话给" py.test"来自src /,它一直以导入错误退出。
我的第一个问题是,当运行" test / test_foo.py"时,py.test无法导入foo.py"直。我通过使用" imp"解决了这个问题。工具。在" test_util.py":
import imp
util = imp.load_source("util", "util.py")
这适用于许多文件。它似乎也意味着当pytest正在运行" path / test / test_foo.py"测试" path / foo.py",它位于目录" path"。
然而,对于" test_vector.py"这是失败的。 Pytest可以找到并导入vector
模块,但无法找到vector
的任何导入。使用pytest时,以下导入(来自" vector.py")都会失败:
from geom.region import *
from region import *
这两个都给出了
形式的错误ImportError: No module named [geom.region / region]
我不知道接下来要做什么来解决这个问题;我对Python中导入的理解是有限的。
使用pytest时处理导入的正确方法是什么?
在vector.py
中,我更改了
from geom.region import Region
简单地
from region import Region
这使得导入相对于" vector.py"。
的目录接下来,在" test / test_vector.py"中,我添加" vector.py"的目录。如下路径:
import sys, os
sys.path.append(os.path.realpath(os.path.dirname(__file__)+"/.."))
这使Python能够找到" ../ region.py"来自" geom / test / test_vector.py"。
这有效,但它似乎非常有问题,因为我在路径中添加了大量新目录。我正在寻找的是
1)与pytest或
兼容的导入策略2)pytest中的一个选项,使其与我的导入策略兼容
所以我将这个问题留待这些问题解答。
答案 0 :(得分:13)
import 查看以下目录以查找模块:
sys.path 是将主目录, PYTHONPATH 与标准相结合的结果库目录。您正在做什么,修改 sys.path 是正确的。这是我经常做的事情。您可以尝试使用 PYTHONPATH ,如果您不想搞乱 sys.path
答案 1 :(得分:9)
如果在测试目录中包含一个 __ init __。py 文件,则当该程序希望设置主目录时,它将“向上”移动,直到找到一个不包含init的目录。文件。在这种情况下,src /。
您可以从这里说:
from geom.region import *
还必须确保在任何其他子目录(例如,另一个嵌套的测试目录)中都有一个init文件
答案 2 :(得分:7)
这里的问题是Pytest遍历文件系统以发现包含测试的文件,但随后需要生成一个模块名称,该名称将导致import
加载该文件。 (请记住,files are not modules。)
Pytest通过查找不包含__init__.py
文件的文件级别或更高级别的第一个目录,并声明包含模块树的模块树的“basedir”来找到这个test package name。从该文件生成的模块。然后它将basedir添加到sys.path
并使用模块名称导入,该模块名称将相对于basedir找到该文件。
您应该注意这一点的含义:
基本路径可能与您预期的基本路径不匹配,在这种情况下,模块的名称与您通常使用的名称不匹配。例如,您认为geom.test.test_vector
在Pytest运行期间实际上只会被test_vector
命名,因为它在__init__.py
中找不到src/geom/test/
,因此将该目录添加到{{1} }}
如果不同目录中的两个文件具有相同的名称,则可能会遇到模块命名冲突。例如,在任何地方都缺少sys.path
个文件,添加__init__.py
会与geom/test/test_util.py
冲突,因为它们都会test/test_util.py
加载import test_util.py
和test/
在路上。
您在此处使用的系统(没有明确的geom/test/
模块)正在为您的目录创建implicit namespace packages。 (包是一个带有子模块的模块。)理想情况下,我们将为Pytest配置一个路径,它也会生成它,但它似乎不知道如何做到这一点。
这里最简单的解决方案就是将空__init__.py
个文件添加到__init__.py
下的所有子目录中;这将导致Pytest使用以src/
下的目录名开头的包/模块名称导入所有内容。
问题How do I Pytest a project using PEP 420 namespace packages?讨论了其他解决方案。
答案 3 :(得分:6)
我想知道该怎么办这个问题。看了这篇文章,并玩了一下,我想出了一个优雅的解决方案。我创建了一个名为" test_setup.py"的文件。并将以下代码放入其中:
import sys, os
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
我将此文件放在顶级目录(例如src)中。当从顶级目录运行pytest
时,它将运行包括此文件在内的所有测试文件,因为该文件的前缀是" test"。文件中没有测试,但它仍然运行,因为它以" test"开始。
代码会将test_setup.py文件的当前目录名附加到测试环境中的系统路径。这只会进行一次,因此路径中没有添加任何东西。
然后,从任何测试函数中,您可以导入相对于该顶级文件夹的模块(例如import geom.region
),并且它知道从src目录添加到路径后的位置。
如果要运行单个测试文件(例如test_util.py)而不是所有文件,则可以使用:
pytest test_setup.py test\test_util.py
这将运行test_setup和test_util代码,以便仍然可以使用test_setup代码。