我在库中有一些python代码试图从一个模块加载一个简单的值,该模块将存在于使用该库的应用程序
from somemodule import simplevalue
通常,使用该库的应用程序将具有模块文件,一切正常。但是,在此库的单元测试中,模块不存在。我知道我可以创建一个临时文件并在运行时将该文件添加到我的路径中,但我很好奇是否有一种方法可以在python中将某些内容加载到内存中以允许上述导入工作。
这更像是一种好奇心,说“将模块添加到测试路径”没有用处:P
答案 0 :(得分:7)
是的。使用types.ModuleType
创建新模块对象,然后将其添加到sys.modules
:
sys.modules["somename"] = types.ModuleType("somename")
然后你可以import somename
。如果需要向其中添加类或函数,请在调用测试脚本之前导入它,然后只需向其中添加函数:
def myfunc(x, y, z):
...
somename.myfunc = myfunc
不言而喻,但以防万一:这主要是学术上的好奇心。它有一些用于测试的用途,但除此之外,坚持以通常的方式导入东西。
顺便提一下,我是如何知道的:我遇到了测试中使用的技术,为非Windows系统上的_winreg
模块制作了“存根”。 Here it is正在使用中。
答案 1 :(得分:5)
没有必要创建模块。没有Python代码关心somemodule.simplevalue
是否实际上是对模块属性的引用。为此,程序需要检查somemodule
的类型。为什么要这么麻烦?
由于您只需要模块中的单个值并将其导入您自己的命名空间,因此只需定义它:
simplevalue = 42
如果您愿意,请先使用try/except
尝试导入真实模块。
try:
from somemodule import simplevalue
except ImportError:
simplevalue = 42
如果要导入整个模块但只使用一个值,则可以使用类来定义命名空间。
try:
import somemodule
except ImportError:
class somemodule(object):
simplevalue = 42
现在somemodule.simplevalue
指的是值,无论模块是否可用。
如果您希望其他也导入somemodule
的模块能够像在单元测试中那样查看伪造的类模块,那么请在以后执行此操作:
import sys
sys.modules["somemodule"] = somemodule
答案 2 :(得分:1)
您的受测系统(我的示例中为sut
)需要能够应对somemodule
可能不存在的事实,因此您可以捕获ImportError
:
#!/usr/bin/env python
try:
from somemodule import simplevalue
except ImportError, e:
if 'somemodule' in e:
'''We expect that to happen in the unittest but you should log something for when
this happens in production'''
def fn():
return simplevalue
然后你可以在unittest中注入一个值:
#!/usr/bin/env python
import unittest
import sut
class T(unittest.TestCase):
def test_fn(self):
sut.simplevalue = 42
self.assertEquals(42, sut.fn())
if __name__ == '__main__':
unittest.main()