【问题标题】:`py.test` and `__init__.py` files`py.test` 和 `__init__.py` 文件
【发布时间】:2011-11-23 14:58:02
【问题描述】:

我认为py.test 在某种意义上是“独立的”,它会“按原样”处理test_*.py 文件,并且只导入这些文件中指定的模块,而不考虑任何周围的文件。看来我错了。这是我与py.test 的对话:

$ ls
__init__.py    test_pytest.py
$ cat __init__.py 
$ cat test_pytest.py 
def test_pytest():
    assert True
$ py.test test_pytest.py 
========================================================= test session starts ==========================================================
platform darwin -- Python 2.7.2 -- pytest-2.1.3
collected 0 items / 1 errors 

================================================================ ERRORS ================================================================
___________________________________________________ ERROR collecting test_pytest.py ____________________________________________________
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/py-1.4.5-py2.7.egg/py/_path/local.py:529: in pyimport
>           mod = __import__(modname, None, None, ['__doc__'])
E           ImportError: No module named test_pytest
======================================================= 1 error in 0.01 seconds ========================================================
$ rm __init__.py 
$ py.test test_pytest.py 
========================================================= test session starts ==========================================================
platform darwin -- Python 2.7.2 -- pytest-2.1.3
collected 1 items 

test_pytest.py .

======================================================= 1 passed in 0.01 seconds =======================================================
$ 

如何使py.test 工作并且仍然拥有我的__init__.py 文件?

更新

在 cmets 中,Holger Krekel 询问父目录的名称是什么。事实证明,我可以重现上面的错误,只有某个父目录名称(例如,与安装的软件包之一相同的名称,如 distutils)。见这里:

~/test_min 
$ tree
.
└── distutils
    ├── __init__.py
    └── test_pytest.py

1 directory, 2 files
~/test_min 
$ cat distutils/__init__.py 
~/test_min 
$ cat distutils/test_pytest.py 
def test_pytest():
    assert True
~/test_min 
$ py.test distutils/test_pytest.py 
======================== test session starts =========================
platform darwin -- Python 2.7.2 -- pytest-2.1.3
collected 0 items / 1 errors 

=============================== ERRORS ===============================
_____________ ERROR collecting distutils/test_pytest.py ______________
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/py-1.4.5-py2.7.egg/py/_path/local.py:529: in pyimport
>           mod = __import__(modname, None, None, ['__doc__'])
E           ImportError: No module named test_pytest
====================== 1 error in 0.01 seconds =======================
~/test_min 
$ rm distutils/__init__.py 
~/test_min 
$ py.test distutils/test_pytest.py 
======================== test session starts =========================
platform darwin -- Python 2.7.2 -- pytest-2.1.3
collected 1 items 

distutils/test_pytest.py .

====================== 1 passed in 0.01 seconds ======================
~/test_min 
$ touch __init__.py
~/test_min 
$ ls
__init__.py distutils
~/test_min 
$ touch distutils/__init__.py
~/test_min 
$ py.test distutils/test_pytest.py 
======================== test session starts =========================
platform darwin -- Python 2.7.2 -- pytest-2.1.3
collected 1 items 

distutils/test_pytest.py .

====================== 1 passed in 0.02 seconds ======================
~/test_min 
$ rm __init__.py 
~/test_min 
$ py.test distutils/test_pytest.py 
======================== test session starts =========================
platform darwin -- Python 2.7.2 -- pytest-2.1.3
collected 0 items / 1 errors 

=============================== ERRORS ===============================
_____________ ERROR collecting distutils/test_pytest.py ______________
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/py-1.4.5-py2.7.egg/py/_path/local.py:529: in pyimport
>           mod = __import__(modname, None, None, ['__doc__'])
E           ImportError: No module named test_pytest
====================== 1 error in 0.01 seconds =======================
~/test_min 
$ mv distutils foobar
~/test_min 
$ py.test foobar/test_pytest.py 
======================== test session starts =========================
platform darwin -- Python 2.7.2 -- pytest-2.1.3
collected 1 items 

foobar/test_pytest.py .

====================== 1 passed in 0.01 seconds ======================
~/test_min 
$ 

希望这些附加信息会有所帮助。

【问题讨论】:

  • 听起来你可能遇到了 Python 包系统的副作用。
  • 如果你包含 init.py 文件并且只说 ... $ py.test 会发生什么
  • 看起来在...的底部可能会提示您的问题pytest.org/latest/goodpractises.html#package-name
  • 值得一提的是,我在 1.3.4 版本中没有看到这种行为。不过,我已经更新到 2.2.0 版试一试,得到了相同的错误输出。
  • 父目录(包含 init.py 的目录)的名称是什么?在包含代码的目录中是否还有更多的 init.py 文件?

标签: python unit-testing pytest


【解决方案1】:

看起来 py.test 正在使用 py._path.pyimport 打开您的文件。如果目录中有__init__.py 文件,它会将您的文件视为一个模块,否则它会打开该文件。长话短说,删除__init__.py 或将您的测试放在项目代码之外的另一个目录中(

https://py.readthedocs.io/en/latest/path.html#py._path.local.LocalPath.pyimport

【讨论】:

  • 我将赏金授予您,这样它就不会自动提供给tito,因为他的回答不正确。不过,我希望在不改变文件结构的情况下解决这个问题。
【解决方案2】:

我真的建议您将目录重命名为不称为“distutils”的名称。为什么 ?因为您正在覆盖现有模块。 当脚本中出现“import distutils”或“from distutils import *”时(来自另一个导入或您自己的 python 文件),它将更喜欢您的目录而不是系统目录。 如果模块 distutils 之前已经加载过,你的 distutils 将不会被加载,因为这个符号已经存在于 global() 中。

重命名该目录(如测试)会更简单,而不是尝试使用 py.text / python internals。

【讨论】:

  • distutils 只是重现错误的示例。我自己的模块名称不同。
  • 好的,最后一个问题。当您在“.”上添加 init.py 时,“.”的名称目录也被视为模块名称。你的情况是什么? (附带说明,即使通过查看您的测试,我认为您没有遇到此错误,但不要忘记 pyc 生成,当删除 py 时,pyc 仍然存在并且可导入。)跨度>
  • 如果你的意思是,当我做$ touch __init__.py?从上面的行可以看出,它是在~/test_min 中完成的。另外,我没有任何 pyc 文件,您可以从 tree 命令中看到。
【解决方案3】:

您可以告诉 pytest 忽略特定文件或 glob 模式,如 here 所述。在项目的根目录中放置一个conftest.py 文件,其中列出了您希望pytest 忽略的文件:

但是,许多项目会有一个他们不想导入的 setup.py。此外,可能存在只能由特定 python 版本导入的文件。对于这种情况,您可以通过在 conftest.py 文件中列出文件来动态定义要忽略的文件:

 # content of conftest.py
 import sys

 collect_ignore = ["setup.py"]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-03
    • 2014-02-27
    • 2019-08-18
    • 1970-01-01
    • 2019-09-27
    • 1970-01-01
    • 1970-01-01
    • 2013-07-14
    相关资源
    最近更新 更多