unittest无法发现/运行测试

时间:2016-01-27 10:23:07

标签: python unit-testing python-import nose python-unittest

some related个问题,但都不适用。

这是我的目录树:

» 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_backendabc_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

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", 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

2 个答案:

答案 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