2011-01-14 93 views
3

我有在尝试从会为使用这个库负载Python模块无法从文件

from somemodule import simplevalue 

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

这更多的是好奇,称“模块添加到您的测试路径”是无益的:P

回答

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正在使用中。

+0

感谢托马斯,完美。是的,我同意,这不是我想写的代码模式。但是对于这个测试场景它可以正常工作。 – smullins 2011-01-14 01:05:16

+0

@smullins:不客气。这个警告对于匿名未来的读者来说比你更多,因为你听起来像你知道你在做什么。 – 2011-01-14 01:25:30

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 

然后你可以注入一个值你的单元测试:

#!/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() 
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