在 python 模块的 py.test 测试目录中,为该模块导入一个文件

Within the py.test test directory for a python module, import a file for the module

我在目录中安排了一个 python 模块。称之为 foo

这是文件布局:

caller.py
foo/__init__.py
foo/bar.py
foo/test/bar_test.py

也就是说,模块被称为foo,当caller.py中的import foo语句得到运行时,foo/__init__.py中的代码被导入。

foo/__init__.py 内,我希望访问 bar.py 的内容。这是通过 import foo.bar.

完成的

我的问题出现在编写 foo/test/bar_test.py 中 运行 的代码时。如果这个文件只是 foo/bar_test.py,那么它也可以使用 import foo.bar 来导入 foo.bar.py 的内容。不幸的是,我们的编码标准规定单元测试位于名为 tests 的子目录中。

鉴于该编码标准,我们如何导入 bar.py?

这不起作用:

# foo/test/bar_test.py
import foo.bar
def test_return5():
   assert bar.return5() == 5

它给了我:

$ py.test
================================================== test session starts ==================================================
platform linux -- Python 3.6.3, pytest-3.2.1, py-1.4.34, pluggy-0.4.0
rootdir: /home/hadoop/xxx/foo, inifile:
collected 0 items / 1 errors

======================================================== ERRORS =========================================================
___________________________________________ ERROR collecting test/bar_test.py ___________________________________________
ImportError while importing test module '/home/hadoop/xxx/foo/test/bar_test.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
test/bar_test.py:3: in <module>
    import foo.bar
E   ModuleNotFoundError: No module named 'foo'
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
================================================ 1 error in 0.10 seconds ================================================

这有效,但很恶心:

# foo/test/bar_test.py

import os
import sys

sys.path.append( os.path.join(os.path.dirname(__file__), "../.."))

import foo.bar

def test_return5():
   assert foo.bar.return5() == 5

这不起作用:

# foo/test/bar_test.py

import os
import sys

sys.path.append( os.path.join(os.path.dirname(__file__), ".."))

import bar

def test_return5():
   assert bar.return5() == 5

因为:

$ py.test
================================================== test session starts ==================================================
platform linux -- Python 3.6.3, pytest-3.2.1, py-1.4.34, pluggy-0.4.0
rootdir: /home/hadoop/xxx/foo, inifile:
collected 0 items / 1 errors

======================================================== ERRORS =========================================================
___________________________________________ ERROR collecting test/bar_test.py ___________________________________________
ImportError while importing test module '/home/hadoop/xxx/foo/test/bar_test.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
test/bar_test.py:8: in <module>
    import bar
bar.py:3: in <module>
    import foo
E   ModuleNotFoundError: No module named 'foo'
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
================================================ 1 error in 0.10 seconds ================================================

因为bar.py有:

# foo/bar.py

import foo

def return5():
    return 5
import foo.bar as bar

如果您从父目录 运行 pytest,那应该在 bar_test.py 中工作(至少,它刚才对我有用)。

您不能在 python 3 中使用 import bar(我假设这就是您正在使用的),因为它不明确 - 请参阅 PEP-404 and a more in depth Whosebug answer 了解更多详细信息。

编辑:查看扩展示例,问题似乎是 bar_test.py 不是 foo 包的一部分(因为 test 目录不是包裹)。如果你添加一个 __init__.py 文件到 test 目录,pytest 会很高兴地 运行 the test::

$ pytest foo/test/bar_test.py 
===================================================================== test session starts ======================================================================
platform linux -- Python 3.5.3, pytest-3.6.3, py-1.5.4, pluggy-0.6.0
rootdir: /home/xxxx/tmp/blank, inifile:
collected 1 item                                                                                                                                                

foo/test/bar_test.py .                                                                                                                                   [100%]

=================================================================== 1 passed in 0.03 seconds ===================================================================
$ ls -lh foo/test/
total 12K
-rw-rw-r-- 1 xxxx xxxx   95 Jul 26 14:44 bar_test.py
-rw-rw-r-- 1 xxxx xxxx    0 Jul 27 16:38 __init__.py
-rw-rw-r-- 1 xxxx xxxx  132 Jul 27 16:38 __init__.pyc
drwxrwsr-x 2 xxxx xxxx 4.0K Jul 27 16:38 __pycache__

请注意,我必须在添加 __init__.py 后删除 __pycache__

有关详细信息,请参阅 pytest docs