python mock
如何不靠耐心測試
通常,我們編寫(xiě)的軟件會(huì )直接與那些我們稱(chēng)之為“骯臟的”服務(wù)交互。通俗地說(shuō),服務(wù)對我們的應用來(lái)說(shuō)是至關(guān)重要的,它們之間的交互是我們設計好的,但這會(huì )帶來(lái)我們不希望的副作用——就是那些在我們自己測試的時(shí)候不希望的功能。
比如,可能我們正在寫(xiě)一個(gè)社交軟件并且想測試一下“發(fā)布到Facebook的功能”,但是我們不希望每次運行測試集的時(shí)候都發(fā)布到Facebook上。
Python的unittest庫中有一個(gè)子包叫unittest.mock——或者你把它聲明成一個(gè)依賴(lài),簡(jiǎn)化為mock——這個(gè)模塊提供了非常強大并且有用的方法,通過(guò)它們可以模擬或者屏敝掉這些不受我們希望的方面。
注意:mock是最近收錄在Python 3.3標準庫中的;之前發(fā)布的版本必須通過(guò) PyPI下載Mock庫。
恐懼系統調用
再舉一個(gè)例子,考慮系統調用,我們將在余下的文章中討論它們。不難發(fā)現,這些都可以考慮使用模擬:無(wú)論你是想寫(xiě)一個(gè)腳本彈出一個(gè)CD驅動(dòng),或者是一個(gè)web服務(wù)用來(lái)刪除/tmp目錄下的緩存文件,或者是一個(gè)socket服務(wù)來(lái)綁定一個(gè)TCP端口,這些調用都是在你單元測試的時(shí)候是不被希望的方面。
作為一個(gè)開(kāi)發(fā)人員,你更關(guān)心你的庫是不是成功的調用了系統函數來(lái)彈出CD,而不是體驗每次測試的時(shí)候CD托盤(pán)都打開(kāi)。
作為一個(gè)開(kāi)發(fā)人員,你更關(guān)心你的庫是不是成功調用了系統函數來(lái)彈出CD(帶著(zhù)正確的參數等)。而不是體驗每次測試的時(shí)候CD托盤(pán)都打開(kāi)(或者更糟,很多次,當一個(gè)單元測試運行的時(shí)候,很多測試點(diǎn)都涉及到了彈出代碼)。
同樣地,保持你的單元測試效率和性能意味著(zhù)要還要保留一些自動(dòng)化測試之外的“緩慢代碼”,比如文件系統和網(wǎng)絡(luò )的訪(fǎng)問(wèn)。
對于我們的第一個(gè)例子,我們要重構一個(gè)從原始到使用mock的一個(gè)標準Python測試用例。我們將會(huì )證明如何用mock寫(xiě)一個(gè)測試用例使我們的測試更智能、更快,并且能暴露更多關(guān)于我們的軟件工作的問(wèn)題。
一個(gè)簡(jiǎn)單的刪除功能
有時(shí),我們需要從文件系統中刪除文件,因此,我們可以寫(xiě)這樣的一個(gè)函數在Python中,這個(gè)函數將使它更容易成為我們的腳本去完成這件事情。
1 2 3 4 5 6 |
#!/usr/bin/env python # -*- coding: utf-8 -*- import os def rm(filename): os.remove(filename) |
很明顯,在這個(gè)時(shí)間點(diǎn)上,我們的rm方法不提供比基本os.remove方法更多的功能,但我們的代碼將會(huì )有所改進(jìn),允許我們在這里添加更多的功能。
讓我們寫(xiě)一個(gè)傳統的測試用例,即,不用模擬測試:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#!/usr/bin/env python # -*- coding: utf-8 -*- from mymodule import rm import os.path import tempfile import unittestclass RmTestCase(unittest.TestCase): tmpfilepath = os.path.join(tempfile.gettempdir(), "tmp-testfile") def setUp(self): with open(self.tmpfilepath, "wb") as f: f.write("Delete me!") def test_rm(self): # remove the file rm(self.tmpfilepath) # test that it was actually removed self.assertFalse(os.path.isfile(self.tempfile), "Failed to remove the file.") |
原文轉自:http://www.diggerplus.org/archives/2704