65

这是一个经常以不同形式被问到的问题,并且经常得到“大声笑你做得不好”的回答。很确定这是因为人们(包括我)正在尝试将其用作实现的常识场景,并且解决方案并不明显(如果您以前没有这样做过)。

会接受“让飞出瓶子”的答案。

给定

project/
    __init__.py
    /code
        __init__.py
        sut.py
    /tests
        __init__.py
        test_sut.py

tests_sut.py 开始的地方:

import code.sut

在根目录中运行鼻子测试会导致:

ImportError: No module named code.sut

走过的大道:

a)做一个亲戚使用

from ..code import sut

b) 将项目的根目录添加到 PYTHONPATH

c) 使用

sys.path.append

在每个测试模块开始处的导入之前添加 .. 路径。

d) 只记得做一个

setup.py 

在项目上将模块安装到站点包中,然后再运行测试。


所以要求是让测试位于可以访问项目的测试包根目录下。以上每一项对我来说都不“自然”,被证明是有问题的,或者看起来太辛苦了!

在 java 中这是可行的,但基本上是通过您的构建工具/IDE 将您的所有类放在类路径上。也许问题是我期待 Python 的“魔法”?在 Flask 网络框架测试中已经注意到,选项 d) 似乎是首选。

无论如何,以下推荐首选解决方案的陈述将消除我自己的“不自然”感觉。

4

3 回答 3

45

我遇到了同样的问题,并在我的相关问题工作中找到了答案。

只需删除项目根目录中的 __init__.py 即可。

于 2012-05-18T04:46:57.260 回答
12

您已经很好地回答了您的问题。 D(安装到系统位置)是可分发代码的首选。我通常使用 C(修改 sys.path),因为我不想在系统范围内安装数百个自定义库。理论上 A(相对导入)似乎更好,但在某些情况下它会失败。B (PYTHONPATH) 是正确的,在我看来真的只是为了测试目的。

这几乎总结了所有选项。您喜欢的选项(Python 神奇地知道在哪里寻找)实际上不是一个可行的解决方案,因为它可能导致不可预测的结果,例如从不相关的项目中自动查找库。

在我看来,最好的办法是把它放在你程序的入口点:

import sys, os
sys.path = [os.path.abspath(os.path.dirname(__file__))] + sys.path
于 2011-07-12T20:37:43.050 回答
5

我知道已经检查了一个答案,我仍然认为这是分享其他替代方案的好理由:)

有一个nose-pathmunge可以让你sys.path在调用时进行设置nosestests

于 2013-09-18T06:00:41.523 回答