python - unittest 无法发现/运行测试

标签 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 以强制它发现测试?如果没有 discover 子命令,unittest 会做什么? (我认为 unittest 默认情况下会进行测试发现)。根据documentation :

python -m unittest is the equivalent of 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

最佳答案

我用 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 目录(双关语)放入 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) 被调用,最终你得到 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) 和 issubclass(obj, case.TestCase) 返回 False 对于所有模块成员(因此 tests 为空)。

要使这种特殊的调用方式起作用,您必须这样做 人们在 discover 之前通常做的事情(除了非标准库 框架):从测试模块手动导入案例(或 也许根据load_tests 协议(protocol)构建测试套件)。

那么,如何

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,但没有找到任何测试。 这就是 unittest/main.py 中的内容。

关于python - unittest 无法发现/运行测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35034664/

相关文章:

node.js - 即使调用计数为 1,Sinon spy 断言也会失败

python - 为什么安装了opencv3却无法导入?

python - 创建列以跟踪另一列中的缺失值

python - 更快地计算特殊相关距离矩阵

java - 测试和继承问题

python - AttributeError : module object has no attribute "Series". 代码在 iPython 中有效

python - 如何在同一个项目中使用 Streamlit 和 Pytest

python - 无法使用 python 和 beautifulsoup 抓取网页中的某些 href

javascript - 为什么我的 WebSocket 会自动关闭?

.net - 使用 NCrunch 运行测试时如何查看控制台输出?