不是从文件加载python模块

时间:2011-01-14 00:28:51

标签: python unit-testing module import

我在库中有一些python代码试图从一个模块加载一个简单的值,该模块将存在于使用该库的应用程序

from somemodule import simplevalue

通常,使用该库的应用程序将具有模块文件,一切正常。但是,在此库的单元测试中,模块不存在。我知道我可以创建一个临时文件并在运行时将该文件添加到我的路径中,但我很好奇是否有一种方法可以在python中将某些内容加载到内存中以允许上述导入工作。

这更像是一种好奇心,说“将模块添加到测试路径”没有用处:P

3 个答案:

答案 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()