这是我的目录树:
- » 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)@H_301_17@>我的测试用例扩展了unittest.TestCase@H_301_17@> abc_backend和abc_backend / tests目录有一个(空)__ init__.py@H_301_17@>所有测试模块都是可导入的(见下文)@H_301_17@> unittest discover发现测试,但是相对导入存在问题(见下文)@H_301_17@>鼻子能够发现和运行测试,没有问题
我想了解:
>为什么我需要将发现传递给unittest以强制它发现测试?如果没有discover子命令,unittest会做什么? (我认为unittest默认测试发现).根据documentation:
python -m unittest is the equivalent of python -m unittest 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
unittest discover有相对进口的问题
如果我从顶部目录运行它:
- 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",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",in <module>
- from .. import init
- SystemError: Parent module '' not loaded,cannot perform relative import
解决方法
相对进口问题
相对进口存在问题的原因是由于@H_301_17@调用的细节你真的不导入abc_backend包.
首先,我们来看看
- top» python3 -m unittest discover abc_backend
当你从那个顶部运行测试时,abc_backend就不会被导入.@H_301_17@这是因为/ home / user / top / abc_backend被添加到sys.path中@H_301_17@of / 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@H_301_17@dir不包含abc_backend包.这也可以解决
- abc_backend» python3 -m unittest discover tests -t ../
这将正确地将/ home / user / top dir(双关语)放入sys.path.
-t(或–top-level-directory)选项设置顶级目录@H_301_17@项目和默认启动目录(默认为.).@H_301_17@所以,sys.path中的内容很重要,因为它会影响导入@H_301_17@影响测试加载,因为发现使用导入机器加载测试.
-m unittest和-m unittest发现之间的差异
当你这样做
- top» python3 -m unittest abc_backend
实际上你正在运行unittest / __ main__.py文件.那里@H_301_17@调用main(module = None),最终你会得到@H_301_17@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不包含任何测试用例,@H_301_17@isinstance(obj,type)和issubclass(obj,case.TestCase)返回@H_301_17@所有模块成员都为假(因此测试为空).
要使这种特殊的调用方式发挥作用,您必须这样做@H_301_17@人们通常在发现前的时间做了什么(除了非stdlib@H_301_17@框架):从测试模块手动导入案例(或@H_301_17@也许根据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’,使用loadTestsFromNames,它在某个时刻调用loadTestsFromModule,并且没有找到任何测试.这就是unittest / main.py中的方式.