[英]pytest failed to import local module (importing built-in module instead)
I have the following Python 2.7 simplified project structure:我有以下 Python 2.7 简化项目结构:
project/
├── libs/
| └── zipfile.py
├── tests/
| ├── __init__.py
| └── test_hello.py
├── hello.py
└── main.py
I want this project to use the patched version of one of Python built-in modules (which in this example is zipfile
) located in libs
.我希望该项目使用位于
libs
的 Python 内置模块之一(在本例中为zipfile
)的修补版本。 Note that this is an external requirement, and I cannot change the project structure.请注意,这是外部要求,我无法更改项目结构。
Below are the simplified implementation of each file:下面是每个文件的简化实现:
libs/zipfile.py库/zipfile.py
def is_zipfile(filename):
return "Patched zipfile called"
tests/test_hello.py测试/test_hello.py
from hello import hello
def test_hello():
assert hello() == "Patched zipfile called"
hello.py你好.py
import os
import sys
libs_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "libs"))
if libs_path not in sys.path:
sys.path.insert(1, libs_path)
import zipfile
def hello():
print(zipfile.__file__) # to check which zipfile module is imported
result = zipfile.is_zipfile("some_path")
return result
main.py主文件
from hello import hello
def main():
print(hello())
if __name__ == "__main__":
main()
When running the program directly ( python main.py
), I got the expected result:直接运行程序(
python main.py
)时,得到了预期的结果:
/home/project/libs/zipfile.pyc
Patched zipfile called
However, when running pytest with project
as the working directory ( pytest -s
), it failed:但是,当以
project
作为工作目录( pytest -s
)运行 pytest 时,它失败了:
/usr/lib/python2.7/zipfile.pyc
================================== FAILURES ===================================
_________________________________ test_hello __________________________________
def test_hello():
> assert hello() == "Patched zipfile called"
E assert False == 'Patched zipfile called'
E + where False = hello()
tests/test_hello.py:4: AssertionError
========================== 1 failed in 0.13 seconds ===========================
I've tried a couple solutions presented in this SO post , such as running python -m pytest
, but none has worked for me.我已经尝试了这篇 SO post 中提出的几个解决方案,例如运行
python -m pytest
,但没有一个对我python -m pytest
。 Is there a way to successfully run this test in a non-hacky way?有没有办法以非hacky的方式成功运行这个测试?
The reason your patched zipfile
module is not being imported is it has already been imported before the test is started (likely by pytest or one of its dependencies)未导入修补的
zipfile
模块的原因是它在测试开始之前已经导入(可能是 pytest 或其依赖项之一)
I verified this by putting this at the top of hello.py
:我通过将其放在
hello.py
的顶部来验证这hello.py
:
if 'zipfile' in sys.modules:
raise AssertionError('zipfile already imported')
I then get:然后我得到:
$ ./venv/bin/python -mpytest tests
============================= test session starts ==============================
platform linux -- Python 3.6.7, pytest-4.3.0, py-1.8.0, pluggy-0.9.0
rootdir: /tmp/x, inifile:
collected 0 items / 1 errors
==================================== ERRORS ====================================
_____________________ ERROR collecting tests/test_hello.py _____________________
tests/test_hello.py:1: in <module>
from hello import hello
hello.py:5: in <module>
raise AssertionError('zipfile already imported')
E AssertionError: zipfile already imported
!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!
=========================== 1 error in 0.14 seconds ============================
You could delete zipfile
from sys.modules
and then perhaps your copy would be the only one imported:您可以从
sys.modules
删除zipfile
,然后也许您的副本将是唯一导入的:
sys.modules.pop('zipfile', None)
That said, all of this seems like potentially a bad idea as anyone who has already imported that module will have access to the old zipfile
and stubbing out stdlib implementation has high potential to break third party libraries which don't expect that.也就是说,所有这些似乎都可能是一个坏主意,因为任何已经导入该模块的人都可以访问旧的
zipfile
并且剔除 stdlib 实现很有可能破坏不期望的第三方库。
You might have ~slightly better luck by patching out individual methods on the zipfile
module directly (using something like mock.patch.object(zipfile, 'fn', ...)
通过直接修补
zipfile
模块上的各个方法(使用类似mock.patch.object(zipfile, 'fn', ...)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.