这是我的项目布局:
project
+-- package_1
| +-- __init__.py
| +-- module_1.py tests
+-- package_2
| +-- __init__.py
| +-- module_2.py tests
+-- tests
+-- package_1
| +-- __init__.py
| +-- test_module_1.py
+-- package_2
+-- __init__.py
+-- test_module_2.py
test_module_1.py开头为:
import package_1.module_1
test_module_2.py始于:
import package_2.module_2
从项目目录运行python -m unittest discover tests
会出现错误:
EE
======================================================================
ERROR: package_1.test_module_1 (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: package_1.test_module_1
Traceback (most recent call last):
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/loader.py", line 434, in _find_test_path
module = self._get_module_from_name(name)
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/loader.py", line 375, in _get_module_from_name
__import__(name)
File "/Users/maggyero/project/tests/package_1/test_module_1.py", line 1, in <module>
import package_1.module_1
ModuleNotFoundError: No module named 'package_1.module_1'
======================================================================
ERROR: package_2.test_module_2 (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: package_2.test_module_2
Traceback (most recent call last):
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/loader.py", line 434, in _find_test_path
module = self._get_module_from_name(name)
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/loader.py", line 375, in _get_module_from_name
__import__(name)
File "/Users/maggyero/project/tests/package_2/test_module_2.py", line 1, in <module>
import package_2.module_2
ModuleNotFoundError: No module named 'package_2.module_2'
----------------------------------------------------------------------
Ran 2 tests in 0.000s
FAILED (errors=2)
在test_module_1.py的开头添加import sys; print(sys.modules['package_1'])
,在test_module_2.py的开头添加import sys; print(sys.modules['package_2'])
,以查看sys.modules
cache中的内容,表明package_1和package_2在测试发现期间,已经从tests目录中导入了该文件:
<module 'package_1' from '/Users/maggyero/project/tests/package_1/__init__.py'>
<module 'package_2' from '/Users/maggyero/project/tests/package_2/__init__.py'>
即使先前已更新sys.modules
,导入先前导入的程序包也会重用sys.path
中的相同缓存的程序包。因此,当执行import package_1.module_1
和import package_2.module_2
时,将重新导入测试目录(包含test_module_1和test_module_2)中的package_1和package_2,而不是项目目录(包含module_1和module_2)中的package_1和package_2,然后导入module_1和module_2,并引发ModuleNotFoundError
。
是否有一种解决方法,除了重命名之外,还可以避免来自tests目录的软件包遮盖了项目目录的软件包?
下面的Laurent Laporte的另一种解决方案(他避免执行'package_1'
和'package_2'
时在sys.modules
中已经有import package_1.module_1
和import package_2.module_2
,通过使{{ 1}}和'tests.package_1'
相反,这要归功于顶层目录的更改),是更新'tests.package_2'
并将包重新加载到test_module_1.py中:
sys.path
和test_module_2.py:
import importlib
import pathlib
import sys
sys.path.insert(0, pathlib.Path(__file__).resolve().parents[2])
import package_1
importlib.reload(package_1)
import package_1.module_1
此解决方案的唯一优点是,tests目录不必是常规软件包(具有__init__.py文件)。因此,当Unittest允许递归命名空间包发现时(此时票证仍处于打开状态:https://bugs.python.org/issue23882)将没有任何优势。
最好使用Laurent Laporte的解决方案,因为与包装重新装载相比,包装限定更好地区分了具有相同名称的包装。另一个很好的解决方案是包重命名(例如将package_1和package_2从tests目录重命名为test_package_1和test_package_2)。
答案 0 :(得分:1)
您可以使用标志 -t ,-top-level-directory directory 来设置顶级目录,从而解决您的问题项目的名称(默认为开始目录)
例如:
python -m unittest discover tests -t .
但是,为了使 discover 导入您的测试模块,您需要通过在其中插入tests
来将__init__.py
目录变成一个包。
请参阅有关tests discovery的文档。
注释:
我在PyTest上遇到了同样的问题。在GitHub上见我的study。
在其他开源项目中,只有一个根软件包(例如,只有package_1
),没有tests/package_1
目录,只有tests
和所有{ {1}}个模块(可能还有子软件包)。因此,问题没有出现。