相比較於unittest,nose這類測試類庫,mock給我的感覺是完全不一樣的。剛開始看mock是因為openstack中的測試用到了它,翻閱其文件時候完全不清楚他是幹嘛的。直到看到了 這篇文章,才發現mock可以解決我很多實際的問題。這裡小秦就記錄下mock的實際使用場景的乙個例子,方便和我之前有同樣疑問的人能快速的理解其價值。
另外,強烈推薦看下這個文章,他寫的比我下面要寫的詳細的多。同時mock的官方文件也是強烈推薦值得一看的。
首先說下mock是幹什麼的。在一些測試用例中,測試會的依賴一些外部資源,這些資源一般通過封裝的類或方法進行訪問。比如我有個方法是刪除一台虛擬機器,然後根據刪除所消耗的時間判定是否需要再次建立虛擬機器:
def
recreate_vm
(): delete_used_time = vmutil.delete_vm(***) #刪除一台vm,測試的時候我們知道目前的測試資源刪除一台虛擬機器耗時肯定大於100秒
******...... #這裡是其它的一些邏輯**
if delete_used_time > 100:
vmutil.create_vm(delete_used_time) #如果耗時大於100,則重新建立vm,並且將這個引數傳入
#如果**執行到這邊,那麼就ok
print
'ok'
問題來了,虛擬機器的建立和刪除是比較耗時的,有時候可能還需要花錢,對於軟體開發測試來說,每次測試都跑這麼一段**代價很大。那怎麼才能判斷recreate_vm這個方法是不是工作正常呢?我們可以假設vmutil這個方法是完全ok的,可以信任的,所以我們要測試的其實是我們的『******…… 』這段邏輯,以及最後**是否執行到了『vmutil.create_vm(delete_used_time)』並且是否正確傳入了引數。因此我們可以試著用下面的例子替代:
def
__delete_vm
(***):
return
500def
__create_vm
(***):
pass
vmutil.delete_vm = __delete_vm
vmutil.create_vm = __create_vm
defrecreate_vm
():delete_used_time = vmutil.delete_vm(***)
******...... #這裡是其它的一些邏輯**
if delete_used_time > 100:
vmutil.create_vm(delete_used_time)
print
'ok'
deftest_recreate_vm
():recreate_vm()
此時再跑這段**,很快速的就能知道**是不是執行到了if中(如果列印ok那麼就是執行到了if中)。這個例子其實就是一種mock,在外部測試資源比較昂貴的情況下,如果其和我們要真正測試的**邏輯無關,那麼通過某種仿造的方式取代外部測試資源的呼叫,從而實現我們對真正要測試的邏輯**的測試。但這裡有個問題,如果原來的測試方法沒有print 『ok』這一行,我們怎麼知道**執行到了if中呢?另外我們怎麼知道在******這段邏輯**執行完後,我們的delete_used_time是否還是vmutil.delete_vm返回的那個值呢?這個時候就可以用mock了。
用mock這個模組的話上面的例子可以寫成:
def
recreate_vm
():delete_used_time = vmutil.delete_vm(***)
******...... #這裡是其它的一些邏輯**
if delete_used_time > 100:
vmutil.create_vm(delete_used_time)
print
'ok'
@mock.patch.object(vmutil, 'delete_vm')
@mock.patch.object(vmutil, 'create_vm')
deftest_recreate_vm
(create_vm_mock, delete_vm_mock):
delete_vm_mock.return_value = 500
#這行**保證vmutil.delete_vm的呼叫返回500
recreate_vm()
vmutil.create_vm.assert_called_once_with(500) #這行**保證我們的if中的create_vm會的被呼叫,並且保證我們的delete_used_time沒有因為***xx的邏輯而改變
這就是mock的乙個作用:在外部資源很昂貴,或者不大容易知道測試**的執行結果的時候,可以自動化的進行測試用例的測試。小秦個人覺得assert_called_once_with這類方法給我的感受是最新鮮的,delete_vm_mock.return_value = 500通過上面的例子其實可以直接實現,但是要判斷**是否執行到if以及create_vm是否正確被呼叫這個,用mock真的是很方便。
def
operation_on_db
(): name = db.exec_sql('select name from *** limit 1')
parsed_name = do_sth_on_name(name) #應該得到name * 2
age = db.exec_sql('select age from yyy limit 1')
parsed_age = do_sth_on_age(age) #應該得到age + 1
******...... #一些邏輯**
return
' - '.format(name=parsed_name, age=parsed_age)
通過用mock,我們可以很容易的在沒有db的情況下進行測試:
@mock.patch.object(db, 'exec_sql')
deftest_operation_on_db
(exec_sql_mock):
exec_sql_mock.side_effect = ['name_***', 23]
ret = operation_on_db()
assert ret == 'name_***name_*** - 24'
Nginx防hashdos模組使用幫助
wget no check certificate mv master nginx hashdos.zip unzip nginx hashdos.zip 編譯安裝 配置注意事項 在http段,增加如下 hashdos on body max count 1000 在各自的location段,要按照...
使用re模組定位網頁資訊資料位置 Python
儘管我們使用urllib.request可以獲取到網頁的所有資料,但是要獲取我們想要的資料還需要進一步進行資料處理。本篇主要介紹如何使用python的re模組進行資料定位及獲取。1 目標網頁原始碼觀察 2 確定資料定位方法 ul lb worlds flt site gfkdbkzsxxw reso...
使用OS模組來獲取檔案路徑
python os模組包含普遍的作業系統功能。如果你希望你的程式能夠與平台無關的話,這個模組是尤為重要的。os.getcwd 函式得到當前工作目錄,即當前python指令碼工作的目錄路徑。os.listdir 返回指定目錄下的所有檔案和目錄名。os.remove 刪除乙個檔案。os.path.spl...