2011-01-14 94 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