这是我的目录树:
» tree abc_backend
abc_backend/
├── backend_main.py
├── FundDatabase.db
├── healthcheck.py
├── __init__.py
├── init.py
├── portfolio.py
├── private.py
├── __pycache__
├── questionnaire.py
├── recurring.py
├── registration.py
├── tests
│ ├── config.py
│ ├── __init__.py
│ ├── __pycache__
│ ├── test_backend.py
│ ├── test_healthcheck.py
│ └── test_private.py
├── trading.py
├── Users.db
├── VERSION
└── visualisation.py
unittest
无法找到任何内容:
top » python -m unittest abc_backend
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
甚至不在abc_backend
内:
abc_backend » python -m unittest tests
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
我已经验证过:
test_whatever
)unittest.TestCase
abc_backend
和abc_backend/tests
目录有(空)__init__.py
unittest discover
找到测试,但是相对导入存在问题(见下文)nose
能够发现并运行测试,没有问题我想了解:
discover
传递给unittest
以强制它发现测试? unittest
没有discover
子命令会做什么? (我认为unittest默认测试发现)。根据{{3}}:python -m unittest相当于python -m unittest discover
discover
子命令),为什么我有导入问题?» python
Python 3.4.3 (default, Oct 14 2015, 20:28:29)
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import abc_backend.tests
>>> import abc_backend.tests.test_private
>>> import abc_backend.tests.test_healthcheck
>>> import abc_backend.tests.test_backend
如果我从顶部目录运行它:
top » python -m unittest discover abc_backend
======================================================================
ERROR: tests.test_private (unittest.loader.ModuleImportFailure)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3.4/unittest/case.py", line 58, in testPartExecutor
yield
File "/usr/lib/python3.4/unittest/case.py", line 577, in run
testMethod()
File "/usr/lib/python3.4/unittest/loader.py", line 32, in testFailure
raise exception
ImportError: Failed to import test module: tests.test_private
Traceback (most recent call last):
File "/usr/lib/python3.4/unittest/loader.py", line 312, in _find_tests
module = self._get_module_from_name(name)
File "/usr/lib/python3.4/unittest/loader.py", line 290, in _get_module_from_name
__import__(name)
File "/foo/bar/abc_backend/tests/test_private.py", line 6, in <module>
from .. import init
ValueError: attempted relative import beyond top-level package
如果我在abc_backend
内运行它:
abc_backend » python -m unittest discover tests
======================================================================
ERROR: test_private (unittest.loader.ModuleImportFailure)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3.4/unittest/case.py", line 58, in testPartExecutor
yield
File "/usr/lib/python3.4/unittest/case.py", line 577, in run
testMethod()
File "/usr/lib/python3.4/unittest/loader.py", line 32, in testFailure
raise exception
ImportError: Failed to import test module: test_private
Traceback (most recent call last):
File "/usr/lib/python3.4/unittest/loader.py", line 312, in _find_tests
module = self._get_module_from_name(name)
File "/usr/lib/python3.4/unittest/loader.py", line 290, in _get_module_from_name
__import__(name)
File "/foo/bar/abc_backend/tests/test_private.py", line 6, in <module>
from .. import init
SystemError: Parent module '' not loaded, cannot perform relative import
答案 0 :(得分:8)
我重现了CPython 3.5的所有问题,所以我的回答应该是 与3.4和3.5相关。
相对进口存在问题的原因是由于
您实际上没有导入abc_backend
包的调用细节。
首先,我们来看看
top» python3 -m unittest discover abc_backend
当您从那个顶部运行测试时,abc_backend
就不会被导入。
这是因为/home/user/top/abc_backend
被添加到sys.path中
/home/user/top
。要解决此问题,请执行
top» python3 -m unittest discover abc_backend -t .
现在,关于in-abc_backend调用。当你这样做
abc_backend» python3 -m unittest discover tests
abc_backend
不可导入,因为/home/user/top/abc_backend/tests
dir不包含abc_backend
包。这也可以通过
abc_backend» python3 -m unittest discover tests -t ../
将/home/user/top
dir(双关语)正确地放入sys.path
。
-t
(或--top-level-directory
)选项设置顶级目录
项目和默认启动目录(默认为.
)。
因此,sys.path
中的内容很重要,因为这会影响进口
影响测试加载,因为发现使用导入机器加载测试。
-m unittest
和-m unittest discover
当你这样做时
top» python3 -m unittest abc_backend
实际上您正在运行unittest/__main__.py
文件。那里
调用main(module=None)
,最终你会到达
{/ 1}}
loadTestsFromModule
由于tests = []
for name in dir(module):
obj = getattr(module, name)
if isinstance(obj, type) and issubclass(obj, case.TestCase):
tests.append(self.loadTestsFromTestCase(obj))
不包含任何测试用例,
abc_backend/__init__.py
返回
所有模块成员都isinstance(obj, type) and issubclass(obj, case.TestCase)
(因此False
为空)。
要使这种特殊的调用方式发挥作用,你必须这样做
人们通常在tests
之前做过的事情(除了非stdlib之外)
框架):从测试模块手动导入案例(或
也许根据discover
协议构建测试套件。
那么,
load_tests
不同?
基本上,差异可以表示为以下条件:
top» python3 -m unittest discover abc_backend
当if len(argv) > 1 and argv[1].lower() == 'discover':
# -m unittest discover
loader.discover(...)
else:
# -m unittest
loader.loadTestsFromNames(...)
为argv
时,
使用实际发现机制。当['python3 -m unittest', 'discover', 'abc_backend']
为argv
时,
使用['python3 -m unittest', 'abc_backend']
,在某个时刻调用loadTestsFromNames
,并且未找到任何测试。
这就是loadTestsFromModule
中的事情。
答案 1 :(得分:0)
我今天遇到了类似的问题,实际上解决方案是用Python API document编写的:
如果找到包(包含名为 init .py的文件的目录),将检查包的load_tests函数。如果存在,那么它将被称为package.load_tests(loader,tests,pattern)。测试发现需要注意确保在调用期间仅检查一次包测试,即使load_tests函数本身调用loader.discover也是如此。
因此,您需要做的就是编写一个load_tests函数并在__init __注册您的TestCase类.py