简体   繁体   English

如何导入和猴子补丁 Python 模块,该模块位于与测试不同的 package 中?

[英]How do I import and monkey patch a Python module that is in a different package from the tests?

My source tree looks like this:我的源代码树如下所示:

.
├── README.md
├── app
│   ├── __init__.py
│   ├── flask_main.py
│   └── lib.py
├── run_endpoint_check_tests.sh
├── run_flask.sh
├── run_unit_tests.sh
└── tests
    ├── endpoint_checks.py
    └── test_lib.py

flask_main.py (naturally) imports lib.py like this: import roku_lib flask_main.py (自然)像这样import roku_lib lib.py

But to get test_lib.py to import lib.py , I need to do this:但是要让test_lib.py导入lib.py ,我需要这样做:

sys.path.append("app")
from app import lib

And I run the unit tests using this (in run_unit_tests.sh ):我使用它运行单元测试(在run_unit_tests.sh中):

#!/bin/sh
python -m pytest

(I haven't been able to get running pytest to work, which I guess makes sense after reading https://docs.pytest.org/en/latest/goodpractices.html#tests-outside-application-code .) (我一直无法运行pytest工作,我认为在阅读https://docs.pytest.org/en/

This unit test fails though:这个单元测试失败了:

def test_load_from_s3(mocker, monkeypatch):
    x_mock = mocker.Mock()
    return_mock = mocker.Mock()
    x_mock.Object = mocker.Mock(return_value=return_mock)
    monkeypatch.setattr(lib, 'get_x', lambda: x_mock)

    y = lib.get_x()

    x_mock.Object.assert_called_once()

    ...

I think it fails because calling lib.get_x() results in it importing it's own (copy of?) lib that is not monkey patched.我认为它失败了,因为调用 lib.get_x() 会导致它导入它自己的(副本?)没有猴子补丁的库。

The same test works when the source tree looks like this:当源代码树如下所示时,相同的测试工作:

    .
    ├── README.md
    ├── __init__.py
    ├── lib.py
    ├── uses_lib.py
    └── tests
        ├── __init__.py
        ├── test_uses_lib.py
        └── test_lib.py

And sys.path.append("app") & from app import lib are unnecessary.并且sys.path.append("app") & from app import lib是不必要的。

But for historical reasons, I must keep flask_main.py in the app package.但由于历史原因,我必须flask_main.py保留在应用程序 package 中。 I could move lib.py into a separate package though, if that solves my problem.不过,如果这样可以解决我的问题,我可以将lib.py移动到单独的 package 中。

So finally my questions...所以最后我的问题...

How do I fix the imports or monkey patching code (or both) so the monkey patch works?如何修复导入或猴子补丁代码(或两者)以便猴子补丁工作?

Is it possible (by adding extra empty __init__.py files where missing, perhaps?) to get the import to work in test_lib.py without sys.path.append("app") ?是否有可能(通过在缺少的地方添加额外的空__init__.py文件,也许?)在没有sys.path.append("app")的情况下让导入在test_lib.py中工作?

I moved lib.py into a libs directory:我将lib.py移动到libs目录中:

.
├── README.md
├── app
│   ├── __init__.py
│   └── flask_main.py
├── libs
│   ├── __init__.py
│   ├── lib_a.py
│   └── lib_b.py
├── run_endpoint_check_tests.sh
├── run_unit_tests.sh
└── tests
    ├── endpoint_checks.py
    ├── test_lib_a.py
    └── test_lib_b.py

(And I split lib.py into lib_a.py and lib_b.py . lib_b.py imports lib_a .) (我将lib.py拆分为lib_a.pylib_b.pylib_b.py导入lib_a 。)

And I import lib_a.py and lib_b.py the same way in flask_main.py , lib_b.py , and test_lib_a.py & test_lib_b.py :我在flask_main.pylib_b.pytest_lib_a.pylib_b.py中以相同的方式导入lib_a.pytest_lib_b.py

sys.path.append("..")
from libs import lib_a
from libs import lib_b

Now flask_main.py runs properly and the unit tests pass (with the monkey patch assertions not failing).现在flask_main.py运行正常并且单元测试通过(猴子补丁断言没有失败)。

Note I deleted run_flask.sh since I now have to run flask_main.py with the app directory as the cwd.注意我删除run_flask.sh ,因为我现在必须以app目录作为 cwd 运行flask_main.py

Note also I still have to run python -m pytest ——running pytest leads to ModuleNotFoundErrors.另请注意,我仍然必须运行python -m pytest ——运行pytest会导致 ModuleNotFoundErrors。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM