【问题标题】:How to solve ImportError with pytest如何使用 pytest 解决 ImportError
【发布时间】:2022-01-03 18:49:12
【问题描述】:

Therewerealready 有关此主题的问题。有时程序员会在某些地方放一些__init__.py,通常说应该使用绝对路径。但是,我不让它在这里工作:

如何从包中导入类,以便在 pytest 中运行测试并使用代码?

目前我得到 pytest 或通过各自运行的代码。

我的示例项目结构是

.
├── testingonly
│   ├── cli.py
│   ├── __init__.py
│   └── testingonly.py
└── tests
    ├── __init__.py
    └── test_testingonly.py

__init__.py 在这两种情况下都是一个空文件。

$ cat testingonly/cli.py
"""Console script for testingonly."""
from testingonly import Tester

def main(args=None):
    """Console script for testingonly."""
    te = Tester()
    return 0

main()
$ cat testingonly/testingonly.py
"""Main module."""
class Tester():
    def __init__(self):
        print("Hello")

这给出了 - 正如预期的那样:

$ python3 testingonly/cli.py
Hello

但是,尝试对此进行测试失败:

$ pytest
========================================================= test session starts =========================================================
platform linux -- Python 3.7.3, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /home/stefan/Development/testingonly
collected 0 items / 1 error                                                                                                           

=============================================================== ERRORS ================================================================
_____________________________________________ ERROR collecting tests/test_testingonly.py ______________________________________________
ImportError while importing test module '/home/stefan/Development/testingonly/tests/test_testingonly.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.7/importlib/__init__.py:127: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
tests/test_testingonly.py:10: in <module>
    from testingonly import cli
testingonly/cli.py:2: in <module>
    from testingonly import Tester
E   ImportError: cannot import name 'Tester' from 'testingonly' (/home/stefan/Development/testingonly/testingonly/__init__.py)

testingonly/testingonly.py 重命名为testingonly/mytest.py 并更改test_testingonly.py(来自testingonly import mytest)和cli.py(来自mytest import Tester)中的导入

$ pytest
========================================================= test session starts =========================================================
platform linux -- Python 3.7.3, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /home/stefan/Development/testingonly
collected 0 items / 1 error                                                                                                           

=============================================================== ERRORS ================================================================
_____________________________________________ ERROR collecting tests/test_testingonly.py ______________________________________________
ImportError while importing test module '/home/stefan/Development/testingonly/tests/test_testingonly.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.7/importlib/__init__.py:127: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
tests/test_testingonly.py:10: in <module>
    from testingonly import cli
testingonly/cli.py:2: in <module>
    from mytest import Tester
E   ModuleNotFoundError: No module named 'mytest'
======================================================= short test summary info =======================================================
ERROR tests/test_testingonly.py
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
========================================================== 1 error in 0.37s ===========================================================
$ python3 testingonly/cli.py
Hello

另一个建议的解决方案是重命名为 mytest.py 让测试通过,但在 cli.py 中使用 from testingonly.mytest import Tester 会产生 NameNotFound 错误。

$ python3 testingonly/cli.py 
Traceback (most recent call last):
  File "testingonly/cli.py", line 2, in <module>
    from testingonly.mytest import Tester
ModuleNotFoundError: No module named 'testingonly'
$ pytest
========================================================= test session starts =========================================================
platform linux -- Python 3.7.3, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /home/stefan/Development/testingonly
collected 1 item                                                                                                                      

tests/test_testingonly.py .                                                                                                     [100%]

========================================================== 1 passed in 0.12s ==========================================================

【问题讨论】:

  • 这个关于相关 Python Imports 的答案也可能会有所帮助stackoverflow.com/questions/2183205/…
  • 首先from testingonly import Tester是错误的。 Tester 类在模块中定义为 qualname testingonly.testingonly,因为它没有在 testingonly/__init__.py 中导出,因此导入将无法解析。它在testingonly.cli 中有效,只是因为它与testingonly.testingonly 处于同一级别,并且具有相对导入作为后备。要验证,请在根目录中创建一些 foo.py 并使用一行 from testingonly import Tester 并运行 python foo.py - 您将得到相同的错误。
  • 其次,pytest 默认情况下不会将项目根目录添加到sys.path - 您应该自己处理。运行python -m pytest,或者将一个名为conftest.py 的空文件添加到项目根目录。查看PATH issue with pytest 'ImportError: No module named YadaYadaYada' 中的答案了解更多详情。
  • 啊,from testingonly import Tester 的正确替换当然是from testingonly.testingonly import Tester

标签: python pytest python-import


【解决方案1】:

自命名模块testingonly 和文件名testingonly.py 可能会导致模块导入方式出现一些问题。

tests 目录中删除__init__.pyRef this answer .

尝试将testingonly.py 重命名为mytest.py,然后再次将其导入您的项目。

cli.py中,应该是:

from testingonly.mytest import Tester

然后为你的测试文件test_testingonly.py:

from testingonly.mytest import Tester

你的test_testingonly.py 文件应该是这样的:

import pytest
from testingonly.mytest import Tester  # Import the Tester Class


def test_tester(capsys):
    # Create the Tester Class
    te = Tester()
    # Get the captured output
    captured = capsys.readouterr()
    # Assert that the capture output is tested
    assert captured.out == "Hello\n"

最后,运行你的测试:

python -m pytest tests/

这是一个基于您的代码的完整工作示例:https://github.com/cdesch/testingonly

【讨论】:

  • 我用from mytest import Tester 尝试更新了我的问题。另一个给出了 pytest 的错误。即将添加...
  • 你让它工作了吗?我看到你接受了答案。
  • 是的,它成功了!谢谢。
  • 对不起,它没有成功。目前这总是发生在我身上,我对我测试的内容感到困惑......重写问题。
  • 我在 github 上发布了一个适用于您的代码的示例。我还在项目中添加了一个MyCalc 类,以显示另一个正在测试的类。这是代码:github.com/cdesch/testingonly
猜你喜欢
  • 2012-11-18
  • 2021-04-14
  • 1970-01-01
  • 2017-10-27
  • 1970-01-01
  • 2021-12-09
  • 1970-01-01
  • 2015-03-07
  • 2022-01-11
相关资源
最近更新 更多