python-3.x - 如何让 python -m unittest discover 处理 PEP 420 命名空间包?
问题描述
假设项目的顶层是一个没有 __init__.py 的 PEP 420 命名空间包,如下所示:
src
└── toplevel
└── secondlevel
├── __init__.py
└── tests
├── __init__.py
└── test_something.py
可以很好地导入测试文件:
$ python3.8 -m venv v
$ ln -s $PWD/src/toplevel v/lib/python3.8/site-packages/
$ v/bin/python -m toplevel.secondlevel.tests.test_something
Hi from test_something.py
但是,如果我将 unittest 指向这个结构,它会失败:
$ v/bin/python -m unittest discover toplevel.secondlevel
Traceback (most recent call last):
File "/usr/lib/python3.8/runpy.py", line 192, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/usr/lib/python3.8/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/usr/lib/python3.8/unittest/__main__.py", line 18, in <module>
main(module=None)
File "/usr/lib/python3.8/unittest/main.py", line 100, in __init__
self.parseArgs(argv)
File "/usr/lib/python3.8/unittest/main.py", line 124, in parseArgs
self._do_discovery(argv[2:])
File "/usr/lib/python3.8/unittest/main.py", line 244, in _do_discovery
self.createTests(from_discovery=True, Loader=Loader)
File "/usr/lib/python3.8/unittest/main.py", line 154, in createTests
self.test = loader.discover(self.start, self.pattern, self.top)
File "/usr/lib/python3.8/unittest/loader.py", line 340, in discover
self._get_directory_containing_module(top_part)
File "/usr/lib/python3.8/unittest/loader.py", line 354, in _get_directory_containing_module
full_path = os.path.abspath(module.__file__)
File "/usr/lib/python3.8/posixpath.py", line 374, in abspath
path = os.fspath(path)
TypeError: expected str, bytes or os.PathLike object, not NoneType
NoneType 显然来自toplevel.__file__,对于 PEP 420 命名空间包来说是 None 。unittest.loader.TestLoader.discover似乎确实包含一些用于命名空间包的机制,但在这种情况下它不起作用。
如果我添加 __init__.py 文件,一切正常:
$ touch src/toplevel/__init__.py
$ v/bin/python -m unittest discover toplevel.secondlevel
Hi from test_something.py
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
如何使 unittest 与 __init__-less 包一起正常工作?
解决方案
__init__.py
您不应该在常规包装中省略。
命名空间包不是常规包。在常规包中省略__init__.py
是滥用 PEP 420。 unittest 和其他工具不支持这种滥用。
推荐阅读
- firebase - 获取firebase函数实例ID?
- xaml - Xamarin.Forms:如何在样式中设置“GestureRecognizers”
- jquery - 隐藏前一个表并在 jQuery 中单击时显示新表
- angular - 如何在点击时在 PrimeNg 的 p 日历中打开特定的年份和月份
- html - 使用 sed 删除 html 表格列
- javascript - 将 NodeJS MySql 与 React 应用程序集成
- docker - thajeztah/pgadmin4 到本地安装的 postgresql
- java - 将格式错误的 json 数组字符串转换为 Java 对象
- python - Python tkinter - 画布的滚动条切断框架内容
- c++ - 我如何能够访问派生类私有方法?