如何用pytest解决ImportError

How to solve ImportError with pytest

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

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

目前我得到 pytest 或代码通过相应的 运行ning.

我的示例项目结构是

.
├── 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 中的导入(from testingonly import mytest)和 cli.py (from 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 ==========================================================

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

tests 目录中删除 __init__.py

尝试将 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