Importing correctly with pytest
我刚准备好将pytest与python 2.6结合使用。到目前为止,它工作得很好,除了处理"import"语句:我似乎无法让pytest像我的程序那样响应导入。
我的目录结构如下:
1 2 3 4 5 6 7 8 9 10 11 | src/ main.py util.py test/ test_util.py geom/ vector.py region.py test/ test_vector.py test_region.py |
要运行,我从src/调用
在main.py中,我导入向量和区域
1 2 | from geom.region import Region from geom.vector import Vector |
在vector.py中,我导入带有
1 | from geom.region import Region |
当我在标准运行中运行代码时,这些都可以正常工作。但是,当我从src/调用"py.test"时,它始终会退出并出现导入错误。
一些问题和我的解决方案尝试我的第一个问题是,当运行"test/test foo.py"时,py.test无法直接"导入foo.py"。我用"imp"工具解决了这个问题。在"test-tuil.py"中:
1 2 | import imp util = imp.load_source("util","util.py") |
这对许多文件都很有用。这似乎也意味着,当py test运行"path/test/test_foo.py"to test"path/foo.py"时,它基于"path"目录。
但是,"test_vector.py"失败。pytest可以找到并导入
1 2 | from geom.region import * from region import * |
这两个都给出了错误的形式
1 | ImportError: No module named [geom.region / region] |
我不知道下一步该怎么做来解决这个问题;我对Python中的导入的理解是有限的。
在使用pytest时,处理导入的正确方法是什么?
编辑:非常简单的解决方案在
1 | from geom.region import Region |
简单地
1 | from region import Region |
这使得导入相对于"vector.py"目录。
接下来,在"test/test_vector.py"中,我将"vector.py"目录添加到路径中,如下所示:
1 2 | import sys, os sys.path.append(os.path.realpath(os.path.dirname(__file__)+"/..")) |
这使python能够从"geom/test/test_vector.py"中找到"./region.py"。
这是可行的,但它似乎是非常有问题的,因为我正在向路径中添加大量的新目录。我要找的是
1)与Pytest兼容的导入策略,或
2)Pytest中的一个选项,使其与我的导入策略兼容
所以我将这个问题留给这些答案。
import在以下目录中查找模块:
sys.path是主目录、pythonpath和标准库目录组合的结果。您所做的,修改sys.path是正确的。这是我经常做的事。如果你不喜欢弄乱sys.path,可以尝试使用pythonpath。
这里的问题是,pytest在文件系统中查找包含测试的文件,但随后需要生成一个模块名,该模块名将导致
pytest通过查找不包含
你应该注意这其中的一些含义:
基本路径可能与预期的基本路径不匹配,在这种情况下,模块的名称将与您通常使用的名称不匹配。例如,您所认为的
如果不同目录中的两个文件同名,则可能会发生模块命名冲突。例如,在任何地方缺少
您在这里使用的系统没有显式的
这里最简单的解决方案是将空的
问题是如何使用PEP420名称空间包对项目进行pytest?讨论其他解决方案。
我也在想怎么解决这个问题。在阅读了这篇文章,并四处游玩之后,我想出了一个优雅的解决方案。我创建了一个名为"test_setup.py"的文件,并在其中输入以下代码:
1 2 | import sys, os sys.path.append(os.path.dirname(os.path.abspath(__file__))) |
我把这个文件放在顶级目录(比如src)中。当从顶层目录运行
代码将把test_setup.py文件的当前目录名附加到测试环境中的系统路径。这将只做一次,所以没有一堆东西添加到路径中。
然后,在任何测试函数中,您都可以导入与顶层文件夹相关的模块(如
如果要运行单个测试文件(如test_util.py)而不是所有文件,则应使用:
1 | pytest test_setup.py test\test_util.py |
这将运行测试设置和测试实用程序代码,以便仍然可以使用测试设置代码。