在Python中使用可选导入进行测试
我有一个可以使用两个模块的库;一个速度很快,但仅在Linux和macOS上可用,另一个速度较慢,但它是多平台的。我的解决方案是使库与两者兼容,并具有如下内容:在Python中使用可选导入进行测试,python,python-3.x,unit-testing,testing,python-import,Python,Python 3.x,Unit Testing,Testing,Python Import,我有一个可以使用两个模块的库;一个速度很快,但仅在Linux和macOS上可用,另一个速度较慢,但它是多平台的。我的解决方案是使库与两者兼容,并具有如下内容: 试试看: 导入快速模块 除恐怖外: 导入慢模块 现在,我想比较使用两个模块时库的计时。在安装了两个模块的环境中,有没有办法在不更改源代码的情况下屏蔽fastmodule,从而使用slowmodule 您可以编写自己的导入程序并注册它(注意,这是特定于Python 3的,Python 2为此提供了另一个API): 这里,sut是您正在测试
试试看:
导入快速模块
除恐怖外:
导入慢模块
现在,我想比较使用两个模块时库的计时。在安装了两个模块的环境中,有没有办法在不更改源代码的情况下屏蔽
fastmodule
,从而使用slowmodule
您可以编写自己的导入程序并注册它(注意,这是特定于Python 3的,Python 2为此提供了另一个API):
这里,sut
是您正在测试的模块,您必须重新加载它才能更改行为。我为可读性添加了decorators,但这可以通过一些函数或在测试设置中完成
如果使用慢速版本,
fastmodule
将在导入时引发ImportError
,而将使用slowmodule
。在“快速”的情况下,一切正常。谢谢你的技巧,但这似乎根本没有被调用……事实上,如果我之前没有加载我的包,这一切都会很好地工作。我尝试使用importlib.reload
,但没有成功。有没有一种方法可以在一个脚本中实现这一点,在这个脚本中,我希望同时使用fastmodule
和slowmodule
来聚合数据?我对答案进行了一些扩展,以展示如何在测试中同时使用slowmodule
和fastmodule
。诚然,这不是最好的代码,但它应该可以工作(我用一些伪代码测试了它)。谢谢del sys.modules['fastmodule']
是缺少的步骤!=)
import sut
import functools
import importlib
import sys
def use_slow(f):
@functools.wraps(f)
def wrapped(*args, **kwargs):
ImportRaiser.use_slow = True
if 'fastmodule' in sys.modules:
del sys.modules['fastmodule'] # otherwise it will remain cached
importlib.reload(sut)
f(*args, **kwargs)
return wrapped
def use_fast(f):
@functools.wraps(f)
def wrapped(*args, **kwargs):
ImportRaiser.use_slow = False
importlib.reload(sut)
f(*args, **kwargs)
return wrapped
class ImportRaiser:
use_slow = False
def find_spec(self, fullname, path, target=None):
if fullname == 'fastmodule':
if self.use_slow:
raise ImportError()
sys.meta_path.insert(0, ImportRaiser())
@use_fast
def test_fast():
# test code
@use_slow
def test_slow():
# test code